statewire 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -80
- package/dist/client/connection.d.ts +19 -6
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +79 -40
- package/dist/client/connection.js.map +1 -1
- package/dist/client/core.d.ts +1 -0
- package/dist/client/core.d.ts.map +1 -1
- package/dist/client/core.js +5 -0
- package/dist/client/core.js.map +1 -1
- package/dist/client/session.d.ts +2 -0
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +96 -16
- package/dist/client/session.js.map +1 -1
- package/dist/host/adapter.d.ts +1 -1
- package/dist/host/adapter.d.ts.map +1 -1
- package/dist/host/adapter.js +7 -1
- package/dist/host/adapter.js.map +1 -1
- package/dist/host/host.d.ts +1 -0
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.js +45 -5
- package/dist/host/host.js.map +1 -1
- package/dist/host/http.d.ts +1 -1
- package/dist/host/http.d.ts.map +1 -1
- package/dist/host/http.js +75 -47
- package/dist/host/http.js.map +1 -1
- package/dist/host/socket.d.ts +23 -7
- package/dist/host/socket.d.ts.map +1 -1
- package/dist/host/socket.js +275 -74
- package/dist/host/socket.js.map +1 -1
- package/dist/host/work.d.ts +7 -0
- package/dist/host/work.d.ts.map +1 -0
- package/dist/host/work.js +53 -0
- package/dist/host/work.js.map +1 -0
- package/dist/host-internal.d.ts +35 -5
- package/dist/host-internal.d.ts.map +1 -1
- package/dist/host-internal.js +2 -1
- package/dist/host.d.ts +16 -3
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +2 -1
- package/dist/statewire.d.ts +11 -2
- package/dist/statewire.d.ts.map +1 -1
- package/dist/statewire.js.map +1 -1
- package/dist/transports/sse.d.ts +1 -4
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js +47 -56
- package/dist/transports/sse.js.map +1 -1
- package/dist/transports/testing.js +2 -2
- package/dist/transports/testing.js.map +1 -1
- package/dist/transports/ws.d.ts +1 -1
- package/dist/transports/ws.d.ts.map +1 -1
- package/dist/transports/ws.js +54 -41
- package/dist/transports/ws.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/wire/documents.d.ts +20 -0
- package/dist/wire/documents.d.ts.map +1 -0
- package/dist/wire/documents.js +74 -0
- package/dist/wire/documents.js.map +1 -0
- package/dist/wire/limits.d.ts +10 -0
- package/dist/wire/limits.d.ts.map +1 -0
- package/dist/wire/limits.js +11 -0
- package/dist/wire/limits.js.map +1 -0
- package/dist/wire/meta.d.ts.map +1 -1
- package/dist/wire/meta.js +1 -1
- package/dist/wire/meta.js.map +1 -1
- package/dist/wire/ops.d.ts.map +1 -1
- package/dist/wire/ops.js +1 -2
- package/dist/wire/ops.js.map +1 -1
- package/dist/wire/version.d.ts +7 -0
- package/dist/wire/version.d.ts.map +1 -0
- package/dist/wire/version.js +8 -0
- package/dist/wire/version.js.map +1 -0
- package/package.json +1 -1
- package/src/client/connection.ts +159 -52
- package/src/client/core.ts +6 -0
- package/src/client/session.ts +104 -29
- package/src/host/adapter.ts +10 -2
- package/src/host/host.ts +54 -4
- package/src/host/http.ts +132 -66
- package/src/host/socket.ts +410 -81
- package/src/host/work.ts +50 -0
- package/src/host-internal.ts +32 -4
- package/src/host.ts +18 -2
- package/src/statewire.ts +16 -2
- package/src/transports/sse.ts +60 -68
- package/src/transports/testing.ts +2 -2
- package/src/transports/ws.ts +29 -48
- package/src/types.ts +1 -0
- package/src/wire/documents.ts +109 -0
- package/src/wire/limits.ts +6 -0
- package/src/wire/meta.ts +6 -1
- package/src/wire/ops.ts +1 -2
- package/src/wire/version.ts +3 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","names":["useContext","useEffect","useState","applyOps","StatewirePath","TERMINAL","StatewireCmd","StatewireSyn","encodeParams","encodeValue","reviveResponse","reviveValue","bindCommandsHost","CommandsInvocation","CommandsListener","Statewire","StatewireClient","SessionStorageContext","createMemorySessionStore","backoff","createMethodProxy","randomId","StatewireSendError","RemoteLink","StatewireFrame","StatewireRemoteProps","WireCommand","method","params","meta","Pending","seq","command","inv","attempted","posted","applied","resolve","payload","reject","error","CtxPending","ops","protocolError","message","Error","newClientId","rejectedSend","failure","SendFailure","Promise","result","catch","AttachState","StatewireSessionOptions","sessionStore","SessionStorage","onSessionLost","OnSessionLost","onDone","Shared","txq","parked","SessionVerdict","unsubscribe","Session","record","SessionRecord","ctx","recordPersisted","store","shared","ephemeral","deactivated","sessionKnown","durableSeq","resumeAt","idle","ctxOps","ctxPending","lanesOnAttach","attachLaneSeqs","ReadonlySet","frameFailures","pending","canonical","lastPublished","changed","source","StateSource","attach","attachEpoch","running","pumping","transport","waiters","lifecycle","notify","commands","Record","publish","s","wake","waiter","waitForWake","r","push","sleepUntilWake","delayMs","clearTimeout","timer","setTimeout","filter","w","setRecord","save","backlog","SessionCommand","p","map","mergeBacklog","own","known","Set","foreign","c","has","sort","a","b","MAX_PARKED_VERDICTS","syncBacklogInner","splice","parkedSeqs","v","verdicts","length","slice","unchanged","every","i","undefined","syncBacklog","transact","fn","run","then","lock","stored","load","clientId","adoptReset","setIdle","level","cover","entry","onApplied","onCovered","NO_FAILED","FailedCommand","failedCommands","failed","retainFailed","ts","settleEntry","outcome","ok","onSettle","type","rides","cause","settleAll","detach","const","batch","detachFailure","predecessorLost","some","fate","restateContext","ctxNextSeq","settleLost","entries","rebaseRecord","adopt","held","survivors","old","enqueueInner","pump","resetRecord","nextSeq","ephemeralDetach","rejectedFailure","cmd","code","outcomeOf","String","TERMINAL_CMD_TYPES","parkVerdict","handleCmd","Number","isSafeInteger","dur","Math","max","find","consumeVerdicts","consumed","verdict","add","size","handleCmds","cmds","ingestOps","state","changedPaths","publishIngested","snapCtxClock","ctxWm","ctxAligned","sessionLostInner","seqWm","handleHello","syn","attachCmd","attachCtx","reconcile","adoptStored","ctxWatermark","ctxSeq","handleOps","handleRefusal","watermark","retry","Date","now","firstCmd","firstCtx","cmdGap","ctxGap","handleDetach","handleFinish","reason","isFinished","Lanes","frame","cmdEntries","ctxEntries","buildLanes","at","takeAttachLanes","wanted","lanes","connection","status","reconnect","resumeDelay","epoch","send","includes","onPosted","start","subscribe","stop","setTransport","onStart","enqueue","sendCommand","encoded","takeFailed","found","f","discardFailed","retryFailed","setContext","value","Array","isArray","op","path","mint","useStatewireSession","options","defaultStore","mounted","session","onHello","args","onOps","onCmds","onRefusal","onIdle","onDetach","onFinish","snapshot","takeChanged","setOnChange","listener","setListener"],"sources":["../../src/client/session.ts"],"sourcesContent":["import { useContext, useEffect, useState } from \"react\";\nimport { applyOps } from \"../wire/ops\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport { TERMINAL } from \"./connection\";\nimport type { StatewireCmd, StatewireSyn } from \"./connection\";\nimport {\n encodeParams,\n encodeValue,\n reviveResponse,\n reviveValue,\n} from \"../wire/meta\";\nimport { bindCommandsHost } from \"../host/host\";\nimport type { CommandsInvocation, CommandsListener } from \"../host/host\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireClient } from \"../statewire\";\nimport {\n SessionStorageContext,\n createMemorySessionStore,\n} from \"./sessionStore\";\nimport { backoff } from \"./timing\";\nimport { createMethodProxy } from \"../util/methodProxy\";\nimport { randomId } from \"../util/randomId\";\nimport { StatewireSendError } from \"../types\";\nimport type {\n RemoteLink,\n StatewireFrame,\n StatewireRemoteProps,\n} from \"../transports/sse\";\n\ntype WireCommand = {\n method: string;\n params: unknown[];\n meta?: unknown;\n};\n\ntype Pending = {\n readonly seq: number;\n readonly command: WireCommand;\n readonly inv: CommandsInvocation;\n /** A send carrying this statement may have reached the server. */\n attempted: boolean;\n /** In the resend queue when false. */\n posted: boolean;\n /** The server acknowledged admission; the terminal verdict is still due. */\n applied: boolean;\n resolve: (payload: unknown) => void;\n reject: (error: StatewireSendError) => void;\n};\n\ntype CtxPending = {\n readonly seq: number;\n readonly ops: unknown[];\n posted: boolean;\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst newClientId = () => `c-${randomId()}`;\n\nconst rejectedSend = (\n failure: StatewireClient.SendFailure,\n): Promise<unknown> => {\n const result = Promise.reject<unknown>(new StatewireSendError(failure));\n result.catch(() => {});\n return result;\n};\n\ntype AttachState = \"detached\" | \"attached\" | \"finished\";\n\nexport type StatewireSessionOptions = {\n sessionStore?: StatewireClient.SessionStorage | undefined;\n onSessionLost?: StatewireClient.OnSessionLost | undefined;\n onDone?: (() => void) | undefined;\n};\n\ntype Shared = {\n txq: Promise<void>;\n parked: StatewireClient.SessionVerdict[];\n unsubscribe: (() => void) | null;\n};\n\ntype Session = {\n record: StatewireClient.SessionRecord;\n ctx: StatewireRemoteProps;\n recordPersisted: boolean;\n store: StatewireClient.SessionStorage;\n shared: Shared | false;\n ephemeral: boolean;\n /** An ephemeral record died with its attach: the storage is off for good. */\n deactivated: boolean;\n sessionKnown: boolean;\n durableSeq: number;\n resumeAt: number;\n idle: boolean;\n onSessionLost: StatewireClient.OnSessionLost | undefined;\n onDone: (() => void) | undefined;\n ctxOps: unknown[] | undefined;\n ctxPending: CtxPending[];\n lanesOnAttach: boolean;\n attachLaneSeqs: readonly [ReadonlySet<number>, ReadonlySet<number>];\n frameFailures: number;\n pending: Pending[];\n canonical: unknown;\n lastPublished: unknown;\n changed: StatewirePath[];\n source: Statewire.StateSource;\n attach: AttachState;\n attachEpoch: number;\n running: boolean;\n pumping: boolean;\n transport: RemoteLink | null;\n waiters: (() => void)[];\n lifecycle: CommandsListener | null;\n notify: () => void;\n commands: Record<string, (...params: unknown[]) => Promise<unknown>>;\n};\n\nconst publish = (s: Session) => {\n if (s.canonical === s.lastPublished) return;\n s.lastPublished = s.canonical;\n s.notify();\n};\n\nconst wake = (s: Session) => {\n const waiters = s.waiters;\n s.waiters = [];\n for (const waiter of waiters) waiter();\n};\n\nconst waitForWake = (s: Session) => new Promise<void>((r) => s.waiters.push(r));\n\nconst sleepUntilWake = (s: Session, delayMs: number) =>\n new Promise<void>((resolve) => {\n const waiter = () => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(() => {\n s.waiters = s.waiters.filter((w) => w !== waiter);\n resolve();\n }, delayMs);\n s.waiters.push(waiter);\n });\n\nconst setRecord = (s: Session, record: StatewireClient.SessionRecord) => {\n s.record = record;\n if (!s.deactivated) s.store.save(record);\n};\n\nconst backlog = (s: Session): StatewireClient.SessionCommand[] =>\n s.pending\n .filter((p) => p.seq > s.durableSeq)\n .map((p) => ({ seq: p.seq, ...p.command }));\n\nconst mergeBacklog = (s: Session): StatewireClient.SessionCommand[] => {\n const own = backlog(s);\n if (!s.shared) return own;\n const known = new Set(s.pending.map((p) => p.seq));\n const foreign = s.record.commands.filter(\n (c) => !known.has(c.seq) && c.seq > s.durableSeq,\n );\n return [...foreign, ...own].sort((a, b) => a.seq - b.seq);\n};\n\nconst MAX_PARKED_VERDICTS = 64;\n\n// Storage holds what a reload must resend: a command leaves at its dur, at a\n// server verdict, or at a record reset — never at a local channel death.\nconst syncBacklogInner = (s: Session) => {\n const parked = s.shared ? s.shared.parked.splice(0) : [];\n const parkedSeqs = new Set(parked.map((v) => v.seq));\n const commands = mergeBacklog(s).filter((c) => !parkedSeqs.has(c.seq));\n const verdicts =\n parked.length > 0\n ? [...(s.record.verdicts ?? []), ...parked].slice(-MAX_PARKED_VERDICTS)\n : s.record.verdicts;\n const unchanged =\n verdicts === s.record.verdicts &&\n commands.length === s.record.commands.length &&\n commands.every((c, i) => c.seq === s.record.commands[i]!.seq);\n if (unchanged) return;\n setRecord(s, {\n ...s.record,\n commands,\n ...(verdicts !== undefined && { verdicts }),\n });\n};\n\nconst syncBacklog = (s: Session) => {\n if (!s.shared) return syncBacklogInner(s);\n void transact(s, () => syncBacklogInner(s));\n};\n\n// Every record mutation over shared storage is a locked read-modify-write.\nconst transact = (s: Session, fn: () => void): Promise<void> => {\n if (!s.shared || s.deactivated) {\n fn();\n return Promise.resolve();\n }\n const shared = s.shared;\n const run = shared.txq.then(() =>\n s.store.lock!(async () => {\n const stored = s.store.load();\n if (stored !== null && stored.clientId !== s.record.clientId) {\n adoptReset(s, stored);\n } else if (stored !== null) {\n s.record = stored;\n }\n fn();\n }),\n );\n shared.txq = run.then(\n () => {},\n () => {},\n );\n return run;\n};\n\nconst setIdle = (s: Session, level: boolean) => {\n if (level === s.idle) return;\n s.idle = level;\n s.notify();\n if (level) s.onDone?.();\n};\n\nconst cover = (s: Session, entry: Pending) => {\n if (entry.applied) return;\n entry.applied = true;\n s.lifecycle?.onApplied(entry.inv);\n s.lifecycle?.onCovered?.(entry.inv);\n};\n\nconst NO_FAILED: readonly StatewireClient.FailedCommand[] = [];\n\nexport const failedCommands = (\n s: Session,\n): readonly StatewireClient.FailedCommand[] => s.record.failed ?? NO_FAILED;\n\nconst retainFailed = (\n s: Session,\n entry: Pending,\n failure: StatewireClient.SendFailure,\n) => {\n setRecord(s, {\n ...s.record,\n failed: [\n ...(s.record.failed ?? []),\n {\n command: entry.command.method,\n params: entry.command.params,\n ...(entry.command.meta !== undefined && { meta: entry.command.meta }),\n failure,\n ts: entry.inv.ts,\n seq: entry.seq,\n },\n ],\n });\n s.notify();\n};\n\nconst settleEntry = (\n s: Session,\n entry: Pending,\n outcome:\n | { ok: true; payload: unknown }\n | { ok: false; failure: StatewireClient.SendFailure },\n) => {\n s.pending = s.pending.filter((p) => p !== entry);\n if (outcome.ok) {\n entry.resolve(outcome.payload);\n s.lifecycle?.onSettle(entry.inv, {\n type: \"accepted\",\n payload: outcome.payload,\n });\n } else {\n // A statement the record still carries resends on the next attach; only\n // invocations the record no longer owns become failed history.\n const rides =\n (outcome.failure.cause === \"unmount\" ||\n outcome.failure.cause === \"stream-gone\") &&\n entry.seq > s.durableSeq;\n if (!rides) retainFailed(s, entry, outcome.failure);\n entry.reject(new StatewireSendError(outcome.failure));\n s.lifecycle?.onSettle(entry.inv, {\n type: \"rejected\",\n error: new StatewireSendError(outcome.failure),\n });\n }\n};\n\nconst settleAll = (s: Session, detach: \"unmount\" | \"gone\") => {\n const cause =\n detach === \"unmount\" ? (\"unmount\" as const) : (\"stream-gone\" as const);\n const batch = s.pending;\n const detachFailure = (entry: Pending): StatewireClient.SendFailure => {\n if (!entry.attempted) {\n const predecessorLost = batch.some(\n (p) => p.seq < entry.seq && p.attempted,\n );\n return predecessorLost\n ? { fate: \"aborted\", cause, predecessorLost }\n : { fate: \"aborted\", cause };\n }\n return { fate: \"lost\", cause };\n };\n for (const entry of [...batch]) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, { ok: false, failure: detachFailure(entry) });\n }\n};\n\nconst restateContext = (s: Session) => {\n s.ctxPending = [];\n if (s.ctxOps === undefined) return;\n const seq = s.record.ctxNextSeq;\n setRecord(s, { ...s.record, ctxNextSeq: seq + 1 });\n s.ctxPending.push({ seq, ops: s.ctxOps, posted: false });\n};\n\nconst settleLost = (s: Session, entries: Pending[]) => {\n for (const entry of entries) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, {\n ok: false,\n failure: { fate: \"lost\", cause: \"session-lost\" },\n });\n }\n};\n\n// The server-side record's dedup memory is gone: history that may have\n// reached a server settles lost — the new hello's snapshot is the only\n// truth about what survived — and never-attempted statements re-stamp\n// on the adopted lane clocks.\nconst rebaseRecord = (s: Session, adopt: () => void) => {\n const held = [...s.pending];\n const survivors = held.filter((p) => !p.attempted && !p.applied);\n settleLost(\n s,\n held.filter((p) => p.attempted || p.applied),\n );\n s.pending = [];\n s.durableSeq = 0;\n // Failed entries are user-owned history: they ride through every record replacement.\n const failed = s.record.failed;\n adopt();\n if (failed !== undefined && s.record.failed !== failed) {\n setRecord(s, {\n ...s.record,\n failed: [...(s.record.failed ?? []), ...failed],\n });\n }\n for (const old of survivors) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueueInner(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n restateContext(s);\n publish(s);\n wake(s);\n void pump(s);\n};\n\nconst resetRecord = (s: Session, clientId: string) =>\n rebaseRecord(s, () =>\n setRecord(s, { clientId, nextSeq: 1, ctxNextSeq: 1, commands: [] }),\n );\n\n// Another sharer replaced the record's identity: their reset settles our\n// attempted history and our survivors re-stamp on the stored clocks.\nconst adoptReset = (s: Session, stored: StatewireClient.SessionRecord) =>\n rebaseRecord(s, () => {\n s.record = stored;\n });\n\n// The record died with the attach: mint a fresh id for the next one.\nconst ephemeralDetach = (s: Session) => {\n s.ephemeral = false;\n s.sessionKnown = false;\n resetRecord(s, newClientId());\n};\n\nconst rejectedFailure = (cmd: StatewireCmd): StatewireClient.SendFailure => {\n return {\n fate: \"rejected\",\n cause: \"server\",\n ...(cmd.code !== undefined && { code: cmd.code }),\n ...(cmd.message !== undefined && { message: cmd.message }),\n ...(cmd.payload !== undefined && { payload: cmd.payload }),\n };\n};\n\nconst outcomeOf = (\n cmd: StatewireCmd,\n):\n | { ok: true; payload: unknown }\n | { ok: false; failure: StatewireClient.SendFailure } => {\n switch (cmd.type) {\n case \"result\":\n return { ok: true, payload: reviveResponse(cmd).payload };\n case \"rejected\":\n return { ok: false, failure: rejectedFailure(reviveResponse(cmd)) };\n case \"failed\":\n return {\n ok: false,\n failure: {\n fate: \"failed\",\n cause: \"server\",\n ...(cmd.message !== undefined && { message: cmd.message }),\n },\n };\n case \"crashed\":\n return { ok: false, failure: { fate: \"crashed\", cause: \"server\" } };\n case \"expired\":\n return { ok: false, failure: { fate: \"expired\", cause: \"server\" } };\n default:\n return protocolError(`unknown cmd type: ${String(cmd.type)}`);\n }\n};\n\nconst TERMINAL_CMD_TYPES: ReadonlySet<string> = new Set(TERMINAL);\n\nconst parkVerdict = (s: Session, cmd: StatewireCmd) => {\n if (!s.shared || !TERMINAL_CMD_TYPES.has(cmd.type!)) return;\n s.shared.parked.push({\n seq: cmd.seq,\n type: cmd.type as StatewireClient.SessionVerdict[\"type\"],\n ...(cmd.code !== undefined && { code: cmd.code }),\n ...(cmd.message !== undefined && { message: cmd.message }),\n ...(cmd.payload !== undefined && { payload: cmd.payload }),\n ...(cmd.meta !== undefined && { meta: cmd.meta }),\n });\n};\n\nconst handleCmd = (s: Session, cmd: StatewireCmd) => {\n if (!Number.isSafeInteger(cmd.seq) || cmd.seq <= 0) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n if (cmd.dur === true) {\n s.durableSeq = Math.max(s.durableSeq, cmd.seq);\n for (const entry of s.pending) {\n if (entry.seq <= s.durableSeq) entry.posted = true;\n }\n }\n if (cmd.type === undefined) return;\n const entry = s.pending.find((p) => p.seq === cmd.seq);\n if (cmd.type === \"applied\") {\n if (entry) cover(s, entry);\n return;\n }\n parkVerdict(s, cmd);\n if (!entry) return;\n cover(s, entry);\n settleEntry(s, entry, outcomeOf(cmd));\n};\n\nconst consumeVerdicts = (s: Session) => {\n const verdicts = s.record.verdicts ?? [];\n const consumed = new Set<number>();\n for (const verdict of verdicts) {\n const entry = s.pending.find((p) => p.seq === verdict.seq);\n if (!entry) continue;\n consumed.add(verdict.seq);\n cover(s, entry);\n settleEntry(s, entry, outcomeOf(verdict as StatewireCmd));\n }\n if (consumed.size === 0) return;\n setRecord(s, {\n ...s.record,\n commands: s.record.commands.filter((c) => !consumed.has(c.seq)),\n verdicts: verdicts.filter((v) => !consumed.has(v.seq)),\n });\n publish(s);\n wake(s);\n};\n\nconst handleCmds = (s: Session, cmds: StatewireCmd[]) => {\n for (const cmd of cmds) handleCmd(s, cmd);\n syncBacklog(s);\n wake(s);\n};\n\nconst ingestOps = (s: Session, ops: unknown[]) => {\n const applied = applyOps(s.canonical, ops);\n s.canonical = applied.state;\n s.changed.push(...applied.changedPaths);\n};\n\nconst publishIngested = (s: Session) => {\n publish(s);\n wake(s);\n};\n\n// A hello's cmd watermark may understate a durable record (cold host, tray\n// unloaded): held seqs resend as-is and the frame's answer arbitrates —\n// absorption where the record survived, a gap refusal where it did not.\nconst snapCtxClock = (s: Session, ctxWm: number) => {\n const ctxAligned =\n s.ctxPending.every((c, i) => c.seq === ctxWm + 1 + i) &&\n s.record.ctxNextSeq === ctxWm + s.ctxPending.length + 1;\n if (!ctxAligned) {\n setRecord(s, { ...s.record, ctxNextSeq: ctxWm + 1 });\n restateContext(s);\n }\n};\n\n// The refusal's watermarks are exact: every held statement above them was\n// never admitted by the live record, and the first unposted seq being beyond\n// watermark+1 proves the record that admitted the missing prefix is gone —\n// its history settles lost and the lane clocks restart at the watermarks.\nconst sessionLostInner = (s: Session, seqWm: number, ctxWm: number) => {\n const held = [...s.pending];\n settleLost(s, held);\n s.pending = [];\n s.durableSeq = seqWm;\n setRecord(s, {\n clientId: s.record.clientId,\n nextSeq: seqWm + 1,\n ctxNextSeq: ctxWm + 1,\n commands: [],\n ...(s.record.failed !== undefined && { failed: s.record.failed }),\n });\n restateContext(s);\n if (\n held.length > 0 &&\n s.onSessionLost?.(held.map((p) => p.inv)) === \"requeue\"\n ) {\n for (const old of held) {\n enqueueInner(\n s,\n old.command,\n old.inv.params,\n () => {},\n () => {},\n );\n }\n }\n publish(s);\n wake(s);\n};\n\nconst handleHello = (\n s: Session,\n { ops, syn }: { ops: unknown[]; syn: StatewireSyn },\n) => {\n if (syn.record !== undefined && syn.record !== \"ephemeral\") {\n protocolError(`unknown record: ${String(syn.record)}`);\n }\n ingestOps(s, ops);\n s.attach = \"attached\";\n s.attachEpoch += 1;\n s.frameFailures = 0;\n s.resumeAt = 0;\n s.ephemeral = syn.record === \"ephemeral\";\n if (s.ephemeral) s.deactivated = true;\n const [attachCmd, attachCtx] = s.attachLaneSeqs;\n s.attachLaneSeqs = [new Set(), new Set()];\n const reconcile = () => {\n if (s.shared) adoptStored(s);\n // Resending unsettled statements is exactly-once-safe: absorbed replays\n // re-emit their stored verdicts (applied while still in flight).\n s.durableSeq = syn.seq ?? 0;\n for (const entry of s.pending) {\n entry.posted = attachCmd.has(entry.seq);\n }\n const ctxWatermark = syn.ctxSeq ?? 0;\n s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxWatermark);\n for (const c of s.ctxPending) c.posted = attachCtx.has(c.seq);\n snapCtxClock(s, ctxWatermark);\n syncBacklogInner(s);\n s.sessionKnown = true;\n };\n if (!s.shared || s.deactivated) {\n reconcile();\n publishIngested(s);\n void pump(s);\n return;\n }\n void transact(s, reconcile).then(() => {\n publishIngested(s);\n void pump(s);\n });\n};\n\nconst handleOps = (\n s: Session,\n { ops, cmds }: { ops: unknown[]; cmds: StatewireCmd[] },\n) => {\n ingestOps(s, ops);\n for (const cmd of cmds) handleCmd(s, cmd);\n syncBacklog(s);\n publishIngested(s);\n};\n\n// A retry-less {syn} refusal is the one session-loss verdict: a cmd gap\n// against its exact watermark settles the held history lost; a pushback\n// (retry present) or a gapless refusal only reconciles the resend queues.\nconst handleRefusal = (s: Session, syn: StatewireSyn) => {\n const { seq, ctxSeq } = syn;\n if (typeof seq === \"number\") {\n const watermark = Math.max(seq, s.durableSeq);\n for (const entry of s.pending) entry.posted = entry.seq <= watermark;\n }\n if (typeof ctxSeq === \"number\") {\n s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxSeq);\n for (const c of s.ctxPending) c.posted = false;\n }\n if (typeof syn.retry === \"number\") {\n s.resumeAt = Date.now() + syn.retry;\n wake(s);\n void pump(s);\n return;\n }\n const firstCmd = s.pending.find((p) => !p.posted);\n const firstCtx = s.ctxPending.find((c) => !c.posted);\n const cmdGap =\n typeof seq === \"number\" &&\n firstCmd !== undefined &&\n firstCmd.seq > Math.max(seq, s.durableSeq) + 1;\n const ctxGap =\n typeof ctxSeq === \"number\" &&\n firstCtx !== undefined &&\n firstCtx.seq > ctxSeq + 1;\n if (cmdGap || ctxGap) {\n void transact(s, () => {\n if (cmdGap) sessionLostInner(s, seq!, ctxSeq ?? 0);\n else snapCtxClock(s, ctxSeq!);\n }).then(() => {\n wake(s);\n void pump(s);\n });\n return;\n }\n wake(s);\n void pump(s);\n};\n\nconst handleDetach = (s: Session) => {\n if (s.attach === \"attached\") s.attach = \"detached\";\n if (s.ephemeral) ephemeralDetach(s);\n wake(s);\n};\n\nconst handleFinish = (s: Session, { reason }: { reason: string }) => {\n if (reason === \"evicted\" || reason === \"error\") return;\n s.attach = \"finished\";\n settleAll(s, \"gone\");\n publish(s);\n wake(s);\n};\n\nconst isFinished = (s: Session) => s.attach === \"finished\";\n\ntype Lanes = {\n frame: StatewireFrame;\n cmdEntries: Pending[];\n ctxEntries: CtxPending[];\n};\n\n// A lane must be strictly consecutive within a frame: the first unposted run\n// per lane rides now, later runs ride follow-up frames.\nconst buildLanes = (s: Session): Lanes | null => {\n const ctxEntries: CtxPending[] = [];\n for (const entry of s.ctxPending) {\n if (entry.posted) continue;\n if (ctxEntries.length > 0 && entry.seq !== ctxEntries.at(-1)!.seq + 1)\n break;\n ctxEntries.push(entry);\n }\n const cmdEntries: Pending[] = [];\n for (const entry of s.pending) {\n if (entry.posted) continue;\n if (cmdEntries.length > 0 && entry.seq !== cmdEntries.at(-1)!.seq + 1)\n break;\n cmdEntries.push(entry);\n }\n if (ctxEntries.length === 0 && cmdEntries.length === 0) return null;\n return {\n frame: {\n ...(ctxEntries.length > 0 && {\n ctx: ctxEntries.map((c) => ({ ops: c.ops, seq: c.seq })),\n }),\n ...(cmdEntries.length > 0 && {\n cmd: cmdEntries.map((p) => ({ ...p.command, seq: p.seq })),\n }),\n },\n cmdEntries,\n ctxEntries,\n };\n};\n\nconst takeAttachLanes = (s: Session): StatewireFrame | null => {\n s.attachLaneSeqs = [new Set(), new Set()];\n const wanted = s.lanesOnAttach;\n s.lanesOnAttach = false;\n if (!wanted || !s.sessionKnown) return null;\n const lanes = buildLanes(s);\n if (!lanes) return null;\n s.attachLaneSeqs = [\n new Set(lanes.cmdEntries.map((p) => p.seq)),\n new Set(lanes.ctxEntries.map((c) => c.seq)),\n ];\n for (const entry of lanes.cmdEntries) entry.attempted = true;\n return lanes.frame;\n};\n\nconst pump = async (s: Session) => {\n if (s.pumping) return;\n s.pumping = true;\n try {\n while (s.running && !isFinished(s)) {\n const transport = s.transport;\n if (buildLanes(s) === null) return;\n if (s.attach !== \"attached\" || !transport) {\n if (\n (transport?.connection.status === \"disconnected\" &&\n transport.connection.reason === \"idle\") ||\n (transport?.parked && s.pending.length > 0)\n ) {\n transport.connection.reconnect();\n }\n await waitForWake(s);\n continue;\n }\n const resumeDelay = s.resumeAt - Date.now();\n if (resumeDelay > 0) {\n await sleepUntilWake(s, resumeDelay);\n continue;\n }\n const lanes = buildLanes(s);\n if (!lanes) continue;\n const epoch = s.attachEpoch;\n for (const entry of lanes.cmdEntries) entry.attempted = true;\n let result;\n try {\n // Shared storage: the lock across the send keeps per-lane arrival\n // ordered across sharers during attach handover.\n const send = () => transport.send(lanes.frame);\n result = await (s.shared && !s.deactivated\n ? s.store.lock!(send)\n : send());\n } catch {\n if (!s.running || isFinished(s)) return;\n s.frameFailures += 1;\n await sleepUntilWake(s, backoff(s.frameFailures));\n continue;\n }\n if (!s.running) return;\n s.frameFailures = 0;\n if (result.type === \"ok\") {\n if (epoch === s.attachEpoch) {\n for (const entry of lanes.cmdEntries) {\n if (s.pending.includes(entry)) {\n entry.posted = true;\n s.lifecycle?.onPosted?.(entry.inv);\n }\n }\n for (const entry of lanes.ctxEntries) entry.posted = true;\n }\n } else if (result.type === \"refusal\") {\n if (epoch === s.attachEpoch) handleRefusal(s, result.syn);\n } else if (result.type === \"stale-lease\") {\n // A POST outlived its attach: reattach first, the hello arbitrates.\n if (epoch === s.attachEpoch) {\n transport.connection.reconnect();\n await waitForWake(s);\n }\n } else if (result.type === \"no-lease\") {\n // No out-of-band write channel: the frame rides a fresh attach.\n if (epoch === s.attachEpoch) {\n s.lanesOnAttach = true;\n transport.connection.reconnect();\n while (s.running && !isFinished(s) && epoch === s.attachEpoch) {\n await waitForWake(s);\n }\n }\n }\n }\n } finally {\n s.pumping = false;\n }\n};\n\nconst start = (s: Session) => {\n if (s.shared) {\n s.shared.unsubscribe = s.store.subscribe!(() => {\n void transact(s, () => consumeVerdicts(s));\n });\n s.running = true;\n void transact(s, () => {\n if (s.store.load() === null) s.store.save(s.record);\n s.recordPersisted = true;\n adoptStored(s);\n consumeVerdicts(s);\n }).then(() => void pump(s));\n return;\n }\n if (!s.recordPersisted) {\n s.recordPersisted = true;\n s.store.save(s.record);\n }\n adoptStored(s);\n s.running = true;\n void pump(s);\n};\n\nconst stop = (s: Session) => {\n s.running = false;\n if (s.shared) {\n s.shared.unsubscribe?.();\n s.shared.unsubscribe = null;\n }\n wake(s);\n settleAll(s, \"unmount\");\n};\n\nconst setTransport = (s: Session, transport: RemoteLink) => {\n if (s.transport === transport) return;\n s.transport = transport;\n wake(s);\n};\n\nconst enqueueInner = (\n s: Session,\n command: WireCommand,\n params: readonly unknown[],\n resolve: (payload: unknown) => void,\n reject: (error: StatewireSendError) => void,\n) => {\n const seq = s.record.nextSeq;\n const entry: Pending = {\n seq,\n command,\n inv: {\n method: command.method,\n params,\n ts: Date.now(),\n seq,\n clientId: s.record.clientId,\n },\n attempted: false,\n posted: false,\n applied: false,\n resolve,\n reject,\n };\n s.pending.push(entry);\n setRecord(s, { ...s.record, nextSeq: seq + 1, commands: mergeBacklog(s) });\n s.lifecycle?.onStart(entry.inv);\n};\n\nconst enqueue = (\n s: Session,\n command: WireCommand,\n params: readonly unknown[],\n resolve: (payload: unknown) => void,\n reject: (error: StatewireSendError) => void,\n) => {\n if (!s.shared) {\n enqueueInner(s, command, params, resolve, reject);\n wake(s);\n void pump(s);\n return;\n }\n void transact(s, () =>\n enqueueInner(s, command, params, resolve, reject),\n ).then(() => {\n wake(s);\n void pump(s);\n });\n};\n\n// A stored command may have reached a server: attempted settles it lost,\n// never aborted, when a channel death ends the session.\nconst adoptStored = (s: Session) => {\n const known = new Set(s.pending.map((p) => p.seq));\n const stored = s.record.commands.filter((c) => !known.has(c.seq));\n if (stored.length === 0) return;\n for (const { seq, ...command } of stored) {\n const params =\n command.meta === undefined\n ? command.params\n : (reviveValue([...command.params], command.meta) as unknown[]);\n const entry: Pending = {\n seq,\n command,\n inv: {\n method: command.method,\n params,\n ts: Date.now(),\n seq,\n clientId: s.record.clientId,\n },\n attempted: true,\n posted: false,\n applied: false,\n resolve: () => {},\n reject: () => {},\n };\n s.pending.push(entry);\n s.lifecycle?.onStart(entry.inv);\n }\n s.pending.sort((a, b) => a.seq - b.seq);\n};\n\nconst sendCommand = (\n s: Session,\n method: string,\n params: readonly unknown[],\n): Promise<unknown> => {\n if (!s.running) {\n return rejectedSend({ fate: \"aborted\", cause: \"unmount\" });\n }\n if (isFinished(s)) {\n return rejectedSend({ fate: \"aborted\", cause: \"stream-gone\" });\n }\n const result = new Promise<unknown>((resolve, reject) => {\n const { params: encoded, meta } = encodeParams(params);\n enqueue(\n s,\n { method, params: encoded, ...(meta !== undefined && { meta }) },\n params,\n resolve,\n reject,\n );\n });\n result.catch(() => {});\n return result;\n};\n\nconst takeFailed = (\n s: Session,\n entry: StatewireClient.FailedCommand,\n): StatewireClient.FailedCommand => {\n const failed = s.record.failed ?? [];\n const found = failed.find(\n (f) =>\n f.seq === entry.seq && f.ts === entry.ts && f.command === entry.command,\n );\n if (found === undefined) {\n throw new Error(`statewire: unknown failed command \"${entry.command}\"`);\n }\n setRecord(s, { ...s.record, failed: failed.filter((f) => f !== found) });\n s.notify();\n return found;\n};\n\nexport const discardFailed = (\n s: Session,\n entry: StatewireClient.FailedCommand,\n): void => {\n takeFailed(s, entry);\n};\n\nexport const retryFailed = (\n s: Session,\n entry: StatewireClient.FailedCommand,\n): Promise<unknown> => {\n if (!s.running) {\n return rejectedSend({ fate: \"aborted\", cause: \"unmount\" });\n }\n if (isFinished(s)) {\n return rejectedSend({ fate: \"aborted\", cause: \"stream-gone\" });\n }\n const found = takeFailed(s, entry);\n const params =\n found.meta === undefined\n ? found.params\n : (reviveValue([...found.params], found.meta) as unknown[]);\n const result = new Promise<unknown>((resolve, reject) => {\n enqueue(\n s,\n {\n method: found.command,\n params: [...found.params],\n ...(found.meta !== undefined && { meta: found.meta }),\n },\n params,\n resolve,\n reject,\n );\n });\n result.catch(() => {});\n return result;\n};\n\nconst setContext = (s: Session, value: Record<string, unknown>): void => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\"statewire: context must be a plain object\");\n }\n if (!s.running || isFinished(s)) return;\n const { value: encoded, meta } = encodeValue(value);\n const ops = [\n {\n op: \"replace\",\n path: [],\n value: encoded,\n ...(meta !== undefined && { meta }),\n },\n ];\n s.ctxOps = ops;\n const mint = () => {\n const seq = s.record.ctxNextSeq;\n setRecord(s, { ...s.record, ctxNextSeq: seq + 1 });\n s.ctxPending.push({ seq, ops, posted: false });\n };\n if (!s.shared) {\n mint();\n wake(s);\n void pump(s);\n return;\n }\n void transact(s, mint).then(() => {\n wake(s);\n void pump(s);\n });\n};\n\nexport const useStatewireSession = (\n options: StatewireSessionOptions,\n): Session => {\n const [defaultStore] = useState(createMemorySessionStore);\n const mounted = useContext(SessionStorageContext);\n if (options.sessionStore !== undefined && mounted !== undefined) {\n throw new Error(\n \"statewire: session storage is set twice — drop the transport's sessionStore or the client's storage.session\",\n );\n }\n const store = options.sessionStore ?? mounted ?? defaultStore;\n if ((store.lock === undefined) !== (store.subscribe === undefined)) {\n throw new Error(\n \"statewire: session storage must provide lock and subscribe together\",\n );\n }\n const [s] = useState((): Session => {\n const stored = store.load();\n if (stored !== null && !Array.isArray(stored.commands)) {\n throw new Error(\n \"statewire: session storage loaded a record without a commands array\",\n );\n }\n const record = stored ?? {\n clientId: newClientId(),\n nextSeq: 1,\n ctxNextSeq: 1,\n commands: [],\n };\n const session: Session = {\n record,\n ctx: {\n get clientId() {\n return session.record.clientId;\n },\n takeAttachLanes: () => takeAttachLanes(session),\n onHello: (args) => handleHello(session, args),\n onOps: (args) => handleOps(session, args),\n onCmds: (cmds) => handleCmds(session, cmds),\n onRefusal: (syn) => handleRefusal(session, syn),\n onIdle: (level) => setIdle(session, level),\n onDetach: () => handleDetach(session),\n onFinish: (args) => handleFinish(session, args),\n },\n recordPersisted: stored !== null,\n store,\n shared:\n store.lock !== undefined\n ? { txq: Promise.resolve(), parked: [], unsubscribe: null }\n : false,\n ephemeral: false,\n deactivated: false,\n sessionKnown: false,\n durableSeq: 0,\n resumeAt: 0,\n idle: false,\n onSessionLost: undefined,\n onDone: undefined,\n ctxOps: undefined,\n ctxPending: [],\n lanesOnAttach: false,\n attachLaneSeqs: [new Set(), new Set()],\n frameFailures: 0,\n pending: [],\n canonical: undefined,\n lastPublished: undefined,\n changed: [],\n source: {\n snapshot: () => session.canonical,\n takeChanged: () => {\n const changed = session.changed;\n session.changed = [];\n return changed;\n },\n setOnChange: (listener) => {\n session.notify = listener ?? (() => {});\n },\n },\n attach: \"detached\",\n attachEpoch: 0,\n running: false,\n pumping: false,\n transport: null,\n waiters: [],\n lifecycle: null,\n notify: () => {},\n commands: createMethodProxy((method, params) =>\n sendCommand(session, method, params),\n ),\n };\n bindCommandsHost(session.commands, {\n setListener: (listener) => {\n session.lifecycle = listener;\n },\n });\n return session;\n });\n if ((store.lock !== undefined) !== (s.shared !== false)) {\n throw new Error(\n \"statewire: session storage changed sharedness across renders — lock/subscribe must be present from the first render or never\",\n );\n }\n s.store = store;\n s.onSessionLost = options.onSessionLost;\n s.onDone = options.onDone;\n useEffect(() => {\n start(s);\n return () => stop(s);\n }, [s]);\n return s;\n};\n\nexport { setContext, setTransport };\n"],"mappings":";;;;;;;;;;;AAuDA,MAAM2C,iBAAiBC,YAA2B;CAChD,MAAM,IAAIC,MAAM,8BAA8BD,SAAS;AACzD;AAEA,MAAME,oBAAoB,KAAKzB,SAAS;AAExC,MAAM0B,gBACJC,YACqB;CACrB,MAAMG,SAASD,QAAQX,OAAgB,IAAIjB,mBAAmB0B,OAAO,CAAC;CACtEG,OAAOC,YAAY,CAAC,CAAC;CACrB,OAAOD;AACT;AAoDA,MAAMiD,WAAWC,MAAe;CAC9B,IAAIA,EAAEhB,cAAcgB,EAAEf,eAAe;CACrCe,EAAEf,gBAAgBe,EAAEhB;CACpBgB,EAAEJ,OAAO;AACX;AAEA,MAAMK,QAAQD,MAAe;CAC3B,MAAMN,UAAUM,EAAEN;CAClBM,EAAEN,UAAU,CAAA;CACZ,KAAK,MAAMQ,UAAUR,SAASQ,OAAO;AACvC;AAEA,MAAMC,eAAeH,MAAe,IAAInD,SAAeuD,MAAMJ,EAAEN,QAAQW,KAAKD,CAAC,CAAC;AAE9E,MAAME,kBAAkBN,GAAYO,YAClC,IAAI1D,SAAeb,YAAY;CAC7B,MAAMkE,eAAe;EACnBM,aAAaC,KAAK;EAClBzE,QAAQ;CACV;CACA,MAAMyE,QAAQC,iBAAiB;EAC7BV,EAAEN,UAAUM,EAAEN,QAAQiB,QAAQC,MAAMA,MAAMV,MAAM;EAChDlE,QAAQ;CACV,GAAGuE,OAAO;CACVP,EAAEN,QAAQW,KAAKH,MAAM;AACvB,CAAC;AAEH,MAAMW,aAAab,GAAYnC,WAA0C;CACvEmC,EAAEnC,SAASA;CACX,IAAI,CAACmC,EAAE5B,aAAa4B,EAAE/B,MAAM6C,KAAKjD,MAAM;AACzC;AAEA,MAAMkD,WAAWf,MACfA,EAAEjB,QACC4B,QAAQM,MAAMA,EAAEvF,MAAMsE,EAAE1B,UAAU,CAAC,CACnC4C,KAAKD,OAAO;CAAEvF,KAAKuF,EAAEvF;CAAK,GAAGuF,EAAEtF;AAAQ,EAAE;AAE9C,MAAMwF,gBAAgBnB,MAAiD;CACrE,MAAMoB,MAAML,QAAQf,CAAC;CACrB,IAAI,CAACA,EAAE9B,QAAQ,OAAOkD;CACtB,MAAMC,QAAQ,IAAIC,IAAItB,EAAEjB,QAAQmC,KAAKD,MAAMA,EAAEvF,GAAG,CAAC;CAIjD,OAAO,CAAC,GAHQsE,EAAEnC,OAAOgC,SAASc,QAC/Ba,MAAM,CAACH,MAAMI,IAAID,EAAE9F,GAAG,KAAK8F,EAAE9F,MAAMsE,EAAE1B,UAE7BiD,GAAS,GAAGH,GAAG,CAAC,CAACM,MAAMC,GAAGC,MAAMD,EAAEjG,MAAMkG,EAAElG,GAAG;AAC1D;AAMA,MAAMoG,oBAAoB9B,MAAe;CACvC,MAAMvC,SAASuC,EAAE9B,SAAS8B,EAAE9B,OAAOT,OAAOsE,OAAO,CAAC,IAAI,CAAA;CACtD,MAAMC,aAAa,IAAIV,IAAI7D,OAAOyD,KAAKe,MAAMA,EAAEvG,GAAG,CAAC;CACnD,MAAMmE,WAAWsB,aAAanB,CAAC,CAAC,CAACW,QAAQa,MAAM,CAACQ,WAAWP,IAAID,EAAE9F,GAAG,CAAC;CACrE,MAAMwG,WACJzE,OAAO0E,SAAS,IACZ,CAAC,GAAInC,EAAEnC,OAAOqE,YAAY,CAAA,GAAK,GAAGzE,MAAM,CAAC,CAAC2E,MAAM,GAAoB,IACpEpC,EAAEnC,OAAOqE;CAKf,IAHEA,aAAalC,EAAEnC,OAAOqE,YACtBrC,SAASsC,WAAWnC,EAAEnC,OAAOgC,SAASsC,UACtCtC,SAASyC,OAAOd,GAAGe,MAAMf,EAAE9F,QAAQsE,EAAEnC,OAAOgC,SAAS0C,EAAE,CAAE7G,GAAG,GAC/C;CACfmF,UAAUb,GAAG;EACX,GAAGA,EAAEnC;EACLgC;EACA,GAAIqC,aAAaM,KAAAA,KAAa,EAAEN,SAAS;CAC3C,CAAC;AACH;AAEA,MAAMO,eAAezC,MAAe;CAClC,IAAI,CAACA,EAAE9B,QAAQ,OAAO4D,iBAAiB9B,CAAC;CACxC,SAAcA,SAAS8B,iBAAiB9B,CAAC,CAAC;AAC5C;AAGA,MAAM0C,YAAY1C,GAAY2C,OAAkC;CAC9D,IAAI,CAAC3C,EAAE9B,UAAU8B,EAAE5B,aAAa;EAC9BuE,GAAG;EACH,OAAO9F,QAAQb,QAAQ;CACzB;CACA,MAAMkC,SAAS8B,EAAE9B;CACjB,MAAM0E,MAAM1E,OAAOV,IAAIqF,WACrB7C,EAAE/B,MAAM6E,KAAM,YAAY;EACxB,MAAMC,SAAS/C,EAAE/B,MAAM+E,KAAK;EAC5B,IAAID,WAAW,QAAQA,OAAOE,aAAajD,EAAEnC,OAAOoF,UAClDC,WAAWlD,GAAG+C,MAAM;OACf,IAAIA,WAAW,MACpB/C,EAAEnC,SAASkF;EAEbJ,GAAG;CACL,CAAC,CACH;CACAzE,OAAOV,MAAMoF,IAAIC,WACT,CAAC,SACD,CAAC,CACT;CACA,OAAOD;AACT;AAEA,MAAMO,WAAWnD,GAAYoD,UAAmB;CAC9C,IAAIA,UAAUpD,EAAExB,MAAM;CACtBwB,EAAExB,OAAO4E;CACTpD,EAAEJ,OAAO;CACT,IAAIwD,OAAOpD,EAAE1C,SAAS;AACxB;AAEA,MAAM+F,SAASrD,GAAYsD,UAAmB;CAC5C,IAAIA,MAAMvH,SAAS;CACnBuH,MAAMvH,UAAU;CAChBiE,EAAEL,WAAW4D,UAAUD,MAAM1H,GAAG;CAChCoE,EAAEL,WAAW6D,YAAYF,MAAM1H,GAAG;AACpC;AAEA,MAAM6H,YAAsD,CAAA;AAE5D,MAAaE,kBACX3D,MAC6CA,EAAEnC,OAAO+F,UAAUH;AAElE,MAAMI,gBACJ7D,GACAsD,OACA3G,YACG;CACHkE,UAAUb,GAAG;EACX,GAAGA,EAAEnC;EACL+F,QAAQ,CACN,GAAI5D,EAAEnC,OAAO+F,UAAU,CAAA,GACvB;GACEjI,SAAS2H,MAAM3H,QAAQL;GACvBC,QAAQ+H,MAAM3H,QAAQJ;GACtB,GAAI+H,MAAM3H,QAAQH,SAASgH,KAAAA,KAAa,EAAEhH,MAAM8H,MAAM3H,QAAQH,KAAK;GACnEmB;GACAmH,IAAIR,MAAM1H,IAAIkI;GACdpI,KAAK4H,MAAM5H;EACb,CAAC;CAEL,CAAC;CACDsE,EAAEJ,OAAO;AACX;AAEA,MAAMmE,eACJ/D,GACAsD,OACAU,YAGG;CACHhE,EAAEjB,UAAUiB,EAAEjB,QAAQ4B,QAAQM,MAAMA,MAAMqC,KAAK;CAC/C,IAAIU,QAAQC,IAAI;EACdX,MAAMtH,QAAQgI,QAAQ/H,OAAO;EAC7B+D,EAAEL,WAAWuE,SAASZ,MAAM1H,KAAK;GAC/BuI,MAAM;GACNlI,SAAS+H,QAAQ/H;EACnB,CAAC;CACH,OAAO;EAOL,IAAI,GAHD+H,QAAQrH,QAAQ0H,UAAU,aACzBL,QAAQrH,QAAQ0H,UAAU,kBAC5Bf,MAAM5H,MAAMsE,EAAE1B,aACJuF,aAAa7D,GAAGsD,OAAOU,QAAQrH,OAAO;EAClD2G,MAAMpH,OAAO,IAAIjB,mBAAmB+I,QAAQrH,OAAO,CAAC;EACpDqD,EAAEL,WAAWuE,SAASZ,MAAM1H,KAAK;GAC/BuI,MAAM;GACNhI,OAAO,IAAIlB,mBAAmB+I,QAAQrH,OAAO;EAC/C,CAAC;CACH;AACF;AAEA,MAAM2H,aAAatE,GAAYuE,WAA+B;CAC5D,MAAMF,QACJE,WAAW,YAAa,YAAuB;CACjD,MAAME,QAAQzE,EAAEjB;CAChB,MAAM2F,iBAAiBpB,UAAgD;EACrE,IAAI,CAACA,MAAMzH,WAAW;GACpB,MAAM8I,kBAAkBF,MAAMG,MAC3B3D,MAAMA,EAAEvF,MAAM4H,MAAM5H,OAAOuF,EAAEpF,SAChC;GACA,OAAO8I,kBACH;IAAEE,MAAM;IAAWR;IAAOM;GAAgB,IAC1C;IAAEE,MAAM;IAAWR;GAAM;EAC/B;EACA,OAAO;GAAEQ,MAAM;GAAQR;EAAM;CAC/B;CACA,KAAK,MAAMf,SAAS,CAAC,GAAGmB,KAAK,GAAG;EAC9BzE,EAAEL,WAAW6D,YAAYF,MAAM1H,GAAG;EAClCmI,YAAY/D,GAAGsD,OAAO;GAAEW,IAAI;GAAOtH,SAAS+H,cAAcpB,KAAK;EAAE,CAAC;CACpE;AACF;AAEA,MAAMwB,kBAAkB9E,MAAe;CACrCA,EAAEtB,aAAa,CAAA;CACf,IAAIsB,EAAEvB,WAAW+D,KAAAA,GAAW;CAC5B,MAAM9G,MAAMsE,EAAEnC,OAAOkH;CACrBlE,UAAUb,GAAG;EAAE,GAAGA,EAAEnC;EAAQkH,YAAYrJ,MAAM;CAAE,CAAC;CACjDsE,EAAEtB,WAAW2B,KAAK;EAAE3E;EAAKW,KAAK2D,EAAEvB;EAAQ3C,QAAQ;CAAM,CAAC;AACzD;AAEA,MAAMkJ,cAAchF,GAAYiF,YAAuB;CACrD,KAAK,MAAM3B,SAAS2B,SAAS;EAC3BjF,EAAEL,WAAW6D,YAAYF,MAAM1H,GAAG;EAClCmI,YAAY/D,GAAGsD,OAAO;GACpBW,IAAI;GACJtH,SAAS;IAAEkI,MAAM;IAAQR,OAAO;GAAe;EACjD,CAAC;CACH;AACF;AAMA,MAAMa,gBAAgBlF,GAAYmF,UAAsB;CACtD,MAAMC,OAAO,CAAC,GAAGpF,EAAEjB,OAAO;CAC1B,MAAMsG,YAAYD,KAAKzE,QAAQM,MAAM,CAACA,EAAEpF,aAAa,CAACoF,EAAElF,OAAO;CAC/DiJ,WACEhF,GACAoF,KAAKzE,QAAQM,MAAMA,EAAEpF,aAAaoF,EAAElF,OAAO,CAC7C;CACAiE,EAAEjB,UAAU,CAAA;CACZiB,EAAE1B,aAAa;CAEf,MAAMsF,SAAS5D,EAAEnC,OAAO+F;CACxBuB,MAAM;CACN,IAAIvB,WAAWpB,KAAAA,KAAaxC,EAAEnC,OAAO+F,WAAWA,QAC9C/C,UAAUb,GAAG;EACX,GAAGA,EAAEnC;EACL+F,QAAQ,CAAC,GAAI5D,EAAEnC,OAAO+F,UAAU,CAAA,GAAK,GAAGA,MAAM;CAChD,CAAC;CAEH,KAAK,MAAM0B,OAAOD,WAAW;EAC3BrF,EAAEL,WAAW6D,YAAY8B,IAAI1J,GAAG;EAChC2J,aAAavF,GAAGsF,IAAI3J,SAAS2J,IAAI1J,IAAIL,QAAQ+J,IAAItJ,SAASsJ,IAAIpJ,MAAM;CACtE;CACA4I,eAAe9E,CAAC;CAChBD,QAAQC,CAAC;CACTC,KAAKD,CAAC;CACN,KAAUA,CAAC;AACb;AAEA,MAAMyF,eAAezF,GAAYiD,aAC/BiC,aAAalF,SACXa,UAAUb,GAAG;CAAEiD;CAAUyC,SAAS;CAAGX,YAAY;CAAGlF,UAAU,CAAA;AAAG,CAAC,CACpE;AAIF,MAAMqD,cAAclD,GAAY+C,WAC9BmC,aAAalF,SAAS;CACpBA,EAAEnC,SAASkF;AACb,CAAC;AAGH,MAAM4C,mBAAmB3F,MAAe;CACtCA,EAAE7B,YAAY;CACd6B,EAAE3B,eAAe;CACjBoH,YAAYzF,GAAGvD,YAAY,CAAC;AAC9B;AAEA,MAAMmJ,mBAAmBC,QAAmD;CAC1E,OAAO;EACLhB,MAAM;EACNR,OAAO;EACP,GAAIwB,IAAIC,SAAStD,KAAAA,KAAa,EAAEsD,MAAMD,IAAIC,KAAK;EAC/C,GAAID,IAAItJ,YAAYiG,KAAAA,KAAa,EAAEjG,SAASsJ,IAAItJ,QAAQ;EACxD,GAAIsJ,IAAI5J,YAAYuG,KAAAA,KAAa,EAAEvG,SAAS4J,IAAI5J,QAAQ;CAC1D;AACF;AAEA,MAAM8J,aACJF,QAGyD;CACzD,QAAQA,IAAI1B,MAAZ;EACE,KAAK,UACH,OAAO;GAAEF,IAAI;GAAMhI,SAAS5B,eAAewL,GAAG,CAAC,CAAC5J;EAAQ;EAC1D,KAAK,YACH,OAAO;GAAEgI,IAAI;GAAOtH,SAASiJ,gBAAgBvL,eAAewL,GAAG,CAAC;EAAE;EACpE,KAAK,UACH,OAAO;GACL5B,IAAI;GACJtH,SAAS;IACPkI,MAAM;IACNR,OAAO;IACP,GAAIwB,IAAItJ,YAAYiG,KAAAA,KAAa,EAAEjG,SAASsJ,IAAItJ,QAAQ;GAC1D;EACF;EACF,KAAK,WACH,OAAO;GAAE0H,IAAI;GAAOtH,SAAS;IAAEkI,MAAM;IAAWR,OAAO;GAAS;EAAE;EACpE,KAAK,WACH,OAAO;GAAEJ,IAAI;GAAOtH,SAAS;IAAEkI,MAAM;IAAWR,OAAO;GAAS;EAAE;EACpE,SACE,OAAO/H,cAAc,qBAAqB0J,OAAOH,IAAI1B,IAAI,GAAG;CAChE;AACF;AAEA,MAAM8B,qBAA0C,IAAI3E,IAAItH,QAAQ;AAEhE,MAAMkM,eAAelG,GAAY6F,QAAsB;CACrD,IAAI,CAAC7F,EAAE9B,UAAU,CAAC+H,mBAAmBxE,IAAIoE,IAAI1B,IAAK,GAAG;CACrDnE,EAAE9B,OAAOT,OAAO4C,KAAK;EACnB3E,KAAKmK,IAAInK;EACTyI,MAAM0B,IAAI1B;EACV,GAAI0B,IAAIC,SAAStD,KAAAA,KAAa,EAAEsD,MAAMD,IAAIC,KAAK;EAC/C,GAAID,IAAItJ,YAAYiG,KAAAA,KAAa,EAAEjG,SAASsJ,IAAItJ,QAAQ;EACxD,GAAIsJ,IAAI5J,YAAYuG,KAAAA,KAAa,EAAEvG,SAAS4J,IAAI5J,QAAQ;EACxD,GAAI4J,IAAIrK,SAASgH,KAAAA,KAAa,EAAEhH,MAAMqK,IAAIrK,KAAK;CACjD,CAAC;AACH;AAEA,MAAM2K,aAAanG,GAAY6F,QAAsB;CACnD,IAAI,CAACO,OAAOC,cAAcR,IAAInK,GAAG,KAAKmK,IAAInK,OAAO,GAC/CY,cAAc,yCAAyC;CAEzD,IAAIuJ,IAAIS,QAAQ,MAAM;EACpBtG,EAAE1B,aAAaiI,KAAKC,IAAIxG,EAAE1B,YAAYuH,IAAInK,GAAG;EAC7C,KAAK,MAAM4H,SAAStD,EAAEjB,SACpB,IAAIuE,MAAM5H,OAAOsE,EAAE1B,YAAYgF,MAAMxH,SAAS;CAElD;CACA,IAAI+J,IAAI1B,SAAS3B,KAAAA,GAAW;CAC5B,MAAMc,QAAQtD,EAAEjB,QAAQ0H,MAAMxF,MAAMA,EAAEvF,QAAQmK,IAAInK,GAAG;CACrD,IAAImK,IAAI1B,SAAS,WAAW;EAC1B,IAAIb,OAAOD,MAAMrD,GAAGsD,KAAK;EACzB;CACF;CACA4C,YAAYlG,GAAG6F,GAAG;CAClB,IAAI,CAACvC,OAAO;CACZD,MAAMrD,GAAGsD,KAAK;CACdS,YAAY/D,GAAGsD,OAAOyC,UAAUF,GAAG,CAAC;AACtC;AAEA,MAAMa,mBAAmB1G,MAAe;CACtC,MAAMkC,WAAWlC,EAAEnC,OAAOqE,YAAY,CAAA;CACtC,MAAMyE,2BAAW,IAAIrF,IAAY;CACjC,KAAK,MAAMsF,WAAW1E,UAAU;EAC9B,MAAMoB,QAAQtD,EAAEjB,QAAQ0H,MAAMxF,MAAMA,EAAEvF,QAAQkL,QAAQlL,GAAG;EACzD,IAAI,CAAC4H,OAAO;EACZqD,SAASE,IAAID,QAAQlL,GAAG;EACxB2H,MAAMrD,GAAGsD,KAAK;EACdS,YAAY/D,GAAGsD,OAAOyC,UAAUa,OAAuB,CAAC;CAC1D;CACA,IAAID,SAASG,SAAS,GAAG;CACzBjG,UAAUb,GAAG;EACX,GAAGA,EAAEnC;EACLgC,UAAUG,EAAEnC,OAAOgC,SAASc,QAAQa,MAAM,CAACmF,SAASlF,IAAID,EAAE9F,GAAG,CAAC;EAC9DwG,UAAUA,SAASvB,QAAQsB,MAAM,CAAC0E,SAASlF,IAAIQ,EAAEvG,GAAG,CAAC;CACvD,CAAC;CACDqE,QAAQC,CAAC;CACTC,KAAKD,CAAC;AACR;AAEA,MAAM+G,cAAc/G,GAAYgH,SAAyB;CACvD,KAAK,MAAMnB,OAAOmB,MAAMb,UAAUnG,GAAG6F,GAAG;CACxCpD,YAAYzC,CAAC;CACbC,KAAKD,CAAC;AACR;AAEA,MAAMiH,aAAajH,GAAY3D,QAAmB;CAChD,MAAMN,UAAUjC,SAASkG,EAAEhB,WAAW3C,GAAG;CACzC2D,EAAEhB,YAAYjD,QAAQmL;CACtBlH,EAAEd,QAAQmB,KAAK,GAAGtE,QAAQoL,YAAY;AACxC;AAEA,MAAMC,mBAAmBpH,MAAe;CACtCD,QAAQC,CAAC;CACTC,KAAKD,CAAC;AACR;AAKA,MAAMqH,gBAAgBrH,GAAYsH,UAAkB;CAIlD,IAAI,EAFFtH,EAAEtB,WAAW4D,OAAOd,GAAGe,MAAMf,EAAE9F,QAAQ4L,QAAQ,IAAI/E,CAAC,KACpDvC,EAAEnC,OAAOkH,eAAeuC,QAAQtH,EAAEtB,WAAWyD,SAAS,IACvC;EACftB,UAAUb,GAAG;GAAE,GAAGA,EAAEnC;GAAQkH,YAAYuC,QAAQ;EAAE,CAAC;EACnDxC,eAAe9E,CAAC;CAClB;AACF;AAMA,MAAMwH,oBAAoBxH,GAAYyH,OAAeH,UAAkB;CACrE,MAAMlC,OAAO,CAAC,GAAGpF,EAAEjB,OAAO;CAC1BiG,WAAWhF,GAAGoF,IAAI;CAClBpF,EAAEjB,UAAU,CAAA;CACZiB,EAAE1B,aAAamJ;CACf5G,UAAUb,GAAG;EACXiD,UAAUjD,EAAEnC,OAAOoF;EACnByC,SAAS+B,QAAQ;EACjB1C,YAAYuC,QAAQ;EACpBzH,UAAU,CAAA;EACV,GAAIG,EAAEnC,OAAO+F,WAAWpB,KAAAA,KAAa,EAAEoB,QAAQ5D,EAAEnC,OAAO+F,OAAO;CACjE,CAAC;CACDkB,eAAe9E,CAAC;CAChB,IACEoF,KAAKjD,SAAS,KACdnC,EAAE5C,gBAAgBgI,KAAKlE,KAAKD,MAAMA,EAAErF,GAAG,CAAC,MAAM,WAE9C,KAAK,MAAM0J,OAAOF,MAChBG,aACEvF,GACAsF,IAAI3J,SACJ2J,IAAI1J,IAAIL,cACF,CAAC,SACD,CAAC,CACT;CAGJwE,QAAQC,CAAC;CACTC,KAAKD,CAAC;AACR;AAEA,MAAM0H,eACJ1H,GACA,EAAE3D,KAAKsL,UACJ;CACH,IAAIA,IAAI9J,WAAW2E,KAAAA,KAAamF,IAAI9J,WAAW,aAC7CvB,cAAc,mBAAmB0J,OAAO2B,IAAI9J,MAAM,GAAG;CAEvDoJ,UAAUjH,GAAG3D,GAAG;CAChB2D,EAAEX,SAAS;CACXW,EAAEV,eAAe;CACjBU,EAAElB,gBAAgB;CAClBkB,EAAEzB,WAAW;CACbyB,EAAE7B,YAAYwJ,IAAI9J,WAAW;CAC7B,IAAImC,EAAE7B,WAAW6B,EAAE5B,cAAc;CACjC,MAAM,CAACwJ,WAAWC,aAAa7H,EAAEpB;CACjCoB,EAAEpB,iBAAiB,iBAAC,IAAI0C,IAAI,mBAAG,IAAIA,IAAI,CAAC;CACxC,MAAMwG,kBAAkB;EACtB,IAAI9H,EAAE9B,QAAQ6J,YAAY/H,CAAC;EAG3BA,EAAE1B,aAAaqJ,IAAIjM,OAAO;EAC1B,KAAK,MAAM4H,SAAStD,EAAEjB,SACpBuE,MAAMxH,SAAS8L,UAAUnG,IAAI6B,MAAM5H,GAAG;EAExC,MAAMsM,eAAeL,IAAIM,UAAU;EACnCjI,EAAEtB,aAAasB,EAAEtB,WAAWiC,QAAQa,MAAMA,EAAE9F,MAAMsM,YAAY;EAC9D,KAAK,MAAMxG,KAAKxB,EAAEtB,YAAY8C,EAAE1F,SAAS+L,UAAUpG,IAAID,EAAE9F,GAAG;EAC5D2L,aAAarH,GAAGgI,YAAY;EAC5BlG,iBAAiB9B,CAAC;EAClBA,EAAE3B,eAAe;CACnB;CACA,IAAI,CAAC2B,EAAE9B,UAAU8B,EAAE5B,aAAa;EAC9B0J,UAAU;EACVV,gBAAgBpH,CAAC;EACjB,KAAUA,CAAC;EACX;CACF;CACA,SAAcA,GAAG8H,SAAS,CAAC,CAACjF,WAAW;EACrCuE,gBAAgBpH,CAAC;EACjB,KAAUA,CAAC;CACb,CAAC;AACH;AAEA,MAAMkI,aACJlI,GACA,EAAE3D,KAAK2K,WACJ;CACHC,UAAUjH,GAAG3D,GAAG;CAChB,KAAK,MAAMwJ,OAAOmB,MAAMb,UAAUnG,GAAG6F,GAAG;CACxCpD,YAAYzC,CAAC;CACboH,gBAAgBpH,CAAC;AACnB;AAKA,MAAMmI,iBAAiBnI,GAAY2H,QAAsB;CACvD,MAAM,EAAEjM,KAAKuM,WAAWN;CACxB,IAAI,OAAOjM,QAAQ,UAAU;EAC3B,MAAM0M,YAAY7B,KAAKC,IAAI9K,KAAKsE,EAAE1B,UAAU;EAC5C,KAAK,MAAMgF,SAAStD,EAAEjB,SAASuE,MAAMxH,SAASwH,MAAM5H,OAAO0M;CAC7D;CACA,IAAI,OAAOH,WAAW,UAAU;EAC9BjI,EAAEtB,aAAasB,EAAEtB,WAAWiC,QAAQa,MAAMA,EAAE9F,MAAMuM,MAAM;EACxD,KAAK,MAAMzG,KAAKxB,EAAEtB,YAAY8C,EAAE1F,SAAS;CAC3C;CACA,IAAI,OAAO6L,IAAIU,UAAU,UAAU;EACjCrI,EAAEzB,WAAW+J,KAAKC,IAAI,IAAIZ,IAAIU;EAC9BpI,KAAKD,CAAC;EACN,KAAUA,CAAC;EACX;CACF;CACA,MAAMwI,WAAWxI,EAAEjB,QAAQ0H,MAAMxF,MAAM,CAACA,EAAEnF,MAAM;CAChD,MAAM2M,WAAWzI,EAAEtB,WAAW+H,MAAMjF,MAAM,CAACA,EAAE1F,MAAM;CACnD,MAAM4M,SACJ,OAAOhN,QAAQ,YACf8M,aAAahG,KAAAA,KACbgG,SAAS9M,MAAM6K,KAAKC,IAAI9K,KAAKsE,EAAE1B,UAAU,IAAI;CAC/C,MAAMqK,SACJ,OAAOV,WAAW,YAClBQ,aAAajG,KAAAA,KACbiG,SAAS/M,MAAMuM,SAAS;CAC1B,IAAIS,UAAUC,QAAQ;EACpB,SAAc3I,SAAS;GACrB,IAAI0I,QAAQlB,iBAAiBxH,GAAGtE,KAAMuM,UAAU,CAAC;QAC5CZ,aAAarH,GAAGiI,MAAO;EAC9B,CAAC,CAAC,CAACpF,WAAW;GACZ5C,KAAKD,CAAC;GACN,KAAUA,CAAC;EACb,CAAC;EACD;CACF;CACAC,KAAKD,CAAC;CACN,KAAUA,CAAC;AACb;AAEA,MAAM4I,gBAAgB5I,MAAe;CACnC,IAAIA,EAAEX,WAAW,YAAYW,EAAEX,SAAS;CACxC,IAAIW,EAAE7B,WAAWwH,gBAAgB3F,CAAC;CAClCC,KAAKD,CAAC;AACR;AAEA,MAAM6I,gBAAgB7I,GAAY,EAAE8I,aAAiC;CACnE,IAAIA,WAAW,aAAaA,WAAW,SAAS;CAChD9I,EAAEX,SAAS;CACXiF,UAAUtE,GAAG,MAAM;CACnBD,QAAQC,CAAC;CACTC,KAAKD,CAAC;AACR;AAEA,MAAM+I,cAAc/I,MAAeA,EAAEX,WAAW;AAUhD,MAAM+J,cAAcpJ,MAA6B;CAC/C,MAAMmJ,aAA2B,CAAA;CACjC,KAAK,MAAM7F,SAAStD,EAAEtB,YAAY;EAChC,IAAI4E,MAAMxH,QAAQ;EAClB,IAAIqN,WAAWhH,SAAS,KAAKmB,MAAM5H,QAAQyN,WAAWE,GAAG,EAAE,CAAC,CAAE3N,MAAM,GAClE;EACFyN,WAAW9I,KAAKiD,KAAK;CACvB;CACA,MAAM4F,aAAwB,CAAA;CAC9B,KAAK,MAAM5F,SAAStD,EAAEjB,SAAS;EAC7B,IAAIuE,MAAMxH,QAAQ;EAClB,IAAIoN,WAAW/G,SAAS,KAAKmB,MAAM5H,QAAQwN,WAAWG,GAAG,EAAE,CAAC,CAAE3N,MAAM,GAClE;EACFwN,WAAW7I,KAAKiD,KAAK;CACvB;CACA,IAAI6F,WAAWhH,WAAW,KAAK+G,WAAW/G,WAAW,GAAG,OAAO;CAC/D,OAAO;EACL8G,OAAO;GACL,GAAIE,WAAWhH,SAAS,KAAK,EAC3BpE,KAAKoL,WAAWjI,KAAKM,OAAO;IAAEnF,KAAKmF,EAAEnF;IAAKX,KAAK8F,EAAE9F;GAAI,EAAE,EACzD;GACA,GAAIwN,WAAW/G,SAAS,KAAK,EAC3B0D,KAAKqD,WAAWhI,KAAKD,OAAO;IAAE,GAAGA,EAAEtF;IAASD,KAAKuF,EAAEvF;GAAI,EAAE,EAC3D;EACF;EACAwN;EACAC;CACF;AACF;AAEA,MAAMG,mBAAmBtJ,MAAsC;CAC7DA,EAAEpB,iBAAiB,iBAAC,IAAI0C,IAAI,mBAAG,IAAIA,IAAI,CAAC;CACxC,MAAMiI,SAASvJ,EAAErB;CACjBqB,EAAErB,gBAAgB;CAClB,IAAI,CAAC4K,UAAU,CAACvJ,EAAE3B,cAAc,OAAO;CACvC,MAAMmL,QAAQJ,WAAWpJ,CAAC;CAC1B,IAAI,CAACwJ,OAAO,OAAO;CACnBxJ,EAAEpB,iBAAiB,CACjB,IAAI0C,IAAIkI,MAAMN,WAAWhI,KAAKD,MAAMA,EAAEvF,GAAG,CAAC,GAC1C,IAAI4F,IAAIkI,MAAML,WAAWjI,KAAKM,MAAMA,EAAE9F,GAAG,CAAC,CAAC;CAE7C,KAAK,MAAM4H,SAASkG,MAAMN,YAAY5F,MAAMzH,YAAY;CACxD,OAAO2N,MAAMP;AACf;AAEA,MAAMzD,OAAO,OAAOxF,MAAe;CACjC,IAAIA,EAAER,SAAS;CACfQ,EAAER,UAAU;CACZ,IAAI;EACF,OAAOQ,EAAET,WAAW,CAACwJ,WAAW/I,CAAC,GAAG;GAClC,MAAMP,YAAYO,EAAEP;GACpB,IAAI2J,WAAWpJ,CAAC,MAAM,MAAM;GAC5B,IAAIA,EAAEX,WAAW,cAAc,CAACI,WAAW;IACzC,IACGA,WAAWgK,WAAWC,WAAW,kBAChCjK,UAAUgK,WAAWX,WAAW,UACjCrJ,WAAWhC,UAAUuC,EAAEjB,QAAQoD,SAAS,GAEzC1C,UAAUgK,WAAWE,UAAU;IAEjC,MAAMxJ,YAAYH,CAAC;IACnB;GACF;GACA,MAAM4J,cAAc5J,EAAEzB,WAAW+J,KAAKC,IAAI;GAC1C,IAAIqB,cAAc,GAAG;IACnB,MAAMtJ,eAAeN,GAAG4J,WAAW;IACnC;GACF;GACA,MAAMJ,QAAQJ,WAAWpJ,CAAC;GAC1B,IAAI,CAACwJ,OAAO;GACZ,MAAMK,QAAQ7J,EAAEV;GAChB,KAAK,MAAMgE,SAASkG,MAAMN,YAAY5F,MAAMzH,YAAY;GACxD,IAAIiB;GACJ,IAAI;IAGF,MAAMgN,aAAarK,UAAUqK,KAAKN,MAAMP,KAAK;IAC7CnM,SAAS,OAAOkD,EAAE9B,UAAU,CAAC8B,EAAE5B,cAC3B4B,EAAE/B,MAAM6E,KAAMgH,IAAI,IAClBA,KAAK;GACX,QAAQ;IACN,IAAI,CAAC9J,EAAET,WAAWwJ,WAAW/I,CAAC,GAAG;IACjCA,EAAElB,iBAAiB;IACnB,MAAMwB,eAAeN,GAAGlF,QAAQkF,EAAElB,aAAa,CAAC;IAChD;GACF;GACA,IAAI,CAACkB,EAAET,SAAS;GAChBS,EAAElB,gBAAgB;GAClB,IAAIhC,OAAOqH,SAAS,MACd0F;QAAAA,UAAU7J,EAAEV,aAAa;KAC3B,KAAK,MAAMgE,SAASkG,MAAMN,YACxB,IAAIlJ,EAAEjB,QAAQgL,SAASzG,KAAK,GAAG;MAC7BA,MAAMxH,SAAS;MACfkE,EAAEL,WAAWqK,WAAW1G,MAAM1H,GAAG;KACnC;KAEF,KAAK,MAAM0H,SAASkG,MAAML,YAAY7F,MAAMxH,SAAS;IACvD;UACK,IAAIgB,OAAOqH,SAAS,WACrB0F;QAAAA,UAAU7J,EAAEV,aAAa6I,cAAcnI,GAAGlD,OAAO6K,GAAG;GAAA,OACnD,IAAI7K,OAAOqH,SAAS,eAErB0F;QAAAA,UAAU7J,EAAEV,aAAa;KAC3BG,UAAUgK,WAAWE,UAAU;KAC/B,MAAMxJ,YAAYH,CAAC;IACrB;UACK,IAAIlD,OAAOqH,SAAS,YAErB0F;QAAAA,UAAU7J,EAAEV,aAAa;KAC3BU,EAAErB,gBAAgB;KAClBc,UAAUgK,WAAWE,UAAU;KAC/B,OAAO3J,EAAET,WAAW,CAACwJ,WAAW/I,CAAC,KAAK6J,UAAU7J,EAAEV,aAChD,MAAMa,YAAYH,CAAC;IAEvB;;EAEJ;CACF,UAAU;EACRA,EAAER,UAAU;CACd;AACF;AAEA,MAAMyK,SAASjK,MAAe;CAC5B,IAAIA,EAAE9B,QAAQ;EACZ8B,EAAE9B,OAAOP,cAAcqC,EAAE/B,MAAMiM,gBAAiB;GAC9C,SAAclK,SAAS0G,gBAAgB1G,CAAC,CAAC;EAC3C,CAAC;EACDA,EAAET,UAAU;EACZ,SAAcS,SAAS;GACrB,IAAIA,EAAE/B,MAAM+E,KAAK,MAAM,MAAMhD,EAAE/B,MAAM6C,KAAKd,EAAEnC,MAAM;GAClDmC,EAAEhC,kBAAkB;GACpB+J,YAAY/H,CAAC;GACb0G,gBAAgB1G,CAAC;EACnB,CAAC,CAAC,CAAC6C,WAAW,KAAK2C,KAAKxF,CAAC,CAAC;EAC1B;CACF;CACA,IAAI,CAACA,EAAEhC,iBAAiB;EACtBgC,EAAEhC,kBAAkB;EACpBgC,EAAE/B,MAAM6C,KAAKd,EAAEnC,MAAM;CACvB;CACAkK,YAAY/H,CAAC;CACbA,EAAET,UAAU;CACZ,KAAUS,CAAC;AACb;AAEA,MAAMmK,QAAQnK,MAAe;CAC3BA,EAAET,UAAU;CACZ,IAAIS,EAAE9B,QAAQ;EACZ8B,EAAE9B,OAAOP,cAAc;EACvBqC,EAAE9B,OAAOP,cAAc;CACzB;CACAsC,KAAKD,CAAC;CACNsE,UAAUtE,GAAG,SAAS;AACxB;AAEA,MAAMoK,gBAAgBpK,GAAYP,cAA0B;CAC1D,IAAIO,EAAEP,cAAcA,WAAW;CAC/BO,EAAEP,YAAYA;CACdQ,KAAKD,CAAC;AACR;AAEA,MAAMuF,gBACJvF,GACArE,SACAJ,QACAS,SACAE,WACG;CACH,MAAMR,MAAMsE,EAAEnC,OAAO6H;CACrB,MAAMpC,QAAiB;EACrB5H;EACAC;EACAC,KAAK;GACHN,QAAQK,QAAQL;GAChBC;GACAuI,IAAIwE,KAAKC,IAAI;GACb7M;GACAuH,UAAUjD,EAAEnC,OAAOoF;EACrB;EACApH,WAAW;EACXC,QAAQ;EACRC,SAAS;EACTC;EACAE;CACF;CACA8D,EAAEjB,QAAQsB,KAAKiD,KAAK;CACpBzC,UAAUb,GAAG;EAAE,GAAGA,EAAEnC;EAAQ6H,SAAShK,MAAM;EAAGmE,UAAUsB,aAAanB,CAAC;CAAE,CAAC;CACzEA,EAAEL,WAAW0K,QAAQ/G,MAAM1H,GAAG;AAChC;AAEA,MAAM0O,WACJtK,GACArE,SACAJ,QACAS,SACAE,WACG;CACH,IAAI,CAAC8D,EAAE9B,QAAQ;EACbqH,aAAavF,GAAGrE,SAASJ,QAAQS,SAASE,MAAM;EAChD+D,KAAKD,CAAC;EACN,KAAUA,CAAC;EACX;CACF;CACA,SAAcA,SACZuF,aAAavF,GAAGrE,SAASJ,QAAQS,SAASE,MAAM,CAClD,CAAC,CAAC2G,WAAW;EACX5C,KAAKD,CAAC;EACN,KAAUA,CAAC;CACb,CAAC;AACH;AAIA,MAAM+H,eAAe/H,MAAe;CAClC,MAAMqB,QAAQ,IAAIC,IAAItB,EAAEjB,QAAQmC,KAAKD,MAAMA,EAAEvF,GAAG,CAAC;CACjD,MAAMqH,SAAS/C,EAAEnC,OAAOgC,SAASc,QAAQa,MAAM,CAACH,MAAMI,IAAID,EAAE9F,GAAG,CAAC;CAChE,IAAIqH,OAAOZ,WAAW,GAAG;CACzB,KAAK,MAAM,EAAEzG,KAAK,GAAGC,aAAaoH,QAAQ;EACxC,MAAMxH,SACJI,QAAQH,SAASgH,KAAAA,IACb7G,QAAQJ,SACPjB,YAAY,CAAC,GAAGqB,QAAQJ,MAAM,GAAGI,QAAQH,IAAI;EACpD,MAAM8H,QAAiB;GACrB5H;GACAC;GACAC,KAAK;IACHN,QAAQK,QAAQL;IAChBC;IACAuI,IAAIwE,KAAKC,IAAI;IACb7M;IACAuH,UAAUjD,EAAEnC,OAAOoF;GACrB;GACApH,WAAW;GACXC,QAAQ;GACRC,SAAS;GACTC,eAAe,CAAC;GAChBE,cAAc,CAAC;EACjB;EACA8D,EAAEjB,QAAQsB,KAAKiD,KAAK;EACpBtD,EAAEL,WAAW0K,QAAQ/G,MAAM1H,GAAG;CAChC;CACAoE,EAAEjB,QAAQ2C,MAAMC,GAAGC,MAAMD,EAAEjG,MAAMkG,EAAElG,GAAG;AACxC;AAEA,MAAM6O,eACJvK,GACA1E,QACAC,WACqB;CACrB,IAAI,CAACyE,EAAET,SACL,OAAO7C,aAAa;EAAEmI,MAAM;EAAWR,OAAO;CAAU,CAAC;CAE3D,IAAI0E,WAAW/I,CAAC,GACd,OAAOtD,aAAa;EAAEmI,MAAM;EAAWR,OAAO;CAAc,CAAC;CAE/D,MAAMvH,SAAS,IAAID,SAAkBb,SAASE,WAAW;EACvD,MAAM,EAAEX,QAAQiP,SAAShP,SAASrB,aAAaoB,MAAM;EACrD+O,QACEtK,GACA;GAAE1E;GAAQC,QAAQiP;GAAS,GAAIhP,SAASgH,KAAAA,KAAa,EAAEhH,KAAK;EAAG,GAC/DD,QACAS,SACAE,MACF;CACF,CAAC;CACDY,OAAOC,YAAY,CAAC,CAAC;CACrB,OAAOD;AACT;AAEA,MAAM2N,cACJzK,GACAsD,UACkC;CAClC,MAAMM,SAAS5D,EAAEnC,OAAO+F,UAAU,CAAA;CAClC,MAAM8G,QAAQ9G,OAAO6C,MAClBkE,MACCA,EAAEjP,QAAQ4H,MAAM5H,OAAOiP,EAAE7G,OAAOR,MAAMQ,MAAM6G,EAAEhP,YAAY2H,MAAM3H,OACpE;CACA,IAAI+O,UAAUlI,KAAAA,GACZ,MAAM,IAAIhG,MAAM,sCAAsC8G,MAAM3H,QAAO,EAAG;CAExEkF,UAAUb,GAAG;EAAE,GAAGA,EAAEnC;EAAQ+F,QAAQA,OAAOjD,QAAQgK,MAAMA,MAAMD,KAAK;CAAE,CAAC;CACvE1K,EAAEJ,OAAO;CACT,OAAO8K;AACT;AAEA,MAAaE,iBACX5K,GACAsD,UACS;CACTmH,WAAWzK,GAAGsD,KAAK;AACrB;AAEA,MAAauH,eACX7K,GACAsD,UACqB;CACrB,IAAI,CAACtD,EAAET,SACL,OAAO7C,aAAa;EAAEmI,MAAM;EAAWR,OAAO;CAAU,CAAC;CAE3D,IAAI0E,WAAW/I,CAAC,GACd,OAAOtD,aAAa;EAAEmI,MAAM;EAAWR,OAAO;CAAc,CAAC;CAE/D,MAAMqG,QAAQD,WAAWzK,GAAGsD,KAAK;CACjC,MAAM/H,SACJmP,MAAMlP,SAASgH,KAAAA,IACXkI,MAAMnP,SACLjB,YAAY,CAAC,GAAGoQ,MAAMnP,MAAM,GAAGmP,MAAMlP,IAAI;CAChD,MAAMsB,SAAS,IAAID,SAAkBb,SAASE,WAAW;EACvDoO,QACEtK,GACA;GACE1E,QAAQoP,MAAM/O;GACdJ,QAAQ,CAAC,GAAGmP,MAAMnP,MAAM;GACxB,GAAImP,MAAMlP,SAASgH,KAAAA,KAAa,EAAEhH,MAAMkP,MAAMlP,KAAK;EACrD,GACAD,QACAS,SACAE,MACF;CACF,CAAC;CACDY,OAAOC,YAAY,CAAC,CAAC;CACrB,OAAOD;AACT;AAEA,MAAMgO,cAAc9K,GAAY+K,UAAyC;CACvE,IAAI,OAAOA,UAAU,YAAYA,UAAU,QAAQC,MAAMC,QAAQF,KAAK,GACpE,MAAM,IAAIvO,MAAM,2CAA2C;CAE7D,IAAI,CAACwD,EAAET,WAAWwJ,WAAW/I,CAAC,GAAG;CACjC,MAAM,EAAE+K,OAAOP,SAAShP,SAASpB,YAAY2Q,KAAK;CAClD,MAAM1O,MAAM,CACV;EACE6O,IAAI;EACJC,MAAM,CAAA;EACNJ,OAAOP;EACP,GAAIhP,SAASgH,KAAAA,KAAa,EAAEhH,KAAK;CACnC,CAAC;CAEHwE,EAAEvB,SAASpC;CACX,MAAM+O,aAAa;EACjB,MAAM1P,MAAMsE,EAAEnC,OAAOkH;EACrBlE,UAAUb,GAAG;GAAE,GAAGA,EAAEnC;GAAQkH,YAAYrJ,MAAM;EAAE,CAAC;EACjDsE,EAAEtB,WAAW2B,KAAK;GAAE3E;GAAKW;GAAKP,QAAQ;EAAM,CAAC;CAC/C;CACA,IAAI,CAACkE,EAAE9B,QAAQ;EACbkN,KAAK;EACLnL,KAAKD,CAAC;EACN,KAAUA,CAAC;EACX;CACF;CACA,SAAcA,GAAGoL,IAAI,CAAC,CAACvI,WAAW;EAChC5C,KAAKD,CAAC;EACN,KAAUA,CAAC;CACb,CAAC;AACH;AAEA,MAAaqL,uBACXC,YACY;CACZ,MAAM,CAACC,gBAAgB1R,SAASgB,wBAAwB;CACxD,MAAM2Q,UAAU7R,WAAWiB,qBAAqB;CAChD,IAAI0Q,QAAQpO,iBAAiBsF,KAAAA,KAAagJ,YAAYhJ,KAAAA,GACpD,MAAM,IAAIhG,MACR,6GACF;CAEF,MAAMyB,QAAQqN,QAAQpO,gBAAgBsO,WAAWD;CACjD,IAAKtN,MAAM6E,SAASN,KAAAA,OAAgBvE,MAAMiM,cAAc1H,KAAAA,IACtD,MAAM,IAAIhG,MACR,qEACF;CAEF,MAAM,CAACwD,KAAKnG,eAAwB;EAClC,MAAMkJ,SAAS9E,MAAM+E,KAAK;EAC1B,IAAID,WAAW,QAAQ,CAACiI,MAAMC,QAAQlI,OAAOlD,QAAQ,GACnD,MAAM,IAAIrD,MACR,qEACF;EAQF,MAAMiP,UAAmB;GACvB5N,QAPakF,UAAU;IACvBE,UAAUxG,YAAY;IACtBiJ,SAAS;IACTX,YAAY;IACZlF,UAAU,CAAA;GACZ;GAGE9B,KAAK;IACH,IAAIkF,WAAW;KACb,OAAOwI,QAAQ5N,OAAOoF;IACxB;IACAqG,uBAAuBA,gBAAgBmC,OAAO;IAC9CC,UAAUC,SAASjE,YAAY+D,SAASE,IAAI;IAC5CC,QAAQD,WAASzD,UAAUuD,SAASE,MAAI;IACxCE,SAAS7E,SAASD,WAAW0E,SAASzE,IAAI;IAC1C8E,YAAYnE,QAAQQ,cAAcsD,SAAS9D,GAAG;IAC9CoE,SAAS3I,UAAUD,QAAQsI,SAASrI,KAAK;IACzC4I,gBAAgBpD,aAAa6C,OAAO;IACpCQ,WAAWN,WAAS9C,aAAa4C,SAASE,MAAI;GAChD;GACA3N,iBAAiB+E,WAAW;GAC5B9E;GACAC,QACED,MAAM6E,SAASN,KAAAA,IACX;IAAEhF,KAAKX,QAAQb,QAAQ;IAAGyB,QAAQ,CAAA;IAAIE,aAAa;GAAK,IACxD;GACNQ,WAAW;GACXC,aAAa;GACbC,cAAc;GACdC,YAAY;GACZC,UAAU;GACVC,MAAM;GACNpB,eAAeoF,KAAAA;GACflF,QAAQkF,KAAAA;GACR/D,QAAQ+D,KAAAA;GACR9D,YAAY,CAAA;GACZC,eAAe;GACfC,gBAAgB,iBAAC,IAAI0C,IAAI,mBAAG,IAAIA,IAAI,CAAC;GACrCxC,eAAe;GACfC,SAAS,CAAA;GACTC,WAAWwD,KAAAA;GACXvD,eAAeuD,KAAAA;GACftD,SAAS,CAAA;GACTC,QAAQ;IACN+M,gBAAgBT,QAAQzM;IACxBmN,mBAAmB;KACjB,MAAMjN,UAAUuM,QAAQvM;KACxBuM,QAAQvM,UAAU,CAAA;KAClB,OAAOA;IACT;IACAkN,cAAcC,aAAa;KACzBZ,QAAQ7L,SAASyM,mBAAmB,CAAC;IACvC;GACF;GACAhN,QAAQ;GACRC,aAAa;GACbC,SAAS;GACTC,SAAS;GACTC,WAAW;GACXC,SAAS,CAAA;GACTC,WAAW;GACXC,cAAc,CAAC;GACfC,UAAU9E,mBAAmBO,QAAQC,WACnCgP,YAAYkB,SAASnQ,QAAQC,MAAM,CACrC;EACF;EACAhB,iBAAiBkR,QAAQ5L,UAAU,EACjCyM,cAAcD,eAAa;GACzBZ,QAAQ9L,YAAY0M;EACtB,EACF,CAAC;EACD,OAAOZ;CACT,CAAC;CACD,IAAKxN,MAAM6E,SAASN,KAAAA,OAAgBxC,EAAE9B,WAAW,QAC/C,MAAM,IAAI1B,MACR,8HACF;CAEFwD,EAAE/B,QAAQA;CACV+B,EAAE5C,gBAAgBkO,QAAQlO;CAC1B4C,EAAE1C,SAASgO,QAAQhO;CACnB1D,gBAAgB;EACdqQ,MAAMjK,CAAC;EACP,aAAamK,KAAKnK,CAAC;CACrB,GAAG,CAACA,CAAC,CAAC;CACN,OAAOA;AACT"}
|
|
1
|
+
{"version":3,"file":"session.js","names":["applyDocumentOps","StatewireDocuments","useContext","useEffect","useState","StatewirePath","MAX_COMMANDS_PER_FRAME","TERMINAL","StatewireCmd","StatewireSyn","encodeParams","encodeValue","reviveResponse","reviveValue","bindCommandsHost","CommandsInvocation","CommandsListener","Statewire","StatewireClient","SessionStorageContext","createMemorySessionStore","backoff","createMethodProxy","randomId","StatewireSendError","RemoteLink","StatewireFrame","StatewireRemoteProps","WireCommand","method","params","meta","Pending","seq","command","inv","attempted","posted","applied","resolve","payload","reject","error","CtxPending","ops","protocolError","message","Error","newClientId","rejectedSend","failure","SendFailure","Promise","result","catch","AttachState","StatewireSessionOptions","sessionStore","SessionStorage","onSessionLost","OnSessionLost","onDone","Shared","txq","parked","SessionVerdict","unsubscribe","Session","record","SessionRecord","ctx","recordPersisted","store","shared","ephemeral","deactivated","sessionKnown","durableSeq","resumeAt","idle","ctxOps","ctxPending","lanesOnAttach","attachLaneSeqs","ReadonlySet","frameFailures","pending","canonical","documents","State","lastPublished","changed","source","StateSource","attach","attachEpoch","running","pumping","transport","waiters","lifecycle","notify","commands","Record","publish","s","wake","waiter","waitForWake","r","push","sleepUntilWake","delayMs","clearTimeout","timer","setTimeout","filter","w","setRecord","save","backlog","SessionCommand","p","map","mergeBacklog","own","known","Set","foreign","c","has","sort","a","b","MAX_PARKED_VERDICTS","syncBacklogInner","splice","parkedSeqs","v","verdicts","length","slice","unchanged","every","i","undefined","syncBacklog","transact","fn","run","then","lock","stored","load","clientId","adoptReset","setIdle","level","cover","entry","onApplied","onCovered","NO_FAILED","FailedCommand","failedCommands","failed","retainFailedInner","ts","retainFailed","settleEntry","outcome","ok","onSettle","type","rides","cause","settleAll","detach","const","batch","detachFailure","predecessorLost","some","fate","restateContext","ctxNextSeq","settleLost","entries","rebaseRecord","adopt","held","survivors","old","enqueueInner","pump","resetRecord","nextSeq","ephemeralDetach","rejectedFailure","cmd","code","outcomeOf","String","TERMINAL_CMD_TYPES","parkVerdict","handleCmd","Number","isSafeInteger","dur","Math","max","find","consumeVerdicts","consumed","verdict","add","size","handleCmds","cmds","ingestOps","get","value","changedPaths","publishIngested","snapCtxClock","ctxWm","ctxAligned","sessionLostInner","seqWm","handleHello","syn","mode","Map","attachCmd","attachCtx","reconcile","adoptStored","ctxWatermark","ctxSeq","handleOps","handleRefusal","watermark","retry","Date","now","firstCmd","firstCtx","cmdGap","ctxGap","handleDetach","handleFinish","reason","isFinished","Lanes","frame","cmdEntries","ctxEntries","buildLanes","at","takeAttachLanes","wanted","lanes","connection","status","reconnect","resumeDelay","epoch","send","includes","onPosted","start","subscribe","stop","setTransport","onStart","enqueue","sendCommand","encoded","findFailed","f","unknownFailed","takeFailed","found","discardFailed","retryFailed","current","setContext","Array","isArray","op","path","mint","useStatewireSession","options","defaultStore","mounted","session","onHello","args","onOps","onCmds","onRefusal","onIdle","onDetach","onFinish","snapshot","takeChanged","setOnChange","listener","setListener"],"sources":["../../src/client/session.ts"],"sourcesContent":["import { applyDocumentOps } from \"../wire/documents\";\nimport type { StatewireDocuments } from \"../wire/documents\";\nimport { useContext, useEffect, useState } from \"react\";\n\nimport type { StatewirePath } from \"../wire/ops\";\nimport { MAX_COMMANDS_PER_FRAME } from \"../wire/limits\";\nimport { TERMINAL } from \"./connection\";\nimport type { StatewireCmd, StatewireSyn } from \"./connection\";\nimport {\n encodeParams,\n encodeValue,\n reviveResponse,\n reviveValue,\n} from \"../wire/meta\";\nimport { bindCommandsHost } from \"../host/host\";\nimport type { CommandsInvocation, CommandsListener } from \"../host/host\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireClient } from \"../statewire\";\nimport {\n SessionStorageContext,\n createMemorySessionStore,\n} from \"./sessionStore\";\nimport { backoff } from \"./timing\";\nimport { createMethodProxy } from \"../util/methodProxy\";\nimport { randomId } from \"../util/randomId\";\nimport { StatewireSendError } from \"../types\";\nimport type {\n RemoteLink,\n StatewireFrame,\n StatewireRemoteProps,\n} from \"../transports/sse\";\n\ntype WireCommand = {\n method: string;\n params: unknown[];\n meta?: unknown;\n};\n\ntype Pending = {\n readonly seq: number;\n readonly command: WireCommand;\n readonly inv: CommandsInvocation;\n /** A send carrying this statement may have reached the server. */\n attempted: boolean;\n /** In the resend queue when false. */\n posted: boolean;\n /** The server acknowledged admission; the terminal verdict is still due. */\n applied: boolean;\n resolve: (payload: unknown) => void;\n reject: (error: StatewireSendError) => void;\n};\n\ntype CtxPending = {\n readonly seq: number;\n readonly ops: unknown[];\n posted: boolean;\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst newClientId = () => `c-${randomId()}`;\n\nconst rejectedSend = (\n failure: StatewireClient.SendFailure,\n): Promise<unknown> => {\n const result = Promise.reject<unknown>(new StatewireSendError(failure));\n result.catch(() => {});\n return result;\n};\n\ntype AttachState = \"detached\" | \"attached\" | \"finished\";\n\nexport type StatewireSessionOptions = {\n sessionStore?: StatewireClient.SessionStorage | undefined;\n onSessionLost?: StatewireClient.OnSessionLost | undefined;\n onDone?: (() => void) | undefined;\n};\n\ntype Shared = {\n txq: Promise<void>;\n parked: StatewireClient.SessionVerdict[];\n unsubscribe: (() => void) | null;\n};\n\ntype Session = {\n record: StatewireClient.SessionRecord;\n ctx: StatewireRemoteProps;\n recordPersisted: boolean;\n store: StatewireClient.SessionStorage;\n shared: Shared | false;\n ephemeral: boolean;\n /** An ephemeral record died with its attach: the storage is off for good. */\n deactivated: boolean;\n sessionKnown: boolean;\n durableSeq: number;\n resumeAt: number;\n idle: boolean;\n onSessionLost: StatewireClient.OnSessionLost | undefined;\n onDone: (() => void) | undefined;\n ctxOps: unknown[] | undefined;\n ctxPending: CtxPending[];\n lanesOnAttach: boolean;\n attachLaneSeqs: readonly [ReadonlySet<number>, ReadonlySet<number>];\n frameFailures: number;\n pending: Pending[];\n canonical: unknown;\n documents: StatewireDocuments.State;\n lastPublished: unknown;\n changed: StatewirePath[];\n source: Statewire.StateSource;\n attach: AttachState;\n attachEpoch: number;\n running: boolean;\n pumping: boolean;\n transport: RemoteLink | null;\n waiters: (() => void)[];\n lifecycle: CommandsListener | null;\n notify: () => void;\n commands: Record<string, (...params: unknown[]) => Promise<unknown>>;\n};\n\nconst publish = (s: Session) => {\n if (s.canonical === s.lastPublished) return;\n s.lastPublished = s.canonical;\n s.notify();\n};\n\nconst wake = (s: Session) => {\n const waiters = s.waiters;\n s.waiters = [];\n for (const waiter of waiters) waiter();\n};\n\nconst waitForWake = (s: Session) => new Promise<void>((r) => s.waiters.push(r));\n\nconst sleepUntilWake = (s: Session, delayMs: number) =>\n new Promise<void>((resolve) => {\n const waiter = () => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(() => {\n s.waiters = s.waiters.filter((w) => w !== waiter);\n resolve();\n }, delayMs);\n s.waiters.push(waiter);\n });\n\nconst setRecord = (s: Session, record: StatewireClient.SessionRecord) => {\n s.record = record;\n if (!s.deactivated) s.store.save(record);\n};\n\nconst backlog = (s: Session): StatewireClient.SessionCommand[] =>\n s.pending\n .filter((p) => p.seq > s.durableSeq)\n .map((p) => ({ seq: p.seq, ...p.command }));\n\nconst mergeBacklog = (s: Session): StatewireClient.SessionCommand[] => {\n const own = backlog(s);\n if (!s.shared) return own;\n const known = new Set(s.pending.map((p) => p.seq));\n const foreign = s.record.commands.filter(\n (c) => !known.has(c.seq) && c.seq > s.durableSeq,\n );\n return [...foreign, ...own].sort((a, b) => a.seq - b.seq);\n};\n\nconst MAX_PARKED_VERDICTS = 64;\n\n// Storage holds what a reload must resend: a command leaves at its dur, at a\n// server verdict, or at a record reset — never at a local channel death.\nconst syncBacklogInner = (s: Session) => {\n const parked = s.shared ? s.shared.parked.splice(0) : [];\n const parkedSeqs = new Set(parked.map((v) => v.seq));\n const commands = mergeBacklog(s).filter((c) => !parkedSeqs.has(c.seq));\n const verdicts =\n parked.length > 0\n ? [...(s.record.verdicts ?? []), ...parked].slice(-MAX_PARKED_VERDICTS)\n : s.record.verdicts;\n const unchanged =\n verdicts === s.record.verdicts &&\n commands.length === s.record.commands.length &&\n commands.every((c, i) => c.seq === s.record.commands[i]!.seq);\n if (unchanged) return;\n setRecord(s, {\n ...s.record,\n commands,\n ...(verdicts !== undefined && { verdicts }),\n });\n};\n\nconst syncBacklog = (s: Session) => {\n if (!s.shared) return syncBacklogInner(s);\n void transact(s, () => syncBacklogInner(s));\n};\n\n// Every record mutation over shared storage is a locked read-modify-write.\nconst transact = (s: Session, fn: () => void): Promise<void> => {\n if (!s.shared || s.deactivated) {\n fn();\n return Promise.resolve();\n }\n const shared = s.shared;\n const run = shared.txq.then(() =>\n s.store.lock!(async () => {\n const stored = s.store.load();\n if (stored !== null && stored.clientId !== s.record.clientId) {\n adoptReset(s, stored);\n } else if (stored !== null) {\n s.record = stored;\n }\n fn();\n }),\n );\n shared.txq = run.then(\n () => {},\n () => {},\n );\n return run;\n};\n\nconst setIdle = (s: Session, level: boolean) => {\n if (level === s.idle) return;\n s.idle = level;\n s.notify();\n if (level) s.onDone?.();\n};\n\nconst cover = (s: Session, entry: Pending) => {\n if (entry.applied) return;\n entry.applied = true;\n s.lifecycle?.onApplied(entry.inv);\n s.lifecycle?.onCovered?.(entry.inv);\n};\n\nconst NO_FAILED: readonly StatewireClient.FailedCommand[] = [];\n\nexport const failedCommands = (\n s: Session,\n): readonly StatewireClient.FailedCommand[] => s.record.failed ?? NO_FAILED;\n\nconst retainFailedInner = (\n s: Session,\n entry: Pending,\n failure: StatewireClient.SendFailure,\n) => {\n setRecord(s, {\n ...s.record,\n failed: [\n ...(s.record.failed ?? []),\n {\n command: entry.command.method,\n params: entry.command.params,\n ...(entry.command.meta !== undefined && { meta: entry.command.meta }),\n failure,\n ts: entry.inv.ts,\n seq: entry.seq,\n },\n ],\n });\n s.notify();\n};\n\nconst retainFailed = (\n s: Session,\n entry: Pending,\n failure: StatewireClient.SendFailure,\n) => {\n if (!s.shared) {\n retainFailedInner(s, entry, failure);\n return;\n }\n void transact(s, () => retainFailedInner(s, entry, failure));\n};\n\nconst settleEntry = (\n s: Session,\n entry: Pending,\n outcome:\n | { ok: true; payload: unknown }\n | { ok: false; failure: StatewireClient.SendFailure },\n) => {\n s.pending = s.pending.filter((p) => p !== entry);\n if (outcome.ok) {\n entry.resolve(outcome.payload);\n s.lifecycle?.onSettle(entry.inv, {\n type: \"accepted\",\n payload: outcome.payload,\n });\n } else {\n // A statement the record still carries resends on the next attach; only\n // invocations the record no longer owns become failed history.\n const rides =\n (outcome.failure.cause === \"unmount\" ||\n outcome.failure.cause === \"stream-gone\") &&\n entry.seq > s.durableSeq;\n if (!rides) retainFailed(s, entry, outcome.failure);\n entry.reject(new StatewireSendError(outcome.failure));\n s.lifecycle?.onSettle(entry.inv, {\n type: \"rejected\",\n error: new StatewireSendError(outcome.failure),\n });\n }\n};\n\nconst settleAll = (s: Session, detach: \"unmount\" | \"gone\") => {\n const cause =\n detach === \"unmount\" ? (\"unmount\" as const) : (\"stream-gone\" as const);\n const batch = s.pending;\n const detachFailure = (entry: Pending): StatewireClient.SendFailure => {\n if (!entry.attempted) {\n const predecessorLost = batch.some(\n (p) => p.seq < entry.seq && p.attempted,\n );\n return predecessorLost\n ? { fate: \"aborted\", cause, predecessorLost }\n : { fate: \"aborted\", cause };\n }\n return { fate: \"lost\", cause };\n };\n for (const entry of [...batch]) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, { ok: false, failure: detachFailure(entry) });\n }\n};\n\nconst restateContext = (s: Session) => {\n s.ctxPending = [];\n if (s.ctxOps === undefined) return;\n const seq = s.record.ctxNextSeq;\n setRecord(s, { ...s.record, ctxNextSeq: seq + 1 });\n s.ctxPending.push({ seq, ops: s.ctxOps, posted: false });\n};\n\nconst settleLost = (s: Session, entries: Pending[]) => {\n for (const entry of entries) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, {\n ok: false,\n failure: { fate: \"lost\", cause: \"session-lost\" },\n });\n }\n};\n\n// The server-side record's dedup memory is gone: history that may have\n// reached a server settles lost — the new hello's snapshot is the only\n// truth about what survived — and never-attempted statements re-stamp\n// on the adopted lane clocks.\nconst rebaseRecord = (s: Session, adopt: () => void) => {\n const held = [...s.pending];\n const survivors = held.filter((p) => !p.attempted && !p.applied);\n settleLost(\n s,\n held.filter((p) => p.attempted || p.applied),\n );\n s.pending = [];\n s.durableSeq = 0;\n // Failed entries are user-owned history: they ride through every record replacement.\n const failed = s.record.failed;\n adopt();\n if (failed !== undefined && s.record.failed !== failed) {\n setRecord(s, {\n ...s.record,\n failed: [...(s.record.failed ?? []), ...failed],\n });\n }\n for (const old of survivors) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueueInner(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n restateContext(s);\n publish(s);\n wake(s);\n void pump(s);\n};\n\nconst resetRecord = (s: Session, clientId: string) =>\n rebaseRecord(s, () =>\n setRecord(s, { clientId, nextSeq: 1, ctxNextSeq: 1, commands: [] }),\n );\n\n// Another sharer replaced the record's identity: their reset settles our\n// attempted history and our survivors re-stamp on the stored clocks.\nconst adoptReset = (s: Session, stored: StatewireClient.SessionRecord) =>\n rebaseRecord(s, () => {\n s.record = stored;\n });\n\n// The record died with the attach: mint a fresh id for the next one.\nconst ephemeralDetach = (s: Session) => {\n s.ephemeral = false;\n s.sessionKnown = false;\n resetRecord(s, newClientId());\n};\n\nconst rejectedFailure = (cmd: StatewireCmd): StatewireClient.SendFailure => {\n return {\n fate: \"rejected\",\n cause: \"server\",\n ...(cmd.code !== undefined && { code: cmd.code }),\n ...(cmd.message !== undefined && { message: cmd.message }),\n ...(cmd.payload !== undefined && { payload: cmd.payload }),\n };\n};\n\nconst outcomeOf = (\n cmd: StatewireCmd,\n):\n | { ok: true; payload: unknown }\n | { ok: false; failure: StatewireClient.SendFailure } => {\n switch (cmd.type) {\n case \"result\":\n return { ok: true, payload: reviveResponse(cmd).payload };\n case \"rejected\":\n return { ok: false, failure: rejectedFailure(reviveResponse(cmd)) };\n case \"failed\":\n return {\n ok: false,\n failure: {\n fate: \"failed\",\n cause: \"server\",\n ...(cmd.message !== undefined && { message: cmd.message }),\n },\n };\n case \"crashed\":\n return { ok: false, failure: { fate: \"crashed\", cause: \"server\" } };\n case \"expired\":\n return { ok: false, failure: { fate: \"expired\", cause: \"server\" } };\n default:\n return protocolError(`unknown cmd type: ${String(cmd.type)}`);\n }\n};\n\nconst TERMINAL_CMD_TYPES: ReadonlySet<string> = new Set(TERMINAL);\n\nconst parkVerdict = (s: Session, cmd: StatewireCmd) => {\n if (!s.shared || !TERMINAL_CMD_TYPES.has(cmd.type!)) return;\n s.shared.parked.push({\n seq: cmd.seq,\n type: cmd.type as StatewireClient.SessionVerdict[\"type\"],\n ...(cmd.code !== undefined && { code: cmd.code }),\n ...(cmd.message !== undefined && { message: cmd.message }),\n ...(cmd.payload !== undefined && { payload: cmd.payload }),\n ...(cmd.meta !== undefined && { meta: cmd.meta }),\n });\n};\n\nconst handleCmd = (s: Session, cmd: StatewireCmd) => {\n if (!Number.isSafeInteger(cmd.seq) || cmd.seq <= 0) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n if (cmd.dur === true) {\n s.durableSeq = Math.max(s.durableSeq, cmd.seq);\n for (const entry of s.pending) {\n if (entry.seq <= s.durableSeq) entry.posted = true;\n }\n }\n if (cmd.type === undefined) return;\n const entry = s.pending.find((p) => p.seq === cmd.seq);\n if (cmd.type === \"applied\") {\n if (entry) cover(s, entry);\n return;\n }\n parkVerdict(s, cmd);\n if (!entry) return;\n cover(s, entry);\n settleEntry(s, entry, outcomeOf(cmd));\n};\n\nconst consumeVerdicts = (s: Session) => {\n const verdicts = s.record.verdicts ?? [];\n const consumed = new Set<number>();\n for (const verdict of verdicts) {\n const entry = s.pending.find((p) => p.seq === verdict.seq);\n if (!entry) continue;\n consumed.add(verdict.seq);\n cover(s, entry);\n settleEntry(s, entry, outcomeOf(verdict as StatewireCmd));\n }\n if (consumed.size === 0) return;\n setRecord(s, {\n ...s.record,\n commands: s.record.commands.filter((c) => !consumed.has(c.seq)),\n verdicts: verdicts.filter((v) => !consumed.has(v.seq)),\n });\n publish(s);\n wake(s);\n};\n\nconst handleCmds = (s: Session, cmds: StatewireCmd[]) => {\n for (const cmd of cmds) handleCmd(s, cmd);\n syncBacklog(s);\n wake(s);\n};\n\nconst ingestOps = (s: Session, ops: unknown[]) => {\n const applied = applyDocumentOps(s.documents, ops);\n s.documents = applied;\n s.canonical = applied.documents.get(0)?.value;\n s.changed.push(...applied.changedPaths);\n};\n\nconst publishIngested = (s: Session) => {\n publish(s);\n wake(s);\n};\n\n// A hello's cmd watermark may understate a durable record (cold host, tray\n// unloaded): held seqs resend as-is and the frame's answer arbitrates —\n// absorption where the record survived, a gap refusal where it did not.\nconst snapCtxClock = (s: Session, ctxWm: number) => {\n const ctxAligned =\n s.ctxPending.every((c, i) => c.seq === ctxWm + 1 + i) &&\n s.record.ctxNextSeq === ctxWm + s.ctxPending.length + 1;\n if (!ctxAligned) {\n setRecord(s, { ...s.record, ctxNextSeq: ctxWm + 1 });\n restateContext(s);\n }\n};\n\n// The refusal's watermarks are exact: every held statement above them was\n// never admitted by the live record, and the first unposted seq being beyond\n// watermark+1 proves the record that admitted the missing prefix is gone —\n// its history settles lost and the lane clocks restart at the watermarks.\nconst sessionLostInner = (s: Session, seqWm: number, ctxWm: number) => {\n const held = [...s.pending];\n settleLost(s, held);\n s.pending = [];\n s.durableSeq = seqWm;\n setRecord(s, {\n clientId: s.record.clientId,\n nextSeq: seqWm + 1,\n ctxNextSeq: ctxWm + 1,\n commands: [],\n ...(s.record.failed !== undefined && { failed: s.record.failed }),\n });\n restateContext(s);\n if (\n held.length > 0 &&\n s.onSessionLost?.(held.map((p) => p.inv)) === \"requeue\"\n ) {\n for (const old of held) {\n enqueueInner(\n s,\n old.command,\n old.inv.params,\n () => {},\n () => {},\n );\n }\n }\n publish(s);\n wake(s);\n};\n\nconst handleHello = (\n s: Session,\n { ops, syn }: { ops: unknown[]; syn: StatewireSyn },\n) => {\n if (syn.record !== undefined && syn.record !== \"ephemeral\") {\n protocolError(`unknown record: ${String(syn.record)}`);\n }\n s.documents = { mode: null, documents: new Map() };\n ingestOps(s, ops);\n s.attach = \"attached\";\n s.attachEpoch += 1;\n s.frameFailures = 0;\n s.resumeAt = 0;\n s.ephemeral = syn.record === \"ephemeral\";\n if (s.ephemeral) s.deactivated = true;\n const [attachCmd, attachCtx] = s.attachLaneSeqs;\n s.attachLaneSeqs = [new Set(), new Set()];\n const reconcile = () => {\n if (s.shared) adoptStored(s);\n // Resending unsettled statements is exactly-once-safe: absorbed replays\n // re-emit their stored verdicts (applied while still in flight).\n s.durableSeq = syn.seq ?? 0;\n for (const entry of s.pending) {\n entry.posted = attachCmd.has(entry.seq);\n }\n const ctxWatermark = syn.ctxSeq ?? 0;\n s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxWatermark);\n for (const c of s.ctxPending) c.posted = attachCtx.has(c.seq);\n snapCtxClock(s, ctxWatermark);\n syncBacklogInner(s);\n s.sessionKnown = true;\n };\n if (!s.shared || s.deactivated) {\n reconcile();\n publishIngested(s);\n void pump(s);\n return;\n }\n void transact(s, reconcile).then(() => {\n publishIngested(s);\n void pump(s);\n });\n};\n\nconst handleOps = (\n s: Session,\n { ops, cmds }: { ops: unknown[]; cmds: StatewireCmd[] },\n) => {\n ingestOps(s, ops);\n for (const cmd of cmds) handleCmd(s, cmd);\n syncBacklog(s);\n publishIngested(s);\n};\n\n// A retry-less {syn} refusal is the one session-loss verdict: a cmd gap\n// against its exact watermark settles the held history lost; a pushback\n// (retry present) or a gapless refusal only reconciles the resend queues.\nconst handleRefusal = (s: Session, syn: StatewireSyn) => {\n const { seq, ctxSeq } = syn;\n if (typeof seq === \"number\") {\n const watermark = Math.max(seq, s.durableSeq);\n for (const entry of s.pending) entry.posted = entry.seq <= watermark;\n }\n if (typeof ctxSeq === \"number\") {\n s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxSeq);\n for (const c of s.ctxPending) c.posted = false;\n }\n if (typeof syn.retry === \"number\") {\n s.resumeAt = Date.now() + syn.retry;\n wake(s);\n void pump(s);\n return;\n }\n const firstCmd = s.pending.find((p) => !p.posted);\n const firstCtx = s.ctxPending.find((c) => !c.posted);\n const cmdGap =\n typeof seq === \"number\" &&\n firstCmd !== undefined &&\n firstCmd.seq > Math.max(seq, s.durableSeq) + 1;\n const ctxGap =\n typeof ctxSeq === \"number\" &&\n firstCtx !== undefined &&\n firstCtx.seq > ctxSeq + 1;\n if (cmdGap || ctxGap) {\n void transact(s, () => {\n if (cmdGap) sessionLostInner(s, seq!, ctxSeq ?? 0);\n else snapCtxClock(s, ctxSeq!);\n }).then(() => {\n wake(s);\n void pump(s);\n });\n return;\n }\n wake(s);\n void pump(s);\n};\n\nconst handleDetach = (s: Session) => {\n if (s.attach === \"attached\") s.attach = \"detached\";\n if (s.ephemeral) ephemeralDetach(s);\n wake(s);\n};\n\nconst handleFinish = (s: Session, { reason }: { reason: string }) => {\n if (reason === \"reconnect\" || reason === \"error\") return;\n s.attach = \"finished\";\n settleAll(s, \"gone\");\n publish(s);\n wake(s);\n};\n\nconst isFinished = (s: Session) => s.attach === \"finished\";\n\ntype Lanes = {\n frame: StatewireFrame;\n cmdEntries: Pending[];\n ctxEntries: CtxPending[];\n};\n\n// A lane must be strictly consecutive within a frame: the first unposted run\n// per lane rides now, later runs ride follow-up frames.\nconst buildLanes = (s: Session): Lanes | null => {\n const ctxEntries: CtxPending[] = [];\n for (const entry of s.ctxPending) {\n if (entry.posted) continue;\n if (ctxEntries.length >= MAX_COMMANDS_PER_FRAME) break;\n if (ctxEntries.length > 0 && entry.seq !== ctxEntries.at(-1)!.seq + 1)\n break;\n ctxEntries.push(entry);\n }\n const cmdEntries: Pending[] = [];\n for (const entry of s.pending) {\n if (entry.posted) continue;\n if (cmdEntries.length >= MAX_COMMANDS_PER_FRAME) break;\n if (cmdEntries.length > 0 && entry.seq !== cmdEntries.at(-1)!.seq + 1)\n break;\n cmdEntries.push(entry);\n }\n if (ctxEntries.length === 0 && cmdEntries.length === 0) return null;\n return {\n frame: {\n ...(ctxEntries.length > 0 && {\n ctx: ctxEntries.map((c) => ({ ops: c.ops, seq: c.seq })),\n }),\n ...(cmdEntries.length > 0 && {\n cmd: cmdEntries.map((p) => ({ ...p.command, seq: p.seq })),\n }),\n },\n cmdEntries,\n ctxEntries,\n };\n};\n\nconst takeAttachLanes = (s: Session): StatewireFrame | null => {\n s.attachLaneSeqs = [new Set(), new Set()];\n const wanted = s.lanesOnAttach;\n s.lanesOnAttach = false;\n if (!wanted || !s.sessionKnown) return null;\n const lanes = buildLanes(s);\n if (!lanes) return null;\n s.attachLaneSeqs = [\n new Set(lanes.cmdEntries.map((p) => p.seq)),\n new Set(lanes.ctxEntries.map((c) => c.seq)),\n ];\n for (const entry of lanes.cmdEntries) entry.attempted = true;\n return lanes.frame;\n};\n\nconst pump = async (s: Session) => {\n if (s.pumping) return;\n s.pumping = true;\n try {\n while (s.running && !isFinished(s)) {\n const transport = s.transport;\n if (buildLanes(s) === null) return;\n if (s.attach !== \"attached\" || !transport) {\n if (\n (transport?.connection.status === \"disconnected\" &&\n transport.connection.reason === \"idle\") ||\n (transport?.parked && s.pending.length > 0)\n ) {\n transport.connection.reconnect();\n }\n await waitForWake(s);\n continue;\n }\n const resumeDelay = s.resumeAt - Date.now();\n if (resumeDelay > 0) {\n await sleepUntilWake(s, resumeDelay);\n continue;\n }\n const lanes = buildLanes(s);\n if (!lanes) continue;\n const epoch = s.attachEpoch;\n for (const entry of lanes.cmdEntries) entry.attempted = true;\n let result;\n try {\n // Shared storage: the lock across the send keeps per-lane arrival\n // ordered across sharers during attach handover.\n const send = () => transport.send(lanes.frame);\n result = await (s.shared && !s.deactivated\n ? s.store.lock!(send)\n : send());\n } catch {\n if (!s.running || isFinished(s)) return;\n s.frameFailures += 1;\n await sleepUntilWake(s, backoff(s.frameFailures));\n continue;\n }\n if (!s.running) return;\n s.frameFailures = 0;\n if (result.type === \"ok\") {\n if (epoch === s.attachEpoch) {\n for (const entry of lanes.cmdEntries) {\n if (s.pending.includes(entry)) {\n entry.posted = true;\n s.lifecycle?.onPosted?.(entry.inv);\n }\n }\n for (const entry of lanes.ctxEntries) entry.posted = true;\n }\n } else if (result.type === \"refusal\") {\n if (epoch === s.attachEpoch) handleRefusal(s, result.syn);\n } else if (result.type === \"stale-lease\") {\n // A POST outlived its attach: reattach first, the hello arbitrates.\n if (epoch === s.attachEpoch) {\n transport.connection.reconnect();\n await waitForWake(s);\n }\n } else if (result.type === \"no-lease\") {\n // No out-of-band write channel: the frame rides a fresh attach.\n if (epoch === s.attachEpoch) {\n s.lanesOnAttach = true;\n transport.connection.reconnect();\n while (s.running && !isFinished(s) && epoch === s.attachEpoch) {\n await waitForWake(s);\n }\n }\n }\n }\n } finally {\n s.pumping = false;\n }\n};\n\nconst start = (s: Session) => {\n if (s.shared) {\n s.shared.unsubscribe = s.store.subscribe!(() => {\n void transact(s, () => consumeVerdicts(s));\n });\n s.running = true;\n void transact(s, () => {\n if (s.store.load() === null) s.store.save(s.record);\n s.recordPersisted = true;\n adoptStored(s);\n consumeVerdicts(s);\n }).then(() => void pump(s));\n return;\n }\n if (!s.recordPersisted) {\n s.recordPersisted = true;\n s.store.save(s.record);\n }\n adoptStored(s);\n s.running = true;\n void pump(s);\n};\n\nconst stop = (s: Session) => {\n s.running = false;\n if (s.shared) {\n s.shared.unsubscribe?.();\n s.shared.unsubscribe = null;\n }\n wake(s);\n settleAll(s, \"unmount\");\n};\n\nconst setTransport = (s: Session, transport: RemoteLink) => {\n if (s.transport === transport) return;\n s.transport = transport;\n wake(s);\n};\n\nconst enqueueInner = (\n s: Session,\n command: WireCommand,\n params: readonly unknown[],\n resolve: (payload: unknown) => void,\n reject: (error: StatewireSendError) => void,\n) => {\n const seq = s.record.nextSeq;\n const entry: Pending = {\n seq,\n command,\n inv: {\n method: command.method,\n params,\n ts: Date.now(),\n seq,\n clientId: s.record.clientId,\n },\n attempted: false,\n posted: false,\n applied: false,\n resolve,\n reject,\n };\n s.pending.push(entry);\n setRecord(s, { ...s.record, nextSeq: seq + 1, commands: mergeBacklog(s) });\n s.lifecycle?.onStart(entry.inv);\n};\n\nconst enqueue = (\n s: Session,\n command: WireCommand,\n params: readonly unknown[],\n resolve: (payload: unknown) => void,\n reject: (error: StatewireSendError) => void,\n) => {\n if (!s.shared) {\n enqueueInner(s, command, params, resolve, reject);\n wake(s);\n void pump(s);\n return;\n }\n void transact(s, () => {\n if (!s.running) {\n reject(new StatewireSendError({ fate: \"aborted\", cause: \"unmount\" }));\n return;\n }\n if (isFinished(s)) {\n reject(new StatewireSendError({ fate: \"aborted\", cause: \"stream-gone\" }));\n return;\n }\n enqueueInner(s, command, params, resolve, reject);\n }).then(() => {\n wake(s);\n void pump(s);\n });\n};\n\n// A stored command may have reached a server: attempted settles it lost,\n// never aborted, when a channel death ends the session.\nconst adoptStored = (s: Session) => {\n const known = new Set(s.pending.map((p) => p.seq));\n const stored = s.record.commands.filter((c) => !known.has(c.seq));\n if (stored.length === 0) return;\n for (const { seq, ...command } of stored) {\n const params =\n command.meta === undefined\n ? command.params\n : (reviveValue([...command.params], command.meta) as unknown[]);\n const entry: Pending = {\n seq,\n command,\n inv: {\n method: command.method,\n params,\n ts: Date.now(),\n seq,\n clientId: s.record.clientId,\n },\n attempted: true,\n posted: false,\n applied: false,\n resolve: () => {},\n reject: () => {},\n };\n s.pending.push(entry);\n s.lifecycle?.onStart(entry.inv);\n }\n s.pending.sort((a, b) => a.seq - b.seq);\n};\n\nconst sendCommand = (\n s: Session,\n method: string,\n params: readonly unknown[],\n): Promise<unknown> => {\n if (!s.running) {\n return rejectedSend({ fate: \"aborted\", cause: \"unmount\" });\n }\n if (isFinished(s)) {\n return rejectedSend({ fate: \"aborted\", cause: \"stream-gone\" });\n }\n const result = new Promise<unknown>((resolve, reject) => {\n const { params: encoded, meta } = encodeParams(params);\n enqueue(\n s,\n { method, params: encoded, ...(meta !== undefined && { meta }) },\n params,\n resolve,\n reject,\n );\n });\n result.catch(() => {});\n return result;\n};\n\nconst findFailed = (\n s: Session,\n entry: StatewireClient.FailedCommand,\n): StatewireClient.FailedCommand | undefined =>\n (s.record.failed ?? []).find(\n (f) =>\n f.seq === entry.seq && f.ts === entry.ts && f.command === entry.command,\n );\n\nconst unknownFailed = (entry: StatewireClient.FailedCommand) =>\n new Error(`statewire: unknown failed command \"${entry.command}\"`);\n\nconst takeFailed = (\n s: Session,\n entry: StatewireClient.FailedCommand,\n): StatewireClient.FailedCommand => {\n const failed = s.record.failed ?? [];\n const found = findFailed(s, entry);\n if (found === undefined) throw unknownFailed(entry);\n setRecord(s, { ...s.record, failed: failed.filter((f) => f !== found) });\n s.notify();\n return found;\n};\n\nexport const discardFailed = (\n s: Session,\n entry: StatewireClient.FailedCommand,\n): void => {\n if (!s.shared) {\n takeFailed(s, entry);\n return;\n }\n if (findFailed(s, entry) === undefined) throw unknownFailed(entry);\n void transact(s, () => {\n if (findFailed(s, entry) !== undefined) takeFailed(s, entry);\n });\n};\n\nexport const retryFailed = (\n s: Session,\n entry: StatewireClient.FailedCommand,\n): Promise<unknown> => {\n if (!s.running) {\n return rejectedSend({ fate: \"aborted\", cause: \"unmount\" });\n }\n if (isFinished(s)) {\n return rejectedSend({ fate: \"aborted\", cause: \"stream-gone\" });\n }\n const found = findFailed(s, entry);\n if (found === undefined) throw unknownFailed(entry);\n const params =\n found.meta === undefined\n ? found.params\n : (reviveValue([...found.params], found.meta) as unknown[]);\n const result = new Promise<unknown>((resolve, reject) => {\n const retry = () => {\n if (!s.running) {\n reject(new StatewireSendError({ fate: \"aborted\", cause: \"unmount\" }));\n return;\n }\n if (isFinished(s)) {\n reject(\n new StatewireSendError({ fate: \"aborted\", cause: \"stream-gone\" }),\n );\n return;\n }\n const current = findFailed(s, entry);\n if (current === undefined) {\n reject(unknownFailed(entry));\n return;\n }\n takeFailed(s, current);\n enqueueInner(\n s,\n {\n method: current.command,\n params: [...current.params],\n ...(current.meta !== undefined && { meta: current.meta }),\n },\n params,\n resolve,\n reject,\n );\n };\n if (!s.shared) {\n retry();\n wake(s);\n void pump(s);\n return;\n }\n void transact(s, retry).then(() => {\n wake(s);\n void pump(s);\n }, reject);\n });\n result.catch(() => {});\n return result;\n};\n\nconst setContext = (s: Session, value: Record<string, unknown>): void => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\"statewire: context must be a plain object\");\n }\n if (!s.running || isFinished(s)) return;\n const { value: encoded, meta } = encodeValue(value);\n const ops = [\n {\n op: \"replace\",\n path: [],\n value: encoded,\n ...(meta !== undefined && { meta }),\n },\n ];\n s.ctxOps = ops;\n const mint = () => {\n const seq = s.record.ctxNextSeq;\n setRecord(s, { ...s.record, ctxNextSeq: seq + 1 });\n s.ctxPending.push({ seq, ops, posted: false });\n };\n if (!s.shared) {\n mint();\n wake(s);\n void pump(s);\n return;\n }\n void transact(s, () => {\n if (!s.running || isFinished(s)) return;\n mint();\n }).then(() => {\n wake(s);\n void pump(s);\n });\n};\n\nexport const useStatewireSession = (\n options: StatewireSessionOptions,\n): Session => {\n const [defaultStore] = useState(createMemorySessionStore);\n const mounted = useContext(SessionStorageContext);\n if (options.sessionStore !== undefined && mounted !== undefined) {\n throw new Error(\n \"statewire: session storage is set twice — drop the transport's sessionStore or the client's storage.session\",\n );\n }\n const store = options.sessionStore ?? mounted ?? defaultStore;\n if ((store.lock === undefined) !== (store.subscribe === undefined)) {\n throw new Error(\n \"statewire: session storage must provide lock and subscribe together\",\n );\n }\n const [s] = useState((): Session => {\n const stored = store.load();\n if (stored !== null && !Array.isArray(stored.commands)) {\n throw new Error(\n \"statewire: session storage loaded a record without a commands array\",\n );\n }\n const record = stored ?? {\n clientId: newClientId(),\n nextSeq: 1,\n ctxNextSeq: 1,\n commands: [],\n };\n const session: Session = {\n record,\n ctx: {\n get clientId() {\n return session.record.clientId;\n },\n takeAttachLanes: () => takeAttachLanes(session),\n onHello: (args) => handleHello(session, args),\n onOps: (args) => handleOps(session, args),\n onCmds: (cmds) => handleCmds(session, cmds),\n onRefusal: (syn) => handleRefusal(session, syn),\n onIdle: (level) => setIdle(session, level),\n onDetach: () => handleDetach(session),\n onFinish: (args) => handleFinish(session, args),\n },\n recordPersisted: stored !== null,\n store,\n shared:\n store.lock !== undefined\n ? { txq: Promise.resolve(), parked: [], unsubscribe: null }\n : false,\n ephemeral: false,\n deactivated: false,\n sessionKnown: false,\n durableSeq: 0,\n resumeAt: 0,\n idle: false,\n onSessionLost: undefined,\n onDone: undefined,\n ctxOps: undefined,\n ctxPending: [],\n lanesOnAttach: false,\n attachLaneSeqs: [new Set(), new Set()],\n frameFailures: 0,\n pending: [],\n canonical: undefined,\n documents: { mode: null, documents: new Map() },\n lastPublished: undefined,\n changed: [],\n source: {\n snapshot: () => session.canonical,\n takeChanged: () => {\n const changed = session.changed;\n session.changed = [];\n return changed;\n },\n setOnChange: (listener) => {\n session.notify = listener ?? (() => {});\n },\n },\n attach: \"detached\",\n attachEpoch: 0,\n running: false,\n pumping: false,\n transport: null,\n waiters: [],\n lifecycle: null,\n notify: () => {},\n commands: createMethodProxy((method, params) =>\n sendCommand(session, method, params),\n ),\n };\n bindCommandsHost(session.commands, {\n setListener: (listener) => {\n session.lifecycle = listener;\n },\n });\n return session;\n });\n if ((store.lock !== undefined) !== (s.shared !== false)) {\n throw new Error(\n \"statewire: session storage changed sharedness across renders — lock/subscribe must be present from the first render or never\",\n );\n }\n s.store = store;\n s.onSessionLost = options.onSessionLost;\n s.onDone = options.onDone;\n useEffect(() => {\n start(s);\n return () => stop(s);\n }, [s]);\n return s;\n};\n\nexport { setContext, setTransport };\n"],"mappings":"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"}
|
package/dist/host/adapter.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { StatewireHostInternal } from "../host-internal.js";
|
|
|
2
2
|
//#region src/host/adapter.d.ts
|
|
3
3
|
declare const CLIENT_QUERY_PARAM = "client";
|
|
4
4
|
declare const clientIdFromUrl: (url: string | null | undefined) => string;
|
|
5
|
-
declare const textFrameOrClose: (socket: Pick<StatewireHostInternal.Socket, "close">, data: unknown) => string | null;
|
|
5
|
+
declare const textFrameOrClose: (socket: Pick<StatewireHostInternal.Socket, "send" | "close">, data: unknown) => string | null;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { CLIENT_QUERY_PARAM, clientIdFromUrl, textFrameOrClose };
|
|
8
8
|
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","names":[],"sources":["../../src/host/adapter.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","names":[],"sources":["../../src/host/adapter.ts"],"mappings":";;cAGa;cAEA,kBAAmB;cAuBnB,mBACX,QAAQ,KAAK,sBAAsB,2BACnC"}
|
package/dist/host/adapter.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CLIENT_ID_RE } from "./socket.js";
|
|
1
2
|
//#region src/host/adapter.ts
|
|
2
3
|
const CLIENT_QUERY_PARAM = "client";
|
|
3
4
|
const clientIdFromUrl = (url) => {
|
|
@@ -10,11 +11,16 @@ const clientIdFromUrl = (url) => {
|
|
|
10
11
|
}
|
|
11
12
|
const clientId = parsed.searchParams.get(CLIENT_QUERY_PARAM);
|
|
12
13
|
if (!clientId) throw new Error(`statewire: url is missing the "${CLIENT_QUERY_PARAM}" query parameter`);
|
|
14
|
+
if (!CLIENT_ID_RE.test(clientId)) throw new Error("statewire: invalid client id");
|
|
13
15
|
return clientId;
|
|
14
16
|
};
|
|
15
17
|
const textFrameOrClose = (socket, data) => {
|
|
16
18
|
if (typeof data === "string") return data;
|
|
17
|
-
socket.
|
|
19
|
+
socket.send(JSON.stringify({ fin: {
|
|
20
|
+
reason: "protocol-error",
|
|
21
|
+
message: "malformed frame"
|
|
22
|
+
} }));
|
|
23
|
+
socket.close(1008, "malformed frame");
|
|
18
24
|
return null;
|
|
19
25
|
};
|
|
20
26
|
//#endregion
|
package/dist/host/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","names":["StatewireHostInternal","CLIENT_QUERY_PARAM","clientIdFromUrl","url","Error","parsed","URL","clientId","searchParams","get","textFrameOrClose","socket","Pick","Socket","data","close"],"sources":["../../src/host/adapter.ts"],"sourcesContent":["import type { StatewireHostInternal } from \"../host-internal\";\n\nexport const CLIENT_QUERY_PARAM = \"client\";\n\nexport const clientIdFromUrl = (url: string | null | undefined): string => {\n if (!url) {\n throw new Error(\"statewire: cannot resolve client id: missing url\");\n }\n let parsed: URL;\n try {\n parsed = new URL(url, \"http://statewire\");\n } catch {\n throw new Error(\n `statewire: cannot resolve client id: unparseable url \"${url}\"`,\n );\n }\n const clientId = parsed.searchParams.get(CLIENT_QUERY_PARAM);\n if (!clientId) {\n throw new Error(\n `statewire: url is missing the \"${CLIENT_QUERY_PARAM}\" query parameter`,\n );\n }\n return clientId;\n};\n\nexport const textFrameOrClose = (\n socket: Pick<StatewireHostInternal.Socket, \"close\">,\n data: unknown,\n): string | null => {\n if (typeof data === \"string\") return data;\n socket.close(1008, \"
|
|
1
|
+
{"version":3,"file":"adapter.js","names":["CLIENT_ID_RE","StatewireHostInternal","CLIENT_QUERY_PARAM","clientIdFromUrl","url","Error","parsed","URL","clientId","searchParams","get","test","textFrameOrClose","socket","Pick","Socket","data","send","JSON","stringify","fin","reason","message","close"],"sources":["../../src/host/adapter.ts"],"sourcesContent":["import { CLIENT_ID_RE } from \"./socket\";\nimport type { StatewireHostInternal } from \"../host-internal\";\n\nexport const CLIENT_QUERY_PARAM = \"client\";\n\nexport const clientIdFromUrl = (url: string | null | undefined): string => {\n if (!url) {\n throw new Error(\"statewire: cannot resolve client id: missing url\");\n }\n let parsed: URL;\n try {\n parsed = new URL(url, \"http://statewire\");\n } catch {\n throw new Error(\n `statewire: cannot resolve client id: unparseable url \"${url}\"`,\n );\n }\n const clientId = parsed.searchParams.get(CLIENT_QUERY_PARAM);\n if (!clientId) {\n throw new Error(\n `statewire: url is missing the \"${CLIENT_QUERY_PARAM}\" query parameter`,\n );\n }\n if (!CLIENT_ID_RE.test(clientId))\n throw new Error(\"statewire: invalid client id\");\n return clientId;\n};\n\nexport const textFrameOrClose = (\n socket: Pick<StatewireHostInternal.Socket, \"send\" | \"close\">,\n data: unknown,\n): string | null => {\n if (typeof data === \"string\") return data;\n socket.send(\n JSON.stringify({\n fin: { reason: \"protocol-error\", message: \"malformed frame\" },\n }),\n );\n socket.close(1008, \"malformed frame\");\n return null;\n};\n"],"mappings":";;AAGA,MAAaE,qBAAqB;AAElC,MAAaC,mBAAmBC,QAA2C;CACzE,IAAI,CAACA,KACH,MAAM,IAAIC,MAAM,kDAAkD;CAEpE,IAAIC;CACJ,IAAI;EACFA,SAAS,IAAIC,IAAIH,KAAK,kBAAkB;CAC1C,QAAQ;EACN,MAAM,IAAIC,MACR,yDAAyDD,IAAG,EAC9D;CACF;CACA,MAAMI,WAAWF,OAAOG,aAAaC,IAAIR,kBAAkB;CAC3D,IAAI,CAACM,UACH,MAAM,IAAIH,MACR,kCAAkCH,mBAAkB,kBACtD;CAEF,IAAI,CAACF,aAAaW,KAAKH,QAAQ,GAC7B,MAAM,IAAIH,MAAM,8BAA8B;CAChD,OAAOG;AACT;AAEA,MAAaI,oBACXC,QACAG,SACkB;CAClB,IAAI,OAAOA,SAAS,UAAU,OAAOA;CACrCH,OAAOI,KACLC,KAAKC,UAAU,EACbC,KAAK;EAAEC,QAAQ;EAAkBC,SAAS;CAAkB,EAC9D,CAAC,CACH;CACAT,OAAOU,MAAM,MAAM,iBAAiB;CACpC,OAAO;AACT"}
|
package/dist/host/host.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ type CommandsHost = {
|
|
|
39
39
|
submit?: (call: CommandsSubmission) => Promise<unknown>;
|
|
40
40
|
/** Registered command names, read live. */
|
|
41
41
|
methods?: () => string[];
|
|
42
|
+
abort?: () => void;
|
|
42
43
|
};
|
|
43
44
|
declare const getCommandsHost: (commands: object) => CommandsHost | undefined;
|
|
44
45
|
declare const bindCommandsHost: (commands: object, host: CommandsHost) => void;
|
package/dist/host/host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","names":[],"sources":["../../src/host/host.ts"],"mappings":";;;;cAmBa,eACX,kBACC,cAAc;cAaJ,oBAAqB,QAChC,YAAY,qBACD,QAAQ,cAAc,SAAS;KAmEhC;WACD;WACA;WACA;WACA;WACA;;KAGC;EACN;EAAkB;;EAClB;EAAkB;;KAEZ;EACV,UAAU,KAAK;EACf,YAAY,KAAK;EACjB,YAAY,KAAK;;EAEjB,aAAa,KAAK;EAClB,WAAW,KAAK,oBAAoB,SAAS;;KAGnC;EACV;EACA;EACA;EACA,SAAS,cAAc;EACvB;EACA,YAAY,SAAS;;KAGX;EACV,cAAc,UAAU;EACxB,UAAU,MAAM,uBAAuB;;EAEvC;;cAKW,kBAAmB,qBAAmB;cAGtC,mBAAoB,kBAAkB,MAAM;
|
|
1
|
+
{"version":3,"file":"host.d.ts","names":[],"sources":["../../src/host/host.ts"],"mappings":";;;;cAmBa,eACX,kBACC,cAAc;cAaJ,oBAAqB,QAChC,YAAY,qBACD,QAAQ,cAAc,SAAS;KAmEhC;WACD;WACA;WACA;WACA;WACA;;KAGC;EACN;EAAkB;;EAClB;EAAkB;;KAEZ;EACV,UAAU,KAAK;EACf,YAAY,KAAK;EACjB,YAAY,KAAK;;EAEjB,aAAa,KAAK;EAClB,WAAW,KAAK,oBAAoB,SAAS;;KAGnC;EACV;EACA;EACA;EACA,SAAS,cAAc;EACvB;EACA,YAAY,SAAS;;KAGX;EACV,cAAc,UAAU;EACxB,UAAU,MAAM,uBAAuB;;EAEvC;EACA;;cAKW,kBAAmB,qBAAmB;cAGtC,mBAAoB,kBAAkB,MAAM;cA0N5C,uBAAwB,kBAAkB,UAAU,UAC/D,WACK,YAAY,SAAS,cAAc,qCAIvC,UAAU,cAAc,cAAc,gBAAgB"}
|
package/dist/host/host.js
CHANGED
|
@@ -78,6 +78,7 @@ const LOCAL_CALLER = Object.freeze({
|
|
|
78
78
|
get clientId() {
|
|
79
79
|
throw new Error("statewire: in-process dispatch has no client id");
|
|
80
80
|
},
|
|
81
|
+
auth: void 0,
|
|
81
82
|
context: null,
|
|
82
83
|
isConnected: true
|
|
83
84
|
});
|
|
@@ -95,9 +96,13 @@ const applyInvocation = (cell, inv) => {
|
|
|
95
96
|
if (inv.applied) return;
|
|
96
97
|
inv.applied = true;
|
|
97
98
|
cell.listener?.onApplied(inv);
|
|
99
|
+
cell.listener?.onCovered?.(inv);
|
|
98
100
|
inv.origin?.onApplied?.();
|
|
99
101
|
};
|
|
100
102
|
const settleInvocation = (cell, inv, call, settled) => {
|
|
103
|
+
if (inv.settled) return;
|
|
104
|
+
inv.settled = true;
|
|
105
|
+
cell.active.delete(inv);
|
|
101
106
|
applyInvocation(cell, inv);
|
|
102
107
|
if (settled.type === "resolved") {
|
|
103
108
|
const outcome = settled.value === void 0 ? { type: "accepted" } : {
|
|
@@ -118,9 +123,32 @@ const settleInvocation = (cell, inv, call, settled) => {
|
|
|
118
123
|
call.reject(error);
|
|
119
124
|
}
|
|
120
125
|
};
|
|
126
|
+
const abortInvocations = (cell) => {
|
|
127
|
+
for (const [inv, call] of cell.active) {
|
|
128
|
+
inv.settled = true;
|
|
129
|
+
inv.controller.abort();
|
|
130
|
+
const error = new StatewireSendError({
|
|
131
|
+
fate: "crashed",
|
|
132
|
+
cause: "server"
|
|
133
|
+
});
|
|
134
|
+
const outcome = {
|
|
135
|
+
type: "rejected",
|
|
136
|
+
error
|
|
137
|
+
};
|
|
138
|
+
cell.listener?.onSettle(inv, outcome);
|
|
139
|
+
inv.origin?.onSettle?.(outcome);
|
|
140
|
+
call.reject(error);
|
|
141
|
+
}
|
|
142
|
+
cell.active.clear();
|
|
143
|
+
};
|
|
121
144
|
const isThenable = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
|
|
145
|
+
const handlerOf = (handlers, method) => {
|
|
146
|
+
if (!Object.prototype.propertyIsEnumerable.call(handlers, method)) return;
|
|
147
|
+
const handler = handlers[method];
|
|
148
|
+
return typeof handler === "function" ? handler : void 0;
|
|
149
|
+
};
|
|
122
150
|
const dispatch = (cell, call) => {
|
|
123
|
-
const handler = cell.handlers
|
|
151
|
+
const handler = handlerOf(cell.handlers, call.method);
|
|
124
152
|
if (handler === void 0) {
|
|
125
153
|
const error = new StatewireSendError({
|
|
126
154
|
fate: "rejected",
|
|
@@ -140,15 +168,20 @@ const dispatch = (cell, call) => {
|
|
|
140
168
|
ts: call.ts,
|
|
141
169
|
seq: ++cell.seq,
|
|
142
170
|
applied: false,
|
|
171
|
+
controller: new AbortController(),
|
|
172
|
+
settled: false,
|
|
143
173
|
...call.origin !== void 0 && { origin: call.origin },
|
|
144
174
|
...call.origin?.clientId !== void 0 && { clientId: call.origin.clientId }
|
|
145
175
|
};
|
|
176
|
+
cell.active.set(inv, call);
|
|
146
177
|
cell.listener?.onStart(inv);
|
|
147
178
|
cell.listener?.onPosted?.(inv);
|
|
148
|
-
cell.listener?.onCovered?.(inv);
|
|
149
179
|
const ctx = {
|
|
150
180
|
caller: call.origin?.caller ?? LOCAL_CALLER,
|
|
151
|
-
|
|
181
|
+
signal: inv.controller.signal,
|
|
182
|
+
applied: () => {
|
|
183
|
+
if (!inv.settled) applyInvocation(cell, inv);
|
|
184
|
+
}
|
|
152
185
|
};
|
|
153
186
|
try {
|
|
154
187
|
const value = handler.call(ctx, ...call.params);
|
|
@@ -199,6 +232,7 @@ const useStatewireCommands = (commands) => {
|
|
|
199
232
|
const cell = {
|
|
200
233
|
handlers: null,
|
|
201
234
|
queue: [],
|
|
235
|
+
active: /* @__PURE__ */ new Map(),
|
|
202
236
|
running: false,
|
|
203
237
|
listener: null,
|
|
204
238
|
seq: 0,
|
|
@@ -220,10 +254,15 @@ const useStatewireCommands = (commands) => {
|
|
|
220
254
|
pump(cell);
|
|
221
255
|
}));
|
|
222
256
|
commandsHosts.set(proxy, {
|
|
257
|
+
abort: () => abortInvocations(cell),
|
|
223
258
|
setListener: (listener) => {
|
|
224
259
|
cell.listener = listener;
|
|
225
260
|
},
|
|
226
|
-
methods: () =>
|
|
261
|
+
methods: () => {
|
|
262
|
+
const handlers = cell.handlers;
|
|
263
|
+
if (!handlers) return [];
|
|
264
|
+
return Object.keys(handlers).filter((method_0) => handlerOf(handlers, method_0) !== void 0);
|
|
265
|
+
},
|
|
227
266
|
submit: (origin) => new Promise((resolve_0, reject_0) => {
|
|
228
267
|
if (cell.unmounted) {
|
|
229
268
|
reject_0(/* @__PURE__ */ new Error("statewire: commands called after unmount"));
|
|
@@ -257,6 +296,7 @@ const useStatewireCommands = (commands) => {
|
|
|
257
296
|
}
|
|
258
297
|
queueMicrotask(() => {
|
|
259
298
|
if (!cell_0.unmounted) return;
|
|
299
|
+
abortInvocations(cell_0);
|
|
260
300
|
const queued = cell_0.queue;
|
|
261
301
|
cell_0.queue = [];
|
|
262
302
|
for (const call of queued) call.reject(/* @__PURE__ */ new Error("statewire: unmounted"));
|
|
@@ -265,7 +305,7 @@ const useStatewireCommands = (commands) => {
|
|
|
265
305
|
}, [built]);
|
|
266
306
|
useEffect(() => {
|
|
267
307
|
if (commands) {
|
|
268
|
-
for (const
|
|
308
|
+
for (const method_1 of Object.keys(commands)) if (method_1.startsWith("statewire/")) throw new Error(`statewire: cannot register "${method_1}": the "statewire/" method namespace is reserved`);
|
|
269
309
|
}
|
|
270
310
|
built.cell.handlers = commands || null;
|
|
271
311
|
pump(built.cell);
|
package/dist/host/host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","names":["useEffect","useState","applyOps","sanitizeValue","StatewirePath","StatewireReject","createStateDraft","createMethodProxy","StateDraft","StatewireSendError","Statewire","StatewireHost","isDev","process","env","stateHosts","WeakMap","StateHost","getStateHost","state","get","StateCell","current","draft","changed","onOp","op","Op","onChange","ctl","StateCtl","host","bump","useStatewireState","init","TState","setVersion","cell","commit","c","flush","v","apply","ops","result","invalidate","push","changedPaths","snapshot","setOnOp","listener","setOnChange","takeChanged","value","record","changedPath","set","proxy","const","Settled","type","error","CommandsInvocation","method","params","ts","seq","clientId","CommandsOutcome","payload","CommandsListener","onStart","inv","onPosted","onApplied","onCovered","onSettle","outcome","CommandsSubmission","caller","Caller","CommandsHost","setListener","submit","call","Promise","methods","commandsHosts","getCommandsHost","commands","bindCommandsHost","QueuedCall","resolve","reject","origin","ActiveInvocation","applied","CommandsCell","handlers","Record","args","queue","running","unmounted","stallTimer","ReturnType","setTimeout","STALL_WARN_MS","LOCAL_CALLER","Object","freeze","Error","context","isConnected","toSendError","fate","cause","message","undefined","String","applyInvocation","settleInvocation","settled","isThenable","PromiseLike","then","dispatch","handler","code","ctx","Ctx","this","resolved","pump","watchStall","shift","length","console","warn","useStatewireCommands","Commands","THandlers","ThisType","CommandsProxy","HandledCommands","built","Date","now","keys","clearTimeout","queueMicrotask","queued","startsWith"],"sources":["../../src/host/host.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { applyOps, sanitizeValue } from \"../wire/ops\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport { StatewireReject } from \"./engine\";\nimport { createStateDraft } from \"./draft\";\nimport { createMethodProxy } from \"../util/methodProxy\";\nimport type { StateDraft } from \"./draft\";\nimport { StatewireSendError } from \"../types\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireHost } from \"../host\";\n\nconst isDev = () =>\n typeof process === \"undefined\" || process.env[\"NODE_ENV\"] !== \"production\";\n\n// ─── state ──────────────────────────────────────────────\n\nconst stateHosts = new WeakMap<object, StatewireHost.StateHost>();\n\n/** Host-side accessor for a `useStatewireState` state object's source (`snapshot()` reads the committed state). */\nexport const getStateHost = (\n state: object,\n): StatewireHost.StateHost | undefined => stateHosts.get(state);\n\ntype StateCell = {\n current: unknown;\n draft: StateDraft<object> | null;\n changed: StatewirePath[];\n onOp: ((op: Statewire.Op) => void) | null;\n onChange: (() => void) | null;\n ctl: StatewireHost.StateCtl;\n host: StatewireHost.StateHost;\n bump: () => void;\n};\n\nexport const useStatewireState = <TState>(\n init: () => TState,\n): readonly [TState, StatewireHost.StateCtl<TState>] => {\n const [, setVersion] = useState(0);\n const [cell] = useState((): StateCell => {\n const commit = () => {\n if (c.draft) c.current = c.draft.flush();\n return c.current;\n };\n const c: StateCell = {\n current: sanitizeValue(init()),\n draft: null,\n changed: [[]],\n onOp: null,\n onChange: null,\n bump: () => setVersion((v) => v + 1),\n ctl: {\n apply: (ops) => {\n const result = applyOps(commit(), ops);\n c.current = result.state;\n c.draft?.invalidate();\n c.changed.push(...result.changedPaths);\n if (c.onOp) for (const op of ops) c.onOp(op);\n c.bump();\n c.onChange?.();\n },\n snapshot: commit,\n },\n host: {\n snapshot: commit,\n setOnOp: (listener) => {\n c.onOp = listener;\n },\n setOnChange: (listener) => {\n c.onChange = listener;\n },\n takeChanged: () => {\n const changed = c.changed;\n c.changed = [];\n return changed;\n },\n },\n };\n return c;\n });\n\n let value = cell.ctl.snapshot();\n if (typeof value === \"object\" && value !== null) {\n cell.draft ??= createStateDraft<object>({\n snapshot: () => cell.current,\n record: (op, changedPath) => {\n cell.changed.push(changedPath);\n cell.onOp?.(op);\n cell.bump();\n cell.onChange?.();\n },\n });\n stateHosts.set(cell.draft.proxy, cell.host);\n value = cell.draft.proxy;\n }\n return [value as TState, cell.ctl as StatewireHost.StateCtl<TState>] as const;\n};\n\n// ─── commands ───────────────────────────────────────────\n\ntype Settled =\n | { type: \"resolved\"; value: unknown }\n | { type: \"rejected\"; error: unknown };\n\nexport type CommandsInvocation = {\n readonly method: string;\n readonly params: readonly unknown[];\n readonly ts: number;\n readonly seq: number;\n readonly clientId?: string;\n};\n\nexport type CommandsOutcome =\n | { type: \"accepted\"; payload?: unknown }\n | { type: \"rejected\"; error: unknown };\n\nexport type CommandsListener = {\n onStart: (inv: CommandsInvocation) => void;\n onPosted?: (inv: CommandsInvocation) => void;\n onApplied: (inv: CommandsInvocation) => void;\n /** Canonical state now covers the invocation's effect — drop any overlay. */\n onCovered?: (inv: CommandsInvocation) => void;\n onSettle: (inv: CommandsInvocation, outcome: CommandsOutcome) => void;\n};\n\nexport type CommandsSubmission = {\n method: string;\n params: readonly unknown[];\n clientId?: string;\n caller?: StatewireHost.Caller;\n onApplied?: () => void;\n onSettle?: (outcome: CommandsOutcome) => void;\n};\n\nexport type CommandsHost = {\n setListener: (listener: CommandsListener | null) => void;\n submit?: (call: CommandsSubmission) => Promise<unknown>;\n /** Registered command names, read live. */\n methods?: () => string[];\n};\n\nconst commandsHosts = new WeakMap<object, CommandsHost>();\n\nexport const getCommandsHost = (commands: object): CommandsHost | undefined =>\n commandsHosts.get(commands);\n\nexport const bindCommandsHost = (commands: object, host: CommandsHost) => {\n commandsHosts.set(commands, host);\n};\n\ntype QueuedCall = {\n method: string;\n params: readonly unknown[];\n ts: number;\n resolve: (value: unknown) => void;\n reject: (error: unknown) => void;\n origin?: CommandsSubmission;\n};\n\ntype ActiveInvocation = CommandsInvocation & {\n applied: boolean;\n origin?: CommandsSubmission;\n};\n\ntype CommandsCell = {\n handlers: Record<string, (...args: never[]) => unknown> | null;\n queue: QueuedCall[];\n running: boolean;\n listener: CommandsListener | null;\n seq: number;\n unmounted: boolean;\n stallTimer: ReturnType<typeof setTimeout> | null;\n};\n\nconst STALL_WARN_MS = 5000;\n\n// In-process dispatch has no wire client: never any ambient context, trivially attached.\nconst LOCAL_CALLER: StatewireHost.Caller = Object.freeze({\n get clientId(): string {\n throw new Error(\"statewire: in-process dispatch has no client id\");\n },\n context: null,\n isConnected: true,\n});\n\nconst toSendError = (error: unknown): StatewireSendError =>\n error instanceof StatewireSendError\n ? error\n : error instanceof StatewireReject\n ? new StatewireSendError({\n fate: \"rejected\",\n cause: \"server\",\n message: error.message,\n ...(error.payload !== undefined && { payload: error.payload }),\n })\n : new StatewireSendError({\n fate: \"failed\",\n cause: \"server\",\n message: error instanceof Error ? error.message : String(error),\n });\n\nconst applyInvocation = (cell: CommandsCell, inv: ActiveInvocation) => {\n if (inv.applied) return;\n inv.applied = true;\n cell.listener?.onApplied(inv);\n inv.origin?.onApplied?.();\n};\n\nconst settleInvocation = (\n cell: CommandsCell,\n inv: ActiveInvocation,\n call: QueuedCall,\n settled: Settled,\n) => {\n applyInvocation(cell, inv);\n if (settled.type === \"resolved\") {\n const outcome: CommandsOutcome =\n settled.value === undefined\n ? { type: \"accepted\" }\n : { type: \"accepted\", payload: sanitizeValue(settled.value) };\n cell.listener?.onSettle(inv, outcome);\n inv.origin?.onSettle?.(outcome);\n call.resolve(outcome.payload);\n } else {\n const error = toSendError(settled.error);\n const outcome: CommandsOutcome = { type: \"rejected\", error };\n cell.listener?.onSettle(inv, outcome);\n inv.origin?.onSettle?.(outcome);\n call.reject(error);\n }\n};\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\";\n\nconst dispatch = (cell: CommandsCell, call: QueuedCall) => {\n const handler = cell.handlers![call.method];\n if (handler === undefined) {\n const error = new StatewireSendError({\n fate: \"rejected\",\n cause: \"server\",\n code: \"unknown-command\",\n });\n call.origin?.onSettle?.({ type: \"rejected\", error });\n call.reject(error);\n return;\n }\n const inv: ActiveInvocation = {\n method: call.method,\n params: call.params,\n ts: call.ts,\n seq: ++cell.seq,\n applied: false,\n ...(call.origin !== undefined && { origin: call.origin }),\n ...(call.origin?.clientId !== undefined && {\n clientId: call.origin.clientId,\n }),\n };\n cell.listener?.onStart(inv);\n cell.listener?.onPosted?.(inv);\n cell.listener?.onCovered?.(inv);\n const ctx: StatewireHost.Ctx = {\n caller: call.origin?.caller ?? LOCAL_CALLER,\n applied: () => applyInvocation(cell, inv),\n };\n try {\n const value = (\n handler as (\n this: StatewireHost.Ctx,\n ...args: readonly unknown[]\n ) => unknown\n ).call(ctx, ...call.params);\n if (isThenable(value)) {\n value.then(\n (resolved) =>\n settleInvocation(cell, inv, call, {\n type: \"resolved\",\n value: resolved,\n }),\n (error: unknown) =>\n settleInvocation(cell, inv, call, { type: \"rejected\", error }),\n );\n } else {\n settleInvocation(cell, inv, call, { type: \"resolved\", value });\n }\n } catch (error) {\n settleInvocation(cell, inv, call, { type: \"rejected\", error });\n }\n};\n\n// Prefix-only advancement: each handler runs synchronously to its first\n// await, then the pump moves on; settlement rides the returned promise.\nconst pump = (cell: CommandsCell) => {\n if (cell.running || !cell.handlers) {\n watchStall(cell);\n return;\n }\n cell.running = true;\n try {\n while (cell.handlers) {\n const call = cell.queue.shift();\n if (!call) break;\n dispatch(cell, call);\n }\n } finally {\n cell.running = false;\n }\n};\n\nconst watchStall = (cell: CommandsCell) => {\n if (!isDev() || cell.stallTimer !== null || cell.queue.length === 0) return;\n if (cell.handlers) return;\n cell.stallTimer = setTimeout(() => {\n cell.stallTimer = null;\n if (cell.handlers === null && cell.queue.length > 0 && !cell.unmounted) {\n console.warn(\n `statewire: ${cell.queue.length} buffered command(s) waiting over ${STALL_WARN_MS}ms — did the host forget to arm useStatewireCommands?`,\n );\n }\n }, STALL_WARN_MS);\n};\n\nexport const useStatewireCommands = <THandlers extends Statewire.Commands>(\n commands:\n | (THandlers & ThisType<StatewireHost.Ctx>)\n | undefined\n | null\n | false,\n): Statewire.CommandsProxy<StatewireHost.HandledCommands<THandlers>> => {\n const [built] = useState(() => {\n const cell: CommandsCell = {\n handlers: null,\n queue: [],\n running: false,\n listener: null,\n seq: 0,\n unmounted: false,\n stallTimer: null,\n };\n const proxy = createMethodProxy<\n Statewire.CommandsProxy<StatewireHost.HandledCommands<THandlers>>\n >(\n (method, params) =>\n new Promise((resolve, reject) => {\n if (cell.unmounted) {\n reject(new Error(\"statewire: commands called after unmount\"));\n return;\n }\n cell.queue.push({\n method,\n params,\n ts: Date.now(),\n resolve,\n reject,\n });\n pump(cell);\n }),\n );\n commandsHosts.set(proxy, {\n setListener: (listener) => {\n cell.listener = listener;\n },\n methods: () => (cell.handlers ? Object.keys(cell.handlers) : []),\n submit: (origin) =>\n new Promise((resolve, reject) => {\n if (cell.unmounted) {\n reject(new Error(\"statewire: commands called after unmount\"));\n return;\n }\n cell.queue.push({\n method: origin.method,\n params: origin.params,\n ts: Date.now(),\n resolve,\n reject,\n origin,\n });\n pump(cell);\n }),\n });\n return { cell, proxy };\n });\n\n useEffect(() => {\n const { cell } = built;\n cell.unmounted = false;\n return () => {\n cell.unmounted = true;\n cell.handlers = null;\n if (cell.stallTimer !== null) {\n clearTimeout(cell.stallTimer);\n cell.stallTimer = null;\n }\n queueMicrotask(() => {\n if (!cell.unmounted) return;\n const queued = cell.queue;\n cell.queue = [];\n for (const call of queued) {\n call.reject(new Error(\"statewire: unmounted\"));\n }\n });\n };\n }, [built]);\n\n useEffect(() => {\n if (commands) {\n for (const method of Object.keys(commands)) {\n if (method.startsWith(\"statewire/\")) {\n throw new Error(\n `statewire: cannot register \"${method}\": the \"statewire/\" method namespace is reserved`,\n );\n }\n }\n }\n built.cell.handlers = commands || null;\n pump(built.cell);\n });\n\n return built.proxy;\n};\n"],"mappings":";;;;;;;AAWA,MAAMY,cACJ,OAAOC,YAAY,eAAeA,QAAQC,IAAI,gBAAgB;AAIhE,MAAMC,6BAAa,IAAIC,QAAyC;;AAGhE,MAAaE,gBACXC,UACwCJ,WAAWK,IAAID,KAAK;AAa9D,MAAac,qBACXC,SACsD;CACtD,MAAM,GAAGE,cAAcnC,SAAS,CAAC;CACjC,MAAM,CAACoC,QAAQpC,eAA0B;EACvC,MAAMqC,eAAe;GACnB,IAAIC,EAAEhB,OAAOgB,EAAEjB,UAAUiB,EAAEhB,MAAMiB,MAAM;GACvC,OAAOD,EAAEjB;EACX;EACA,MAAMiB,IAAe;GACnBjB,SAASnB,cAAc+B,KAAK,CAAC;GAC7BX,OAAO;GACPC,SAAS,CAAC,CAAA,CAAE;GACZC,MAAM;GACNG,UAAU;GACVI,YAAYI,YAAYK,MAAMA,IAAI,CAAC;GACnCZ,KAAK;IACHa,QAAQC,QAAQ;KACd,MAAMC,SAAS1C,SAASoC,OAAO,GAAGK,GAAG;KACrCJ,EAAEjB,UAAUsB,OAAOzB;KACnBoB,EAAEhB,OAAOsB,WAAW;KACpBN,EAAEf,QAAQsB,KAAK,GAAGF,OAAOG,YAAY;KACrC,IAAIR,EAAEd,MAAM,KAAK,MAAMC,MAAMiB,KAAKJ,EAAEd,KAAKC,EAAE;KAC3Ca,EAAEP,KAAK;KACPO,EAAEX,WAAW;IACf;IACAoB,UAAUV;GACZ;GACAP,MAAM;IACJiB,UAAUV;IACVW,UAAUC,aAAa;KACrBX,EAAEd,OAAOyB;IACX;IACAC,cAAcD,eAAa;KACzBX,EAAEX,WAAWsB;IACf;IACAE,mBAAmB;KACjB,MAAM5B,UAAUe,EAAEf;KAClBe,EAAEf,UAAU,CAAA;KACZ,OAAOA;IACT;GACF;EACF;EACA,OAAOe;CACT,CAAC;CAED,IAAIc,QAAQhB,KAAKR,IAAImB,SAAS;CAC9B,IAAI,OAAOK,UAAU,YAAYA,UAAU,MAAM;EAC/ChB,KAAKd,UAAUjB,iBAAyB;GACtC0C,gBAAgBX,KAAKf;GACrBgC,SAAS5B,IAAI6B,gBAAgB;IAC3BlB,KAAKb,QAAQsB,KAAKS,WAAW;IAC7BlB,KAAKZ,OAAOC,EAAE;IACdW,KAAKL,KAAK;IACVK,KAAKT,WAAW;GAClB;EACF,CAAC;EACDb,WAAWyC,IAAInB,KAAKd,MAAMkC,OAAOpB,KAAKN,IAAI;EAC1CsB,QAAQhB,KAAKd,MAAMkC;CACrB;CACA,OAAO,CAACJ,OAAiBhB,KAAKR,GAAqC;AACrE;AA6CA,MAAM0D,gCAAgB,IAAIvE,QAA8B;AAExD,MAAawE,mBAAmBC,aAC9BF,cAAcnE,IAAIqE,QAAQ;AAE5B,MAAaC,oBAAoBD,UAAkB1D,SAAuB;CACxEwD,cAAc/B,IAAIiC,UAAU1D,IAAI;AAClC;AA0BA,MAAM4E,gBAAgB;AAGtB,MAAMC,eAAqCC,OAAOC,OAAO;CACvD,IAAI3C,WAAmB;EACrB,MAAM,IAAI4C,MAAM,iDAAiD;CACnE;CACAC,SAAS;CACTC,aAAa;AACf,CAAC;AAED,MAAMC,eAAerD,UACnBA,iBAAiBpD,qBACboD,QACAA,iBAAiBxD,kBACf,IAAII,mBAAmB;CACrB0G,MAAM;CACNC,OAAO;CACPC,SAASxD,MAAMwD;CACf,GAAIxD,MAAMQ,YAAYiD,KAAAA,KAAa,EAAEjD,SAASR,MAAMQ,QAAQ;AAC9D,CAAC,IACD,IAAI5D,mBAAmB;CACrB0G,MAAM;CACNC,OAAO;CACPC,SAASxD,iBAAiBkD,QAAQlD,MAAMwD,UAAUE,OAAO1D,KAAK;AAChE,CAAC;AAET,MAAM2D,mBAAmBnF,MAAoBmC,QAA0B;CACrE,IAAIA,IAAIwB,SAAS;CACjBxB,IAAIwB,UAAU;CACd3D,KAAKa,UAAUwB,UAAUF,GAAG;CAC5BA,IAAIsB,QAAQpB,YAAY;AAC1B;AAEA,MAAM+C,oBACJpF,MACAmC,KACAY,MACAsC,YACG;CACHF,gBAAgBnF,MAAMmC,GAAG;CACzB,IAAIkD,QAAQ9D,SAAS,YAAY;EAC/B,MAAMiB,UACJ6C,QAAQrE,UAAUiE,KAAAA,IACd,EAAE1D,MAAM,WAAW,IACnB;GAAEA,MAAM;GAAYS,SAASlE,cAAcuH,QAAQrE,KAAK;EAAE;EAChEhB,KAAKa,UAAU0B,SAASJ,KAAKK,OAAO;EACpCL,IAAIsB,QAAQlB,WAAWC,OAAO;EAC9BO,KAAKQ,QAAQf,QAAQR,OAAO;CAC9B,OAAO;EACL,MAAMR,QAAQqD,YAAYQ,QAAQ7D,KAAK;EACvC,MAAMgB,UAA2B;GAAEjB,MAAM;GAAYC;EAAM;EAC3DxB,KAAKa,UAAU0B,SAASJ,KAAKK,OAAO;EACpCL,IAAIsB,QAAQlB,WAAWC,OAAO;EAC9BO,KAAKS,OAAOhC,KAAK;CACnB;AACF;AAEA,MAAM8D,cAActE,UAClB,OAAOA,UAAU,YACjBA,UAAU,QACV,OAAQA,MAA6BwE,SAAS;AAEhD,MAAMC,YAAYzF,MAAoB+C,SAAqB;CACzD,MAAM2C,UAAU1F,KAAK6D,SAAUd,KAAKrB;CACpC,IAAIgE,YAAYT,KAAAA,GAAW;EACzB,MAAMzD,QAAQ,IAAIpD,mBAAmB;GACnC0G,MAAM;GACNC,OAAO;GACPY,MAAM;EACR,CAAC;EACD5C,KAAKU,QAAQlB,WAAW;GAAEhB,MAAM;GAAYC;EAAM,CAAC;EACnDuB,KAAKS,OAAOhC,KAAK;EACjB;CACF;CACA,MAAMW,MAAwB;EAC5BT,QAAQqB,KAAKrB;EACbC,QAAQoB,KAAKpB;EACbC,IAAImB,KAAKnB;EACTC,KAAK,EAAE7B,KAAK6B;EACZ8B,SAAS;EACT,GAAIZ,KAAKU,WAAWwB,KAAAA,KAAa,EAAExB,QAAQV,KAAKU,OAAO;EACvD,GAAIV,KAAKU,QAAQ3B,aAAamD,KAAAA,KAAa,EACzCnD,UAAUiB,KAAKU,OAAO3B,SACxB;CACF;CACA9B,KAAKa,UAAUqB,QAAQC,GAAG;CAC1BnC,KAAKa,UAAUuB,WAAWD,GAAG;CAC7BnC,KAAKa,UAAUyB,YAAYH,GAAG;CAC9B,MAAMyD,MAAyB;EAC7BlD,QAAQK,KAAKU,QAAQf,UAAU6B;EAC/BZ,eAAewB,gBAAgBnF,MAAMmC,GAAG;CAC1C;CACA,IAAI;EACF,MAAMnB,QACJ0E,QAIA3C,KAAK6C,KAAK,GAAG7C,KAAKpB,MAAM;EAC1B,IAAI2D,WAAWtE,KAAK,GAClBA,MAAMwE,MACHO,aACCX,iBAAiBpF,MAAMmC,KAAKY,MAAM;GAChCxB,MAAM;GACNP,OAAO+E;EACT,CAAC,IACFvE,UACC4D,iBAAiBpF,MAAMmC,KAAKY,MAAM;GAAExB,MAAM;GAAYC;EAAM,CAAC,CACjE;OAEA4D,iBAAiBpF,MAAMmC,KAAKY,MAAM;GAAExB,MAAM;GAAYP;EAAM,CAAC;CAEjE,SAASQ,OAAO;EACd4D,iBAAiBpF,MAAMmC,KAAKY,MAAM;GAAExB,MAAM;GAAYC;EAAM,CAAC;CAC/D;AACF;AAIA,MAAMwE,QAAQhG,SAAuB;CACnC,IAAIA,KAAKiE,WAAW,CAACjE,KAAK6D,UAAU;EAClCoC,WAAWjG,IAAI;EACf;CACF;CACAA,KAAKiE,UAAU;CACf,IAAI;EACF,OAAOjE,KAAK6D,UAAU;GACpB,MAAMd,OAAO/C,KAAKgE,MAAMkC,MAAM;GAC9B,IAAI,CAACnD,MAAM;GACX0C,SAASzF,MAAM+C,IAAI;EACrB;CACF,UAAU;EACR/C,KAAKiE,UAAU;CACjB;AACF;AAEA,MAAMgC,cAAcjG,SAAuB;CACzC,IAAI,CAACzB,MAAM,KAAKyB,KAAKmE,eAAe,QAAQnE,KAAKgE,MAAMmC,WAAW,GAAG;CACrE,IAAInG,KAAK6D,UAAU;CACnB7D,KAAKmE,aAAaE,iBAAiB;EACjCrE,KAAKmE,aAAa;EAClB,IAAInE,KAAK6D,aAAa,QAAQ7D,KAAKgE,MAAMmC,SAAS,KAAK,CAACnG,KAAKkE,WAC3DkC,QAAQC,KACN,cAAcrG,KAAKgE,MAAMmC,OAAM,oCAAqC7B,cAAa,sDACnF;CAEJ,GAAGA,aAAa;AAClB;AAEA,MAAagC,wBACXlD,aAKsE;CACtE,MAAM,CAACwD,SAAShJ,eAAe;EAC7B,MAAMoC,OAAqB;GACzB6D,UAAU;GACVG,OAAO,CAAA;GACPC,SAAS;GACTpD,UAAU;GACVgB,KAAK;GACLqC,WAAW;GACXC,YAAY;EACd;EACA,MAAM/C,QAAQlD,mBAGXwD,QAAQC,WACP,IAAIqB,SAASO,SAASC,WAAW;GAC/B,IAAIxD,KAAKkE,WAAW;IAClBV,uBAAO,IAAIkB,MAAM,0CAA0C,CAAC;IAC5D;GACF;GACA1E,KAAKgE,MAAMvD,KAAK;IACdiB;IACAC;IACAC,IAAIiF,KAAKC,IAAI;IACbvD;IACAC;GACF,CAAC;GACDwC,KAAKhG,IAAI;EACX,CAAC,CACL;EACAkD,cAAc/B,IAAIC,OAAO;GACvByB,cAAchC,aAAa;IACzBb,KAAKa,WAAWA;GAClB;GACAoC,eAAgBjD,KAAK6D,WAAWW,OAAOuC,KAAK/G,KAAK6D,QAAQ,IAAI,CAAA;GAC7Df,SAASW,WACP,IAAIT,SAASO,WAASC,aAAW;IAC/B,IAAIxD,KAAKkE,WAAW;KAClBV,yBAAO,IAAIkB,MAAM,0CAA0C,CAAC;KAC5D;IACF;IACA1E,KAAKgE,MAAMvD,KAAK;KACdiB,QAAQ+B,OAAO/B;KACfC,QAAQ8B,OAAO9B;KACfC,IAAIiF,KAAKC,IAAI;KACbvD,SAAAA;KACAC,QAAAA;KACAC;IACF,CAAC;IACDuC,KAAKhG,IAAI;GACX,CAAC;EACL,CAAC;EACD,OAAO;GAAEA;GAAMoB;EAAM;CACvB,CAAC;CAEDzD,gBAAgB;EACd,MAAM,EAAEqC,MAAAA,WAAS4G;EACjB5G,OAAKkE,YAAY;EACjB,aAAa;GACXlE,OAAKkE,YAAY;GACjBlE,OAAK6D,WAAW;GAChB,IAAI7D,OAAKmE,eAAe,MAAM;IAC5B6C,aAAahH,OAAKmE,UAAU;IAC5BnE,OAAKmE,aAAa;GACpB;GACA8C,qBAAqB;IACnB,IAAI,CAACjH,OAAKkE,WAAW;IACrB,MAAMgD,SAASlH,OAAKgE;IACpBhE,OAAKgE,QAAQ,CAAA;IACb,KAAK,MAAMjB,QAAQmE,QACjBnE,KAAKS,uBAAO,IAAIkB,MAAM,sBAAsB,CAAC;GAEjD,CAAC;EACH;CACF,GAAG,CAACkC,KAAK,CAAC;CAEVjJ,gBAAgB;EACd,IAAIyF,UACG;QAAA,MAAM1B,YAAU8C,OAAOuC,KAAK3D,QAAQ,GACvC,IAAI1B,SAAOyF,WAAW,YAAY,GAChC,MAAM,IAAIzC,MACR,+BAA+BhD,SAAM,iDACvC;EAAA;EAINkF,MAAM5G,KAAK6D,WAAWT,YAAY;EAClC4C,KAAKY,MAAM5G,IAAI;CACjB,CAAC;CAED,OAAO4G,MAAMxF;AACf"}
|
|
1
|
+
{"version":3,"file":"host.js","names":["useEffect","useState","applyOps","sanitizeValue","StatewirePath","StatewireReject","createStateDraft","createMethodProxy","StateDraft","StatewireSendError","Statewire","StatewireHost","isDev","process","env","stateHosts","WeakMap","StateHost","getStateHost","state","get","StateCell","current","draft","changed","onOp","op","Op","onChange","ctl","StateCtl","host","bump","useStatewireState","init","TState","setVersion","cell","commit","c","flush","v","apply","ops","result","invalidate","push","changedPaths","snapshot","setOnOp","listener","setOnChange","takeChanged","value","record","changedPath","set","proxy","const","Settled","type","error","CommandsInvocation","method","params","ts","seq","clientId","CommandsOutcome","payload","CommandsListener","onStart","inv","onPosted","onApplied","onCovered","onSettle","outcome","CommandsSubmission","caller","Caller","CommandsHost","setListener","submit","call","Promise","methods","abort","commandsHosts","getCommandsHost","commands","bindCommandsHost","QueuedCall","resolve","reject","origin","ActiveInvocation","applied","controller","AbortController","settled","CommandsCell","handlers","Record","args","queue","active","Map","running","unmounted","stallTimer","ReturnType","setTimeout","STALL_WARN_MS","LOCAL_CALLER","Object","freeze","Error","auth","undefined","context","isConnected","toSendError","fate","cause","message","String","applyInvocation","settleInvocation","delete","abortInvocations","clear","isThenable","PromiseLike","then","handlerOf","prototype","propertyIsEnumerable","handler","dispatch","code","ctx","Ctx","signal","this","resolved","pump","watchStall","shift","length","console","warn","useStatewireCommands","Commands","THandlers","ThisType","CommandsProxy","HandledCommands","built","Date","now","keys","filter","clearTimeout","queueMicrotask","queued","startsWith"],"sources":["../../src/host/host.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { applyOps, sanitizeValue } from \"../wire/ops\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport { StatewireReject } from \"./engine\";\nimport { createStateDraft } from \"./draft\";\nimport { createMethodProxy } from \"../util/methodProxy\";\nimport type { StateDraft } from \"./draft\";\nimport { StatewireSendError } from \"../types\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireHost } from \"../host\";\n\nconst isDev = () =>\n typeof process === \"undefined\" || process.env[\"NODE_ENV\"] !== \"production\";\n\n// ─── state ──────────────────────────────────────────────\n\nconst stateHosts = new WeakMap<object, StatewireHost.StateHost>();\n\n/** Host-side accessor for a `useStatewireState` state object's source (`snapshot()` reads the committed state). */\nexport const getStateHost = (\n state: object,\n): StatewireHost.StateHost | undefined => stateHosts.get(state);\n\ntype StateCell = {\n current: unknown;\n draft: StateDraft<object> | null;\n changed: StatewirePath[];\n onOp: ((op: Statewire.Op) => void) | null;\n onChange: (() => void) | null;\n ctl: StatewireHost.StateCtl;\n host: StatewireHost.StateHost;\n bump: () => void;\n};\n\nexport const useStatewireState = <TState>(\n init: () => TState,\n): readonly [TState, StatewireHost.StateCtl<TState>] => {\n const [, setVersion] = useState(0);\n const [cell] = useState((): StateCell => {\n const commit = () => {\n if (c.draft) c.current = c.draft.flush();\n return c.current;\n };\n const c: StateCell = {\n current: sanitizeValue(init()),\n draft: null,\n changed: [[]],\n onOp: null,\n onChange: null,\n bump: () => setVersion((v) => v + 1),\n ctl: {\n apply: (ops) => {\n const result = applyOps(commit(), ops);\n c.current = result.state;\n c.draft?.invalidate();\n c.changed.push(...result.changedPaths);\n if (c.onOp) for (const op of ops) c.onOp(op);\n c.bump();\n c.onChange?.();\n },\n snapshot: commit,\n },\n host: {\n snapshot: commit,\n setOnOp: (listener) => {\n c.onOp = listener;\n },\n setOnChange: (listener) => {\n c.onChange = listener;\n },\n takeChanged: () => {\n const changed = c.changed;\n c.changed = [];\n return changed;\n },\n },\n };\n return c;\n });\n\n let value = cell.ctl.snapshot();\n if (typeof value === \"object\" && value !== null) {\n cell.draft ??= createStateDraft<object>({\n snapshot: () => cell.current,\n record: (op, changedPath) => {\n cell.changed.push(changedPath);\n cell.onOp?.(op);\n cell.bump();\n cell.onChange?.();\n },\n });\n stateHosts.set(cell.draft.proxy, cell.host);\n value = cell.draft.proxy;\n }\n return [value as TState, cell.ctl as StatewireHost.StateCtl<TState>] as const;\n};\n\n// ─── commands ───────────────────────────────────────────\n\ntype Settled =\n | { type: \"resolved\"; value: unknown }\n | { type: \"rejected\"; error: unknown };\n\nexport type CommandsInvocation = {\n readonly method: string;\n readonly params: readonly unknown[];\n readonly ts: number;\n readonly seq: number;\n readonly clientId?: string;\n};\n\nexport type CommandsOutcome =\n | { type: \"accepted\"; payload?: unknown }\n | { type: \"rejected\"; error: unknown };\n\nexport type CommandsListener = {\n onStart: (inv: CommandsInvocation) => void;\n onPosted?: (inv: CommandsInvocation) => void;\n onApplied: (inv: CommandsInvocation) => void;\n /** Canonical state now covers the invocation's effect — drop any overlay. */\n onCovered?: (inv: CommandsInvocation) => void;\n onSettle: (inv: CommandsInvocation, outcome: CommandsOutcome) => void;\n};\n\nexport type CommandsSubmission = {\n method: string;\n params: readonly unknown[];\n clientId?: string;\n caller?: StatewireHost.Caller;\n onApplied?: () => void;\n onSettle?: (outcome: CommandsOutcome) => void;\n};\n\nexport type CommandsHost = {\n setListener: (listener: CommandsListener | null) => void;\n submit?: (call: CommandsSubmission) => Promise<unknown>;\n /** Registered command names, read live. */\n methods?: () => string[];\n abort?: () => void;\n};\n\nconst commandsHosts = new WeakMap<object, CommandsHost>();\n\nexport const getCommandsHost = (commands: object): CommandsHost | undefined =>\n commandsHosts.get(commands);\n\nexport const bindCommandsHost = (commands: object, host: CommandsHost) => {\n commandsHosts.set(commands, host);\n};\n\ntype QueuedCall = {\n method: string;\n params: readonly unknown[];\n ts: number;\n resolve: (value: unknown) => void;\n reject: (error: unknown) => void;\n origin?: CommandsSubmission;\n};\n\ntype ActiveInvocation = CommandsInvocation & {\n applied: boolean;\n controller: AbortController;\n settled: boolean;\n origin?: CommandsSubmission;\n};\n\ntype CommandsCell = {\n handlers: Record<string, (...args: never[]) => unknown> | null;\n queue: QueuedCall[];\n active: Map<ActiveInvocation, QueuedCall>;\n running: boolean;\n listener: CommandsListener | null;\n seq: number;\n unmounted: boolean;\n stallTimer: ReturnType<typeof setTimeout> | null;\n};\n\nconst STALL_WARN_MS = 5000;\n\n// In-process dispatch has no wire client: never any ambient context, trivially attached.\nconst LOCAL_CALLER: StatewireHost.Caller = Object.freeze({\n get clientId(): string {\n throw new Error(\"statewire: in-process dispatch has no client id\");\n },\n auth: undefined,\n context: null,\n isConnected: true,\n});\n\nconst toSendError = (error: unknown): StatewireSendError =>\n error instanceof StatewireSendError\n ? error\n : error instanceof StatewireReject\n ? new StatewireSendError({\n fate: \"rejected\",\n cause: \"server\",\n message: error.message,\n ...(error.payload !== undefined && { payload: error.payload }),\n })\n : new StatewireSendError({\n fate: \"failed\",\n cause: \"server\",\n message: error instanceof Error ? error.message : String(error),\n });\n\nconst applyInvocation = (cell: CommandsCell, inv: ActiveInvocation) => {\n if (inv.applied) return;\n inv.applied = true;\n cell.listener?.onApplied(inv);\n cell.listener?.onCovered?.(inv);\n inv.origin?.onApplied?.();\n};\n\nconst settleInvocation = (\n cell: CommandsCell,\n inv: ActiveInvocation,\n call: QueuedCall,\n settled: Settled,\n) => {\n if (inv.settled) return;\n inv.settled = true;\n cell.active.delete(inv);\n applyInvocation(cell, inv);\n if (settled.type === \"resolved\") {\n const outcome: CommandsOutcome =\n settled.value === undefined\n ? { type: \"accepted\" }\n : { type: \"accepted\", payload: sanitizeValue(settled.value) };\n cell.listener?.onSettle(inv, outcome);\n inv.origin?.onSettle?.(outcome);\n call.resolve(outcome.payload);\n } else {\n const error = toSendError(settled.error);\n const outcome: CommandsOutcome = { type: \"rejected\", error };\n cell.listener?.onSettle(inv, outcome);\n inv.origin?.onSettle?.(outcome);\n call.reject(error);\n }\n};\n\nconst abortInvocations = (cell: CommandsCell) => {\n for (const [inv, call] of cell.active) {\n inv.settled = true;\n inv.controller.abort();\n const error = new StatewireSendError({ fate: \"crashed\", cause: \"server\" });\n const outcome: CommandsOutcome = { type: \"rejected\", error };\n cell.listener?.onSettle(inv, outcome);\n inv.origin?.onSettle?.(outcome);\n call.reject(error);\n }\n cell.active.clear();\n};\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\";\n\n// A command is an own, enumerable, function-valued property — exactly what\n// `Object.keys` shows, so dispatch, `statewire/commands`, and the reserved-\n// namespace guard share one view; prototype-chain names are not commands.\nconst handlerOf = (\n handlers: Record<string, (...args: never[]) => unknown>,\n method: string,\n): ((...args: never[]) => unknown) | undefined => {\n if (!Object.prototype.propertyIsEnumerable.call(handlers, method)) {\n return undefined;\n }\n const handler = handlers[method];\n return typeof handler === \"function\" ? handler : undefined;\n};\n\nconst dispatch = (cell: CommandsCell, call: QueuedCall) => {\n const handler = handlerOf(cell.handlers!, call.method);\n if (handler === undefined) {\n const error = new StatewireSendError({\n fate: \"rejected\",\n cause: \"server\",\n code: \"unknown-command\",\n });\n call.origin?.onSettle?.({ type: \"rejected\", error });\n call.reject(error);\n return;\n }\n const inv: ActiveInvocation = {\n method: call.method,\n params: call.params,\n ts: call.ts,\n seq: ++cell.seq,\n applied: false,\n controller: new AbortController(),\n settled: false,\n ...(call.origin !== undefined && { origin: call.origin }),\n ...(call.origin?.clientId !== undefined && {\n clientId: call.origin.clientId,\n }),\n };\n cell.active.set(inv, call);\n cell.listener?.onStart(inv);\n cell.listener?.onPosted?.(inv);\n const ctx: StatewireHost.Ctx = {\n caller: call.origin?.caller ?? LOCAL_CALLER,\n signal: inv.controller.signal,\n applied: () => {\n if (!inv.settled) applyInvocation(cell, inv);\n },\n };\n try {\n const value = (\n handler as (\n this: StatewireHost.Ctx,\n ...args: readonly unknown[]\n ) => unknown\n ).call(ctx, ...call.params);\n if (isThenable(value)) {\n value.then(\n (resolved) =>\n settleInvocation(cell, inv, call, {\n type: \"resolved\",\n value: resolved,\n }),\n (error: unknown) =>\n settleInvocation(cell, inv, call, { type: \"rejected\", error }),\n );\n } else {\n settleInvocation(cell, inv, call, { type: \"resolved\", value });\n }\n } catch (error) {\n settleInvocation(cell, inv, call, { type: \"rejected\", error });\n }\n};\n\n// Prefix-only advancement: each handler runs synchronously to its first\n// await, then the pump moves on; settlement rides the returned promise.\nconst pump = (cell: CommandsCell) => {\n if (cell.running || !cell.handlers) {\n watchStall(cell);\n return;\n }\n cell.running = true;\n try {\n while (cell.handlers) {\n const call = cell.queue.shift();\n if (!call) break;\n dispatch(cell, call);\n }\n } finally {\n cell.running = false;\n }\n};\n\nconst watchStall = (cell: CommandsCell) => {\n if (!isDev() || cell.stallTimer !== null || cell.queue.length === 0) return;\n if (cell.handlers) return;\n cell.stallTimer = setTimeout(() => {\n cell.stallTimer = null;\n if (cell.handlers === null && cell.queue.length > 0 && !cell.unmounted) {\n console.warn(\n `statewire: ${cell.queue.length} buffered command(s) waiting over ${STALL_WARN_MS}ms — did the host forget to arm useStatewireCommands?`,\n );\n }\n }, STALL_WARN_MS);\n};\n\nexport const useStatewireCommands = <THandlers extends Statewire.Commands>(\n commands:\n | (THandlers & ThisType<StatewireHost.Ctx>)\n | undefined\n | null\n | false,\n): Statewire.CommandsProxy<StatewireHost.HandledCommands<THandlers>> => {\n const [built] = useState(() => {\n const cell: CommandsCell = {\n handlers: null,\n queue: [],\n active: new Map(),\n running: false,\n listener: null,\n seq: 0,\n unmounted: false,\n stallTimer: null,\n };\n const proxy = createMethodProxy<\n Statewire.CommandsProxy<StatewireHost.HandledCommands<THandlers>>\n >(\n (method, params) =>\n new Promise((resolve, reject) => {\n if (cell.unmounted) {\n reject(new Error(\"statewire: commands called after unmount\"));\n return;\n }\n cell.queue.push({\n method,\n params,\n ts: Date.now(),\n resolve,\n reject,\n });\n pump(cell);\n }),\n );\n commandsHosts.set(proxy, {\n abort: () => abortInvocations(cell),\n setListener: (listener) => {\n cell.listener = listener;\n },\n methods: () => {\n const handlers = cell.handlers;\n if (!handlers) return [];\n return Object.keys(handlers).filter(\n (method) => handlerOf(handlers, method) !== undefined,\n );\n },\n submit: (origin) =>\n new Promise((resolve, reject) => {\n if (cell.unmounted) {\n reject(new Error(\"statewire: commands called after unmount\"));\n return;\n }\n cell.queue.push({\n method: origin.method,\n params: origin.params,\n ts: Date.now(),\n resolve,\n reject,\n origin,\n });\n pump(cell);\n }),\n });\n return { cell, proxy };\n });\n\n useEffect(() => {\n const { cell } = built;\n cell.unmounted = false;\n return () => {\n cell.unmounted = true;\n cell.handlers = null;\n if (cell.stallTimer !== null) {\n clearTimeout(cell.stallTimer);\n cell.stallTimer = null;\n }\n queueMicrotask(() => {\n if (!cell.unmounted) return;\n abortInvocations(cell);\n const queued = cell.queue;\n cell.queue = [];\n for (const call of queued) {\n call.reject(new Error(\"statewire: unmounted\"));\n }\n });\n };\n }, [built]);\n\n useEffect(() => {\n if (commands) {\n for (const method of Object.keys(commands)) {\n if (method.startsWith(\"statewire/\")) {\n throw new Error(\n `statewire: cannot register \"${method}\": the \"statewire/\" method namespace is reserved`,\n );\n }\n }\n }\n built.cell.handlers = commands || null;\n pump(built.cell);\n });\n\n return built.proxy;\n};\n"],"mappings":"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"}
|