statewire 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -42,6 +42,7 @@ type Conn = {
42
42
  hasSnapshot: boolean;
43
43
  lease: string | null;
44
44
  attempt: number;
45
+ liveAt: number | null;
45
46
  episode: Episode | null;
46
47
  awaitingHello: boolean;
47
48
  held: StatewireCmd[];
@@ -54,7 +55,8 @@ type Conn = {
54
55
  notify: (connection: StatewireClient.Connection) => void;
55
56
  reconnect: () => void;
56
57
  };
57
- declare const handleEnvelope: (c: Conn, env: StatewireEnvelope) => AttemptOutcome | null;
58
+ declare const validateRefusalSyn: (value: unknown) => StatewireSyn;
59
+ declare const handleEnvelope: (c: Conn, value: unknown) => AttemptOutcome | null;
58
60
  declare const useStatewireConn: (props: {
59
61
  url: string;
60
62
  onChange?: ((connection: StatewireClient.Connection) => void) | undefined;
@@ -63,5 +65,5 @@ declare const useStatewireConn: (props: {
63
65
  }) => Conn;
64
66
  declare const classify: (timeout: AbortSignal) => Error;
65
67
  //#endregion
66
- export { AttemptOutcome, Conn, Episode, Gate, StatewireCmd, StatewireEnvelope, StatewireSyn, classify, handleEnvelope, useStatewireConn };
68
+ export { AttemptOutcome, Conn, Episode, Gate, StatewireCmd, StatewireEnvelope, StatewireSyn, classify, handleEnvelope, useStatewireConn, validateRefusalSyn };
67
69
  //# sourceMappingURL=connection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","names":[],"sources":["../../src/client/connection.ts"],"mappings":";;;;KAQY;EACV;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;EAEA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA,MAAM;EACN;EACA;EACA,MAAM;EACN,MAAM,cAAc;;KAGV;EAAS;EAAkB;;KAoC3B;KAEA;EACV,YAAY,gBAAgB;EAC5B;EACA;EACA;EACA,SAAS;EACT;EACA,MAAM;EACN,MAAM;EACN,OAAO;EACP,UAAU;EACV,KAAK;EACL,WAAW,YAAY,gBAAgB;EACvC,cAAc,OAAO,oBAAoB,QAAQ;EACjD,SAAS,YAAY,gBAAgB;EACrC;;cAyGW,iBACX,GAAG,MACH,KAAK,sBACJ;cAwFU,mBAAoB;EAC/B;EACA,aAAa,YAAY,gBAAgB;EACzC,KAAK;EACL,cAAc,GAAG,MAAM,OAAO,oBAAoB,QAAQ;MACxD;cAkDS,WAAY,SAAS,gBAAW"}
1
+ {"version":3,"file":"connection.d.ts","names":[],"sources":["../../src/client/connection.ts"],"mappings":";;;;KAQY;EACV;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;EAEA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA,MAAM;EACN;EACA;EACA,MAAM;EACN,MAAM,cAAc;;KAGV;EAAS;EAAkB;;KAoC3B;KAEA;EACV,YAAY,gBAAgB;EAC5B;EACA;EACA;EACA;EACA,SAAS;EACT;EACA,MAAM;EACN,MAAM;EACN,OAAO;EACP,UAAU;EACV,KAAK;EACL,WAAW,YAAY,gBAAgB;EACvC,cAAc,OAAO,oBAAoB,QAAQ;EACjD,SAAS,YAAY,gBAAgB;EACrC;;cA8CW,qBAAsB,mBAAiB;cAyNvC,iBACX,GAAG,MACH,mBACC;cAuFU,mBAAoB;EAC/B;EACA,aAAa,YAAY,gBAAgB;EACzC,KAAK;EACL,cAAc,GAAG,MAAM,OAAO,oBAAoB,QAAQ;MACxD;cAoDS,WAAY,SAAS,gBAAW"}
@@ -1,5 +1,5 @@
1
1
  import { reviveOps, reviveValue } from "../wire/meta.js";
2
- import { backoff } from "./timing.js";
2
+ import { backoff, timing } from "./timing.js";
3
3
  import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
4
4
  import { flushTapSync } from "@assistant-ui/tap";
5
5
  //#region src/client/connection.ts
@@ -45,6 +45,58 @@ const setStatus = (c, next) => {
45
45
  const protocolError = (message) => {
46
46
  throw new Error(`statewire: protocol error: ${message}`);
47
47
  };
48
+ const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
49
+ const isNonnegativeSafeInteger = (value) => Number.isSafeInteger(value) && value >= 0;
50
+ const isPositiveSafeInteger = (value) => Number.isSafeInteger(value) && value > 0;
51
+ const validateOptionalString = (value, field) => {
52
+ if (value !== void 0 && typeof value !== "string") protocolError(`${field} must be a string`);
53
+ };
54
+ const validateSynScalars = (syn) => {
55
+ if (syn["seq"] !== void 0 && !isNonnegativeSafeInteger(syn["seq"])) protocolError("syn.seq must be a nonnegative safe integer");
56
+ if (syn["ctxSeq"] !== void 0 && !isNonnegativeSafeInteger(syn["ctxSeq"])) protocolError("syn.ctxSeq must be a nonnegative safe integer");
57
+ if (syn["retry"] !== void 0 && !isNonnegativeSafeInteger(syn["retry"])) protocolError("syn.retry must be a nonnegative safe integer");
58
+ validateOptionalString(syn["id"], "syn.id");
59
+ if (syn["idle"] !== void 0 && typeof syn["idle"] !== "boolean") protocolError("syn.idle must be a boolean");
60
+ validateOptionalString(syn["record"], "syn.record");
61
+ };
62
+ const validateRefusalSyn = (value) => {
63
+ if (!isObject(value)) return protocolError("syn must be an object");
64
+ validateSynScalars(value);
65
+ if (value["id"] !== void 0 || value["idle"] !== void 0 || value["record"] !== void 0) protocolError("invalid refusal syn");
66
+ if (value["seq"] === void 0 && value["ctxSeq"] === void 0 && value["retry"] === void 0) protocolError("refusal syn has no watermarks or retry");
67
+ return value;
68
+ };
69
+ const validateCmd = (value) => {
70
+ if (!isObject(value)) return protocolError("cmd entry must be an object");
71
+ if (!isPositiveSafeInteger(value["seq"])) protocolError("cmd.seq must be a positive safe integer");
72
+ validateOptionalString(value["type"], "cmd.type");
73
+ validateOptionalString(value["code"], "cmd.code");
74
+ validateOptionalString(value["message"], "cmd.message");
75
+ if (value["dur"] !== void 0 && value["dur"] !== true) protocolError("cmd.dur must be true");
76
+ return true;
77
+ };
78
+ const validateFin = (value) => {
79
+ if (!isObject(value)) return protocolError("fin must be an object");
80
+ if (typeof value["reason"] !== "string") protocolError("fin.reason must be a string");
81
+ validateOptionalString(value["message"], "fin.message");
82
+ return true;
83
+ };
84
+ const validateEnvelope = (value) => {
85
+ if (!isObject(value)) return protocolError("packet must be an object");
86
+ if (value["ops"] !== void 0 && !Array.isArray(value["ops"])) protocolError("ops must be an array");
87
+ if (value["cmd"] !== void 0) {
88
+ const cmd = value["cmd"];
89
+ if (!Array.isArray(cmd)) return protocolError("cmd must be an array");
90
+ for (const entry of cmd) validateCmd(entry);
91
+ }
92
+ if (value["idle"] !== void 0 && typeof value["idle"] !== "boolean") protocolError("idle must be a boolean");
93
+ if (value["next"] !== void 0) {
94
+ if (value["next"] !== true) protocolError("next must be true");
95
+ if (value["cmd"] === void 0 || value["ops"] !== void 0 || value["fin"] !== void 0) protocolError("next must ride a cmd-only packet");
96
+ }
97
+ if (value["fin"] !== void 0) validateFin(value["fin"]);
98
+ return value;
99
+ };
48
100
  const releaseHeld = (c) => {
49
101
  if (c.held.length === 0) return;
50
102
  const held = c.held;
@@ -53,29 +105,56 @@ const releaseHeld = (c) => {
53
105
  };
54
106
  const cmdsOf = (env) => {
55
107
  if (env.cmd === void 0) return [];
56
- if (!Array.isArray(env.cmd)) return protocolError("cmd must be an array");
57
108
  return env.cmd;
58
109
  };
110
+ const snapshotOf = (env) => {
111
+ const ops = env.ops;
112
+ if (ops === void 0) return protocolError("hello missing snapshot");
113
+ if (ops.length !== 1 || !isObject(ops[0])) return protocolError("hello snapshot must be one root replace op");
114
+ const op = ops[0];
115
+ if (op["op"] !== "replace" || !Array.isArray(op["path"]) || op["path"].length !== 0 || !Object.hasOwn(op, "value")) return protocolError("hello snapshot must be one root replace op");
116
+ return reviveOps(ops);
117
+ };
118
+ const helloSynOf = (env) => {
119
+ if (!isObject(env.syn)) return protocolError("expected hello");
120
+ validateSynScalars(env.syn);
121
+ if (env.syn["retry"] !== void 0) protocolError("hello syn cannot carry retry");
122
+ return env.syn;
123
+ };
59
124
  const handleHello = (c, env) => {
60
- const syn = env.syn;
61
- if (syn === void 0) return protocolError("expected hello");
62
- c.awaitingHello = false;
63
- c.hasSnapshot = true;
125
+ const syn = helloSynOf(env);
126
+ const ops = snapshotOf(env);
64
127
  c.ctx.onHello({
65
- ops: env.ops === void 0 ? [] : reviveOps(env.ops),
128
+ ops,
66
129
  syn
67
130
  });
68
131
  c.ctx.onIdle(syn.idle ?? false);
69
- c.attempt = 0;
132
+ c.awaitingHello = false;
133
+ c.hasSnapshot = true;
134
+ c.liveAt = Date.now();
70
135
  c.episode = null;
71
136
  setStatus(c, { status: "live" });
72
137
  };
73
- const deliverEnvelope = (c, env) => {
74
- if (env.syn !== void 0) {
75
- const syn = env.syn;
76
- if (syn.seq !== void 0 || syn.ctxSeq !== void 0 || syn.retry !== void 0) c.ctx.onRefusal(syn);
77
- else if (syn.id === void 0) protocolError("invalid mid-stream syn");
138
+ let warnedUnknownSynFact = false;
139
+ const warnUnknownSynFact = () => {
140
+ if (warnedUnknownSynFact) return;
141
+ warnedUnknownSynFact = true;
142
+ console.warn("statewire: ignoring unknown syn fact");
143
+ };
144
+ const deliverSyn = (c, value) => {
145
+ if (!isObject(value)) return protocolError("syn must be an object");
146
+ validateSynScalars(value);
147
+ if (value["record"] !== void 0 || value["idle"] !== void 0) protocolError("invalid mid-stream syn");
148
+ if (value["seq"] !== void 0 || value["ctxSeq"] !== void 0 || value["retry"] !== void 0) {
149
+ c.ctx.onRefusal(validateRefusalSyn(value));
150
+ return;
78
151
  }
152
+ if (value["id"] !== void 0) return;
153
+ if (Object.keys(value).length === 0) protocolError("invalid mid-stream syn");
154
+ warnUnknownSynFact();
155
+ };
156
+ const deliverEnvelope = (c, env) => {
157
+ if (env.syn !== void 0) deliverSyn(c, env.syn);
79
158
  if (env.ops !== void 0) {
80
159
  const held = c.held;
81
160
  c.held = [];
@@ -90,7 +169,14 @@ const deliverEnvelope = (c, env) => {
90
169
  }
91
170
  if (typeof env.idle === "boolean") c.ctx.onIdle(env.idle);
92
171
  };
93
- const isTransientFinish = (reason) => reason === "evicted" || reason === "error";
172
+ const transientCauseOf = (reason) => {
173
+ switch (reason) {
174
+ case "evicted": return "evicted";
175
+ case "error": return "error";
176
+ case "unauthorized": return "unauthorized";
177
+ default: return "error";
178
+ }
179
+ };
94
180
  const settleFin = (c, fin) => {
95
181
  let finish = fin;
96
182
  if (finish.meta !== void 0) {
@@ -108,10 +194,14 @@ const settleFin = (c, fin) => {
108
194
  setStatus(c, { status: "idle" });
109
195
  return "idle";
110
196
  }
111
- c.ctx.onFinish(finish);
112
- if (isTransientFinish(finish.reason)) {
197
+ const terminal = finish.reason === "gone" || finish.reason === "superseded";
198
+ c.ctx.onFinish(terminal ? finish : {
199
+ ...finish,
200
+ reason: "error"
201
+ });
202
+ if (!terminal) {
113
203
  c.episode = {
114
- cause: finish.reason,
204
+ cause: transientCauseOf(finish.reason),
115
205
  ...finish.message !== void 0 && { message: finish.message }
116
206
  };
117
207
  return "reattach";
@@ -123,8 +213,8 @@ const settleFin = (c, fin) => {
123
213
  });
124
214
  return "stop";
125
215
  };
126
- const handleEnvelope = (c, env) => {
127
- if (typeof env !== "object" || env === null) return protocolError("packet must be an object");
216
+ const handleEnvelope = (c, value) => {
217
+ const env = validateEnvelope(value);
128
218
  if (c.awaitingHello) {
129
219
  if (env.fin !== void 0) return settleFin(c, env.fin);
130
220
  handleHello(c, env);
@@ -140,10 +230,12 @@ const handleEnvelope = (c, env) => {
140
230
  return null;
141
231
  };
142
232
  const scheduleRetry = (c, failure, immediate) => {
233
+ if (c.liveAt !== null && Date.now() - c.liveAt >= timing.backoffResetMs) c.attempt = 0;
234
+ c.liveAt = null;
143
235
  c.attempt += 1;
144
236
  c.episode ??= { cause: "dropped" };
145
237
  const delay = immediate ? 0 : backoff(c.attempt);
146
- if (c.hasSnapshot) setStatus(c, {
238
+ setStatus(c, {
147
239
  status: "reconnecting",
148
240
  ...c.episode,
149
241
  attempt: c.attempt,
@@ -158,8 +250,7 @@ const reconnectConn = (c) => {
158
250
  c.attempt = 0;
159
251
  c.episode = { cause: "dropped" };
160
252
  flushTapSync(() => {
161
- if (c.hasSnapshot) scheduleRetry(c, void 0, true);
162
- else setStatus(c, { status: "connecting" });
253
+ scheduleRetry(c, void 0, true);
163
254
  });
164
255
  }
165
256
  openGate(c.gate);
@@ -205,6 +296,7 @@ const useStatewireConn = (props) => {
205
296
  hasSnapshot: false,
206
297
  lease: null,
207
298
  attempt: 0,
299
+ liveAt: null,
208
300
  episode: null,
209
301
  awaitingHello: true,
210
302
  held: [],
@@ -229,6 +321,7 @@ const useStatewireConn = (props) => {
229
321
  c.hasSnapshot = false;
230
322
  c.lease = null;
231
323
  c.attempt = 0;
324
+ c.liveAt = null;
232
325
  c.episode = null;
233
326
  if (c.connection.status !== "connecting") setStatus(c, { status: "connecting" });
234
327
  const lifetime = new AbortController();
@@ -246,6 +339,6 @@ const useStatewireConn = (props) => {
246
339
  };
247
340
  const classify = (timeout) => /* @__PURE__ */ new Error(timeout.aborted ? "timeout" : "network");
248
341
  //#endregion
249
- export { classify, handleEnvelope, useStatewireConn };
342
+ export { classify, handleEnvelope, useStatewireConn, validateRefusalSyn };
250
343
 
251
344
  //# sourceMappingURL=connection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","names":["useEffect","useRef","useState","flushTapSync","reviveOps","reviveValue","backoff","ConnectionState","StatewireRemoteProps","StatewireClient","StatewireHost","Episode","cause","message","StatewireCmd","seq","type","code","payload","meta","dur","StatewireSyn","ctxSeq","record","id","idle","retry","StatewireEnvelope","ops","cmd","next","syn","fin","Fin","Gate","latched","wake","newGate","undefined","takeGate","g","was","waitGate","timeoutMs","Promise","resolve","timer","setTimeout","clearTimeout","openGate","AttemptOutcome","Conn","connection","Connection","hasSnapshot","lease","attempt","episode","awaitingHello","held","gate","abort","AbortController","lifetime","ctx","onChange","attemptOnce","notify","reconnect","setStatus","c","changed","status","protocolError","Error","releaseHeld","length","onCmds","cmdsOf","env","Array","isArray","handleHello","onHello","onIdle","deliverEnvelope","onRefusal","onOps","cmds","push","isTransientFinish","reason","settleFin","finish","rest","onFinish","handleEnvelope","scheduleRetry","failure","immediate","delay","nextRetryAt","Date","now","lastError","reconnectConn","run","alive","outcome","error","signal","aborted","onDetach","useStatewireConn","props","url","latest","current","setConnection","conn","classify","timeout","AbortSignal"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveValue } from \"../wire/meta\";\nimport { backoff } from \"./timing\";\nimport type { ConnectionState, StatewireRemoteProps } from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"evicted\" | \"error\" | \"unauthorized\";\n message?: string;\n};\n\nexport type StatewireCmd = {\n seq: number;\n type?: \"applied\" | \"result\" | \"rejected\" | \"failed\" | \"crashed\" | \"expired\";\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n /** Cumulative: resending through this seq will never be needed. */\n dur?: boolean;\n};\n\nexport type StatewireSyn = {\n seq?: number;\n ctxSeq?: number;\n record?: \"fresh\" | \"resumed\" | \"ephemeral\";\n id?: string;\n idle?: boolean;\n retry?: number;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n cmd?: StatewireCmd[];\n next?: true;\n idle?: boolean;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nexport type Gate = { latched: boolean; wake: (() => void) | undefined };\n\nconst newGate = (): Gate => ({ latched: false, wake: undefined });\n\nconst takeGate = (g: Gate) => {\n const was = g.latched;\n g.latched = false;\n return was;\n};\n\nconst waitGate = (g: Gate, timeoutMs?: number) => {\n if (g.latched) {\n g.latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n g.wake = undefined;\n resolve();\n }, timeoutMs);\n g.wake = () => {\n clearTimeout(timer);\n g.wake = undefined;\n resolve();\n };\n });\n};\n\nconst openGate = (g: Gate) => {\n if (g.wake) g.wake();\n else g.latched = true;\n};\n\nexport type AttemptOutcome = \"stop\" | \"reattach\" | \"ended\" | \"idle\";\n\nexport type Conn = {\n connection: StatewireClient.Connection;\n hasSnapshot: boolean;\n lease: string | null;\n attempt: number;\n episode: Episode | null;\n awaitingHello: boolean;\n held: StatewireCmd[];\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (abort: AbortController) => Promise<AttemptOutcome>;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n const changed = next.status !== c.connection.status;\n c.connection = { ...next, reconnect: c.reconnect };\n c.notify(c.connection);\n if (changed) c.onChange(c.connection);\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\n// A hold's release delivers, never settles: fin and bare close both drain it.\nconst releaseHeld = (c: Conn) => {\n if (c.held.length === 0) return;\n const held = c.held;\n c.held = [];\n c.ctx.onCmds(held);\n};\n\nconst cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {\n if (env.cmd === undefined) return [];\n if (!Array.isArray(env.cmd)) return protocolError(\"cmd must be an array\");\n return env.cmd;\n};\n\nconst handleHello = (c: Conn, env: StatewireEnvelope) => {\n const syn = env.syn;\n if (syn === undefined) return protocolError(\"expected hello\");\n c.awaitingHello = false;\n c.hasSnapshot = true;\n c.ctx.onHello({\n ops: env.ops === undefined ? [] : reviveOps(env.ops),\n syn,\n });\n c.ctx.onIdle(syn.idle ?? false);\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"live\" });\n};\n\nconst deliverEnvelope = (c: Conn, env: StatewireEnvelope) => {\n if (env.syn !== undefined) {\n const syn = env.syn;\n if (\n syn.seq !== undefined ||\n syn.ctxSeq !== undefined ||\n syn.retry !== undefined\n ) {\n c.ctx.onRefusal(syn);\n } else if (syn.id === undefined) {\n protocolError(\"invalid mid-stream syn\");\n }\n }\n if (env.ops !== undefined) {\n const held = c.held;\n c.held = [];\n c.ctx.onOps({\n ops: reviveOps(env.ops),\n cmds: [...held, ...cmdsOf(env)],\n });\n } else if (env.cmd !== undefined) {\n const cmds = cmdsOf(env);\n if (env.next === true) c.held.push(...cmds);\n else c.ctx.onCmds(cmds);\n }\n if (typeof env.idle === \"boolean\") c.ctx.onIdle(env.idle);\n};\n\nconst isTransientFinish = (\n reason: StatewireHost.Fin[\"reason\"],\n): reason is \"evicted\" | \"error\" => reason === \"evicted\" || reason === \"error\";\n\nconst settleFin = (c: Conn, fin: StatewireHost.Fin): AttemptOutcome => {\n let finish = fin;\n if (finish.meta !== undefined) {\n const { meta, ...rest } = finish;\n finish = { ...rest, payload: reviveValue(rest.payload, meta) };\n }\n releaseHeld(c);\n if (finish.reason === \"idle\") {\n c.ctx.onIdle(true);\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"idle\" });\n return \"idle\";\n }\n c.ctx.onFinish(finish);\n if (isTransientFinish(finish.reason)) {\n c.episode = {\n cause: finish.reason,\n ...(finish.message !== undefined && { message: finish.message }),\n };\n return \"reattach\";\n }\n setStatus(c, {\n status: \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n};\n\nexport const handleEnvelope = (\n c: Conn,\n env: StatewireEnvelope,\n): AttemptOutcome | null => {\n if (typeof env !== \"object\" || env === null) {\n return protocolError(\"packet must be an object\");\n }\n if (c.awaitingHello) {\n if (env.fin !== undefined) return settleFin(c, env.fin);\n handleHello(c, env);\n return null;\n }\n deliverEnvelope(c, env);\n if (env.fin !== undefined) return settleFin(c, env.fin);\n if (c.connection.status !== \"live\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"live\" });\n }\n return null;\n};\n\nconst scheduleRetry = (\n c: Conn,\n failure: string | undefined,\n immediate: boolean,\n) => {\n c.attempt += 1;\n c.episode ??= { cause: \"dropped\" };\n const delay = immediate ? 0 : backoff(c.attempt);\n if (c.hasSnapshot) {\n setStatus(c, {\n status: \"reconnecting\",\n ...c.episode,\n attempt: c.attempt,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n }\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"gone\" || c.connection.status === \"idle\") {\n c.attempt = 0;\n c.episode = { cause: \"dropped\" };\n flushTapSync(() => {\n if (c.hasSnapshot) scheduleRetry(c, undefined, true);\n else setStatus(c, { status: \"connecting\" });\n });\n }\n openGate(c.gate);\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n while (alive()) {\n const abort = new AbortController();\n c.abort = abort;\n c.awaitingHello = true;\n c.held = [];\n let outcome: AttemptOutcome | undefined;\n let failure: string | undefined;\n try {\n outcome = await c.attemptOnce(abort);\n } catch (error) {\n if (!abort.signal.aborted) {\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n }\n }\n abort.abort();\n if (!alive()) return;\n flushTapSync(() => {\n releaseHeld(c);\n c.ctx.onDetach();\n });\n if (!alive()) return;\n if (outcome === \"stop\" || outcome === \"idle\") {\n await waitGate(gate);\n continue;\n }\n const immediate = takeGate(gate);\n const delay = flushTapSync(() => scheduleRetry(c, failure, immediate));\n if (delay === 0) continue;\n await waitGate(gate, delay);\n }\n};\n\nexport const useStatewireConn = (props: {\n url: string;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;\n}): Conn => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n hasSnapshot: false,\n lease: null,\n attempt: 0,\n episode: null,\n awaitingHello: true,\n held: [],\n abort: null,\n gate: newGate(),\n lifetime: null,\n get ctx() {\n return latest.current.ctx;\n },\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => latest.current.attemptOnce(conn, abort),\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: { status: \"connecting\", reconnect: () => conn.reconnect() },\n };\n return conn;\n });\n\n useEffect(() => {\n c.hasSnapshot = false;\n c.lease = null;\n c.attempt = 0;\n c.episode = null;\n if (c.connection.status !== \"connecting\") {\n setStatus(c, { status: \"connecting\" });\n }\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = newGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n openGate(c.gate);\n };\n }, [c, props.url]);\n\n return c;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n"],"mappings":"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"}
1
+ {"version":3,"file":"connection.js","names":["useEffect","useRef","useState","flushTapSync","reviveOps","reviveValue","backoff","timing","ConnectionState","StatewireRemoteProps","StatewireClient","StatewireHost","Episode","cause","message","StatewireCmd","seq","type","code","payload","meta","dur","StatewireSyn","ctxSeq","record","id","idle","retry","StatewireEnvelope","ops","cmd","next","syn","fin","Fin","Gate","latched","wake","newGate","undefined","takeGate","g","was","waitGate","timeoutMs","Promise","resolve","timer","setTimeout","clearTimeout","openGate","AttemptOutcome","Conn","connection","Connection","hasSnapshot","lease","attempt","liveAt","episode","awaitingHello","held","gate","abort","AbortController","lifetime","ctx","onChange","attemptOnce","notify","reconnect","setStatus","c","changed","status","protocolError","Error","isObject","value","Record","Array","isArray","isNonnegativeSafeInteger","Number","isSafeInteger","isPositiveSafeInteger","validateOptionalString","field","validateSynScalars","validateRefusalSyn","validateCmd","validateFin","validateEnvelope","entry","releaseHeld","length","onCmds","cmdsOf","env","snapshotOf","op","Object","hasOwn","helloSynOf","handleHello","onHello","onIdle","Date","now","warnedUnknownSynFact","warnUnknownSynFact","console","warn","deliverSyn","onRefusal","keys","deliverEnvelope","onOps","cmds","push","transientCauseOf","reason","settleFin","finish","rest","terminal","onFinish","handleEnvelope","scheduleRetry","failure","immediate","backoffResetMs","delay","nextRetryAt","lastError","reconnectConn","run","alive","outcome","error","signal","aborted","onDetach","useStatewireConn","props","url","latest","current","setConnection","conn","classify","timeout","AbortSignal"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveValue } from \"../wire/meta\";\nimport { backoff, timing } from \"./timing\";\nimport type { ConnectionState, StatewireRemoteProps } from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"evicted\" | \"error\" | \"unauthorized\";\n message?: string;\n};\n\nexport type StatewireCmd = {\n seq: number;\n type?: \"applied\" | \"result\" | \"rejected\" | \"failed\" | \"crashed\" | \"expired\";\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n /** Cumulative: resending through this seq will never be needed. */\n dur?: boolean;\n};\n\nexport type StatewireSyn = {\n seq?: number;\n ctxSeq?: number;\n record?: \"fresh\" | \"resumed\" | \"ephemeral\";\n id?: string;\n idle?: boolean;\n retry?: number;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n cmd?: StatewireCmd[];\n next?: true;\n idle?: boolean;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nexport type Gate = { latched: boolean; wake: (() => void) | undefined };\n\nconst newGate = (): Gate => ({ latched: false, wake: undefined });\n\nconst takeGate = (g: Gate) => {\n const was = g.latched;\n g.latched = false;\n return was;\n};\n\nconst waitGate = (g: Gate, timeoutMs?: number) => {\n if (g.latched) {\n g.latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n g.wake = undefined;\n resolve();\n }, timeoutMs);\n g.wake = () => {\n clearTimeout(timer);\n g.wake = undefined;\n resolve();\n };\n });\n};\n\nconst openGate = (g: Gate) => {\n if (g.wake) g.wake();\n else g.latched = true;\n};\n\nexport type AttemptOutcome = \"stop\" | \"reattach\" | \"ended\" | \"idle\";\n\nexport type Conn = {\n connection: StatewireClient.Connection;\n hasSnapshot: boolean;\n lease: string | null;\n attempt: number;\n liveAt: number | null;\n episode: Episode | null;\n awaitingHello: boolean;\n held: StatewireCmd[];\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (abort: AbortController) => Promise<AttemptOutcome>;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n const changed = next.status !== c.connection.status;\n c.connection = { ...next, reconnect: c.reconnect };\n c.notify(c.connection);\n if (changed) c.onChange(c.connection);\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isNonnegativeSafeInteger = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) >= 0;\n\nconst isPositiveSafeInteger = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) > 0;\n\nconst validateOptionalString = (value: unknown, field: string): void => {\n if (value !== undefined && typeof value !== \"string\") {\n protocolError(`${field} must be a string`);\n }\n};\n\nconst validateSynScalars = (syn: Record<string, unknown>) => {\n if (syn[\"seq\"] !== undefined && !isNonnegativeSafeInteger(syn[\"seq\"])) {\n protocolError(\"syn.seq must be a nonnegative safe integer\");\n }\n if (syn[\"ctxSeq\"] !== undefined && !isNonnegativeSafeInteger(syn[\"ctxSeq\"])) {\n protocolError(\"syn.ctxSeq must be a nonnegative safe integer\");\n }\n if (syn[\"retry\"] !== undefined && !isNonnegativeSafeInteger(syn[\"retry\"])) {\n protocolError(\"syn.retry must be a nonnegative safe integer\");\n }\n validateOptionalString(syn[\"id\"], \"syn.id\");\n if (syn[\"idle\"] !== undefined && typeof syn[\"idle\"] !== \"boolean\") {\n protocolError(\"syn.idle must be a boolean\");\n }\n validateOptionalString(syn[\"record\"], \"syn.record\");\n};\n\nexport const validateRefusalSyn = (value: unknown): StatewireSyn => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value);\n if (\n value[\"id\"] !== undefined ||\n value[\"idle\"] !== undefined ||\n value[\"record\"] !== undefined\n ) {\n protocolError(\"invalid refusal syn\");\n }\n if (\n value[\"seq\"] === undefined &&\n value[\"ctxSeq\"] === undefined &&\n value[\"retry\"] === undefined\n ) {\n protocolError(\"refusal syn has no watermarks or retry\");\n }\n return value as StatewireSyn;\n};\n\nconst validateCmd = (value: unknown): value is StatewireCmd => {\n if (!isObject(value)) return protocolError(\"cmd entry must be an object\");\n if (!isPositiveSafeInteger(value[\"seq\"])) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n validateOptionalString(value[\"type\"], \"cmd.type\");\n validateOptionalString(value[\"code\"], \"cmd.code\");\n validateOptionalString(value[\"message\"], \"cmd.message\");\n if (value[\"dur\"] !== undefined && value[\"dur\"] !== true) {\n protocolError(\"cmd.dur must be true\");\n }\n return true;\n};\n\nconst validateFin = (value: unknown): value is StatewireHost.Fin => {\n if (!isObject(value)) return protocolError(\"fin must be an object\");\n if (typeof value[\"reason\"] !== \"string\") {\n protocolError(\"fin.reason must be a string\");\n }\n validateOptionalString(value[\"message\"], \"fin.message\");\n return true;\n};\n\nconst validateEnvelope = (value: unknown): StatewireEnvelope => {\n if (!isObject(value)) return protocolError(\"packet must be an object\");\n if (value[\"ops\"] !== undefined && !Array.isArray(value[\"ops\"])) {\n protocolError(\"ops must be an array\");\n }\n if (value[\"cmd\"] !== undefined) {\n const cmd = value[\"cmd\"];\n if (!Array.isArray(cmd)) return protocolError(\"cmd must be an array\");\n for (const entry of cmd) validateCmd(entry);\n }\n if (value[\"idle\"] !== undefined && typeof value[\"idle\"] !== \"boolean\") {\n protocolError(\"idle must be a boolean\");\n }\n if (value[\"next\"] !== undefined) {\n if (value[\"next\"] !== true) protocolError(\"next must be true\");\n if (\n value[\"cmd\"] === undefined ||\n value[\"ops\"] !== undefined ||\n value[\"fin\"] !== undefined\n ) {\n protocolError(\"next must ride a cmd-only packet\");\n }\n }\n if (value[\"fin\"] !== undefined) validateFin(value[\"fin\"]);\n return value as StatewireEnvelope;\n};\n\n// A hold's release delivers, never settles: fin and bare close both drain it.\nconst releaseHeld = (c: Conn) => {\n if (c.held.length === 0) return;\n const held = c.held;\n c.held = [];\n c.ctx.onCmds(held);\n};\n\nconst cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {\n if (env.cmd === undefined) return [];\n return env.cmd;\n};\n\nconst snapshotOf = (env: StatewireEnvelope): unknown[] => {\n const ops = env.ops;\n if (ops === undefined) return protocolError(\"hello missing snapshot\");\n if (ops.length !== 1 || !isObject(ops[0])) {\n return protocolError(\"hello snapshot must be one root replace op\");\n }\n const op = ops[0];\n if (\n op[\"op\"] !== \"replace\" ||\n !Array.isArray(op[\"path\"]) ||\n op[\"path\"].length !== 0 ||\n !Object.hasOwn(op, \"value\")\n ) {\n return protocolError(\"hello snapshot must be one root replace op\");\n }\n return reviveOps(ops);\n};\n\nconst helloSynOf = (env: StatewireEnvelope): StatewireSyn => {\n if (!isObject(env.syn)) return protocolError(\"expected hello\");\n validateSynScalars(env.syn);\n if (env.syn[\"retry\"] !== undefined) {\n protocolError(\"hello syn cannot carry retry\");\n }\n return env.syn as StatewireSyn;\n};\n\nconst handleHello = (c: Conn, env: StatewireEnvelope) => {\n const syn = helloSynOf(env);\n const ops = snapshotOf(env);\n c.ctx.onHello({\n ops,\n syn,\n });\n c.ctx.onIdle(syn.idle ?? false);\n c.awaitingHello = false;\n c.hasSnapshot = true;\n c.liveAt = Date.now();\n c.episode = null;\n setStatus(c, { status: \"live\" });\n};\n\nlet warnedUnknownSynFact = false;\n\nconst warnUnknownSynFact = () => {\n if (warnedUnknownSynFact) return;\n warnedUnknownSynFact = true;\n console.warn(\"statewire: ignoring unknown syn fact\");\n};\n\nconst deliverSyn = (c: Conn, value: unknown) => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value);\n if (value[\"record\"] !== undefined || value[\"idle\"] !== undefined) {\n protocolError(\"invalid mid-stream syn\");\n }\n if (\n value[\"seq\"] !== undefined ||\n value[\"ctxSeq\"] !== undefined ||\n value[\"retry\"] !== undefined\n ) {\n c.ctx.onRefusal(validateRefusalSyn(value));\n return;\n }\n if (value[\"id\"] !== undefined) return;\n if (Object.keys(value).length === 0) {\n protocolError(\"invalid mid-stream syn\");\n }\n warnUnknownSynFact();\n};\n\nconst deliverEnvelope = (c: Conn, env: StatewireEnvelope) => {\n if (env.syn !== undefined) deliverSyn(c, env.syn);\n if (env.ops !== undefined) {\n const held = c.held;\n c.held = [];\n c.ctx.onOps({\n ops: reviveOps(env.ops),\n cmds: [...held, ...cmdsOf(env)],\n });\n } else if (env.cmd !== undefined) {\n const cmds = cmdsOf(env);\n if (env.next === true) c.held.push(...cmds);\n else c.ctx.onCmds(cmds);\n }\n if (typeof env.idle === \"boolean\") c.ctx.onIdle(env.idle);\n};\n\nconst transientCauseOf = (\n reason: StatewireHost.Fin[\"reason\"],\n): Episode[\"cause\"] => {\n switch (reason) {\n case \"evicted\":\n return \"evicted\";\n case \"error\":\n return \"error\";\n case \"unauthorized\":\n return \"unauthorized\";\n default:\n return \"error\";\n }\n};\n\nconst settleFin = (c: Conn, fin: StatewireHost.Fin): AttemptOutcome => {\n let finish = fin;\n if (finish.meta !== undefined) {\n const { meta, ...rest } = finish;\n finish = { ...rest, payload: reviveValue(rest.payload, meta) };\n }\n releaseHeld(c);\n if (finish.reason === \"idle\") {\n c.ctx.onIdle(true);\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"idle\" });\n return \"idle\";\n }\n const terminal = finish.reason === \"gone\" || finish.reason === \"superseded\";\n c.ctx.onFinish(terminal ? finish : { ...finish, reason: \"error\" });\n if (!terminal) {\n c.episode = {\n cause: transientCauseOf(finish.reason),\n ...(finish.message !== undefined && { message: finish.message }),\n };\n return \"reattach\";\n }\n setStatus(c, {\n status: \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n};\n\nexport const handleEnvelope = (\n c: Conn,\n value: unknown,\n): AttemptOutcome | null => {\n const env = validateEnvelope(value);\n if (c.awaitingHello) {\n if (env.fin !== undefined) return settleFin(c, env.fin);\n handleHello(c, env);\n return null;\n }\n deliverEnvelope(c, env);\n if (env.fin !== undefined) return settleFin(c, env.fin);\n if (c.connection.status !== \"live\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"live\" });\n }\n return null;\n};\n\nconst scheduleRetry = (\n c: Conn,\n failure: string | undefined,\n immediate: boolean,\n) => {\n if (c.liveAt !== null && Date.now() - c.liveAt >= timing.backoffResetMs) {\n c.attempt = 0;\n }\n c.liveAt = null;\n c.attempt += 1;\n c.episode ??= { cause: \"dropped\" };\n const delay = immediate ? 0 : backoff(c.attempt);\n setStatus(c, {\n status: \"reconnecting\",\n ...c.episode,\n attempt: c.attempt,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"gone\" || c.connection.status === \"idle\") {\n c.attempt = 0;\n c.episode = { cause: \"dropped\" };\n flushTapSync(() => {\n scheduleRetry(c, undefined, true);\n });\n }\n openGate(c.gate);\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n while (alive()) {\n const abort = new AbortController();\n c.abort = abort;\n c.awaitingHello = true;\n c.held = [];\n let outcome: AttemptOutcome | undefined;\n let failure: string | undefined;\n try {\n outcome = await c.attemptOnce(abort);\n } catch (error) {\n if (!abort.signal.aborted) {\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n }\n }\n abort.abort();\n if (!alive()) return;\n flushTapSync(() => {\n releaseHeld(c);\n c.ctx.onDetach();\n });\n if (!alive()) return;\n if (outcome === \"stop\" || outcome === \"idle\") {\n await waitGate(gate);\n continue;\n }\n const immediate = takeGate(gate);\n const delay = flushTapSync(() => scheduleRetry(c, failure, immediate));\n if (delay === 0) continue;\n await waitGate(gate, delay);\n }\n};\n\nexport const useStatewireConn = (props: {\n url: string;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;\n}): Conn => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n hasSnapshot: false,\n lease: null,\n attempt: 0,\n liveAt: null,\n episode: null,\n awaitingHello: true,\n held: [],\n abort: null,\n gate: newGate(),\n lifetime: null,\n get ctx() {\n return latest.current.ctx;\n },\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => latest.current.attemptOnce(conn, abort),\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: { status: \"connecting\", reconnect: () => conn.reconnect() },\n };\n return conn;\n });\n\n useEffect(() => {\n c.hasSnapshot = false;\n c.lease = null;\n c.attempt = 0;\n c.liveAt = null;\n c.episode = null;\n if (c.connection.status !== \"connecting\") {\n setStatus(c, { status: \"connecting\" });\n }\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = newGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n openGate(c.gate);\n };\n }, [c, props.url]);\n\n return c;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":";;;;;;KAyBK;EACH;EACA;EACA;;KAGG;WACM;WACA,SAAS;WACT,KAAK;;EAEd;;EAEA;;EAEA;EACA,UAAU;EACV,SAAS,OAAO;;KAGb;WACM;WACA;EACT;;KAiBG;KAEO,0BAA0B;EACpC;;KAGG;EACH,QAAQ;EACR,KAAK;EACL;EACA,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YAAY;EACZ;EACA,0BAA0B,qBAAqB;EAC/C;EACA,SAAS;EACT;EACA;EACA,SAAS;EACT,QAAQ,UAAU;EAClB,QAAQ;EACR;EACA;EACA;EACA,WAAW;EACX;EACA,WAAW;EACX;EACA,UAAU,mBAAmB,sBAAsB;;cA0d/C,eAAgB,GAAG,SAAS,WAAW;cA6DvC,aAAc,GAAG,SAAS,OAAO;cAoB1B,sBACX,SAAS,4BACR"}
1
+ {"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":";;;;;;KAyBK;EACH;EACA;EACA;;KAGG;WACM;WACA,SAAS;WACT,KAAK;;EAEd;;EAEA;;EAEA;EACA,UAAU;EACV,SAAS,OAAO;;KAGb;WACM;WACA;EACT;;KAiBG;KAEO,0BAA0B;EACpC;;KAGG;EACH,QAAQ;EACR,KAAK;EACL;EACA,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YAAY;EACZ;EACA,0BAA0B,qBAAqB;EAC/C;EACA,SAAS;EACT;EACA;EACA,SAAS;EACT,QAAQ,UAAU;EAClB,QAAQ;EACR;EACA;EACA;EACA,WAAW;EACX;EACA,WAAW;EACX;EACA,UAAU,mBAAmB,sBAAsB;;cAsd/C,eAAgB,GAAG,SAAS,WAAW;cA6DvC,aAAc,GAAG,SAAS,OAAO;cAoB1B,sBACX,SAAS,4BACR"}
@@ -150,17 +150,16 @@ const ephemeralDetach = (s) => {
150
150
  resetRecord(s, newClientId());
151
151
  };
152
152
  const rejectedFailure = (cmd) => {
153
- const code = cmd.code === void 0 || cmd.code === "unknown-command" || cmd.code === "invalid-params" ? cmd.code : protocolError(`unknown rejected code: ${cmd.code}`);
154
153
  return {
155
154
  fate: "rejected",
156
155
  cause: "server",
157
- ...code !== void 0 && { code },
156
+ ...cmd.code !== void 0 && { code: cmd.code },
158
157
  ...cmd.message !== void 0 && { message: cmd.message },
159
158
  ...cmd.payload !== void 0 && { payload: cmd.payload }
160
159
  };
161
160
  };
162
161
  const handleCmd = (s, cmd) => {
163
- if (typeof cmd.seq !== "number") protocolError("cmd entry missing seq");
162
+ if (!Number.isSafeInteger(cmd.seq) || cmd.seq <= 0) protocolError("cmd.seq must be a positive safe integer");
164
163
  if (cmd.dur === true) {
165
164
  s.durableSeq = Math.max(s.durableSeq, cmd.seq);
166
165
  for (const entry of s.pending) if (entry.seq <= s.durableSeq) entry.posted = true;
@@ -277,7 +276,7 @@ const handleRefusal = (s, syn) => {
277
276
  s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxSeq);
278
277
  for (const c of s.ctxPending) c.posted = false;
279
278
  }
280
- if (typeof syn.retry === "number") s.resumeAt = Date.now() + Math.max(0, syn.retry);
279
+ if (typeof syn.retry === "number") s.resumeAt = Date.now() + syn.retry;
281
280
  const firstCmd = s.pending.find((p) => !p.posted);
282
281
  const firstCtx = s.ctxPending.find((c) => !c.posted);
283
282
  if (typeof syn.seq === "number" && firstCmd !== void 0 && firstCmd.seq > Math.max(syn.seq, s.durableSeq) + 1 || typeof syn.ctxSeq === "number" && firstCtx !== void 0 && firstCtx.seq > syn.ctxSeq + 1) s.transport?.connection.reconnect();
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","names":["useEffect","useState","applyOps","StatewirePath","StatewireCmd","StatewireSyn","encodeParams","encodeValue","reviveResponse","bindCommandsHost","CommandsInvocation","CommandsListener","Statewire","StatewireClient","createMemorySessionStore","StatewireSessionRecord","StatewireSessionStore","StatewireSessionStoreOptions","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","onDone","Session","record","ctx","recordPersisted","store","ephemeral","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","setIdle","level","cover","entry","onApplied","onCovered","settleEntry","outcome","ok","p","onSettle","type","settleAll","detach","cause","unmount","gone","superseded","const","batch","detachFailure","predecessorLost","some","fate","restateContext","undefined","ctxNextSeq","resetRecord","clientId","survivors","nextSeq","old","enqueue","ephemeralDetach","rejectedFailure","cmd","code","handleCmd","dur","Math","max","find","String","handleCmds","cmds","ingestOps","state","changedPaths","publishIngested","RECORDS","snapClocks","seqWm","ctxWm","tail","cmdAligned","every","i","length","ctxAligned","c","handleHello","syn","includes","attachCmd","attachCtx","Set","has","ctxWatermark","ctxSeq","pump","handleOps","handleRefusal","watermark","retry","Date","now","firstCmd","firstCtx","clocksAhead","connection","reconnect","handleDetach","handleFinish","reason","isFinished","Lanes","frame","cmdEntries","ctxEntries","buildLanes","at","map","takeAttachLanes","wanted","lanes","status","resumeDelay","epoch","send","onPosted","start","stop","setTransport","ts","onStart","sendCommand","encoded","setContext","value","Array","isArray","op","path","useStatewireSession","options","defaultStore","sessionStore","stored","load","session","onHello","args","onOps","onCmds","onRefusal","onIdle","onDetach","onFinish","snapshot","takeChanged","setOnChange","listener","setListener"],"sources":["../../src/client/session.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { applyOps } from \"../wire/ops\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireCmd, StatewireSyn } from \"./connection\";\nimport { encodeParams, encodeValue, reviveResponse } 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 { createMemorySessionStore } from \"./sessionStore\";\nimport type {\n StatewireSessionRecord,\n StatewireSessionStore,\n StatewireSessionStoreOptions,\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 = StatewireSessionStoreOptions & {\n onDone?: (() => void) | undefined;\n};\n\ntype Session = {\n record: StatewireSessionRecord;\n ctx: StatewireRemoteProps;\n recordPersisted: boolean;\n store: StatewireSessionStore;\n ephemeral: boolean;\n sessionKnown: boolean;\n durableSeq: number;\n resumeAt: number;\n idle: boolean;\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: StatewireSessionRecord) => {\n s.record = record;\n if (!s.ephemeral) s.store.save(record);\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 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 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\" | \"superseded\") => {\n const cause = (\n {\n unmount: \"unmount\",\n gone: \"stream-gone\",\n superseded: \"superseded\",\n } as const\n )[detach];\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\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// from 1 on the reset lane clocks.\nconst resetRecord = (s: Session, clientId: string) => {\n const survivors: Pending[] = [];\n for (const entry of [...s.pending]) {\n if (entry.attempted || entry.applied) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, {\n ok: false,\n failure: { fate: \"lost\", cause: \"session-lost\" },\n });\n } else {\n survivors.push(entry);\n }\n }\n s.pending = [];\n s.durableSeq = 0;\n setRecord(s, { clientId, nextSeq: 1, ctxNextSeq: 1 });\n for (const old of survivors) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueue(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n restateContext(s);\n publish(s);\n wake(s);\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 const code =\n cmd.code === undefined ||\n cmd.code === \"unknown-command\" ||\n cmd.code === \"invalid-params\"\n ? cmd.code\n : protocolError(`unknown rejected code: ${cmd.code}`);\n return {\n fate: \"rejected\",\n cause: \"server\",\n ...(code !== undefined && { code }),\n ...(cmd.message !== undefined && { message: cmd.message }),\n ...(cmd.payload !== undefined && { payload: cmd.payload }),\n };\n};\n\nconst handleCmd = (s: Session, cmd: StatewireCmd) => {\n if (typeof cmd.seq !== \"number\") protocolError(\"cmd entry missing seq\");\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 if (!entry) return;\n cover(s, entry);\n const outcome =\n cmd.type === \"result\"\n ? { ok: true as const, payload: reviveResponse(cmd).payload }\n : cmd.type === \"rejected\"\n ? { ok: false as const, failure: rejectedFailure(reviveResponse(cmd)) }\n : cmd.type === \"failed\"\n ? {\n ok: false as const,\n failure: {\n fate: \"failed\" as const,\n cause: \"server\" as const,\n ...(cmd.message !== undefined && { message: cmd.message }),\n },\n }\n : cmd.type === \"crashed\"\n ? {\n ok: false as const,\n failure: { fate: \"crashed\" as const, cause: \"server\" as const },\n }\n : cmd.type === \"expired\"\n ? {\n ok: false as const,\n failure: {\n fate: \"expired\" as const,\n cause: \"server\" as const,\n },\n }\n : protocolError(`unknown cmd type: ${String(cmd.type)}`);\n settleEntry(s, entry, outcome);\n};\n\nconst handleCmds = (s: Session, cmds: StatewireCmd[]) => {\n for (const cmd of cmds) handleCmd(s, cmd);\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\nconst RECORDS = [\"fresh\", \"resumed\", \"ephemeral\"];\n\n// Snap a resumed session's lane clocks onto the record: seqs above the stated\n// watermark were never admitted, so a stale restored clock re-stamps its\n// never-admitted statements consecutively after the watermark.\nconst snapClocks = (s: Session, seqWm: number, ctxWm: number) => {\n const tail = s.pending.filter((p) => p.seq > seqWm);\n const cmdAligned =\n tail.every((p, i) => p.seq === seqWm + 1 + i) &&\n s.record.nextSeq === seqWm + tail.length + 1;\n if (!cmdAligned) {\n s.pending = s.pending.filter((p) => p.seq <= seqWm);\n setRecord(s, { ...s.record, nextSeq: seqWm + 1 });\n for (const old of tail) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueue(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n }\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\nconst handleHello = (\n s: Session,\n { ops, syn }: { ops: unknown[]; syn: StatewireSyn },\n) => {\n const record = syn.record ?? \"fresh\";\n if (!RECORDS.includes(record)) {\n protocolError(`unknown record: ${String(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 = record === \"ephemeral\";\n const [attachCmd, attachCtx] = s.attachLaneSeqs;\n s.attachLaneSeqs = [new Set(), new Set()];\n if (record === \"resumed\") {\n // Resending unsettled statements is exactly-once-safe: absorbed replays\n // re-emit their stored verdicts (applied while still in flight).\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 snapClocks(s, syn.seq ?? 0, ctxWatermark);\n } else {\n resetRecord(s, s.record.clientId);\n }\n s.sessionKnown = true;\n publishIngested(s);\n void pump(s);\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 publishIngested(s);\n};\n\n// A {syn} refusal never settles: reconcile the resend queues against the\n// stated watermarks; retry present means wait, absent means resend now.\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() + Math.max(0, syn.retry);\n }\n const firstCmd = s.pending.find((p) => !p.posted);\n const firstCtx = s.ctxPending.find((c) => !c.posted);\n const clocksAhead =\n (typeof syn.seq === \"number\" &&\n firstCmd !== undefined &&\n firstCmd.seq > Math.max(syn.seq, s.durableSeq) + 1) ||\n (typeof syn.ctxSeq === \"number\" &&\n firstCtx !== undefined &&\n firstCtx.seq > syn.ctxSeq + 1);\n // Clocks ahead of a record that cannot admit them: reattach first and let\n // the hello's record arbitrate.\n if (clocksAhead) s.transport?.connection.reconnect();\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, reason === \"superseded\" ? \"superseded\" : \"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 (transport?.connection.status === \"idle\") {\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 result = await transport.send(lanes.frame);\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.recordPersisted) {\n s.recordPersisted = true;\n s.store.save(s.record);\n }\n s.running = true;\n void pump(s);\n};\n\nconst stop = (s: Session) => {\n s.running = false;\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 enqueue = (\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 setRecord(s, { ...s.record, nextSeq: seq + 1 });\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 s.lifecycle?.onStart(entry.inv);\n void pump(s);\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 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 const { value: encoded, meta } = encodeValue(value);\n s.ctxOps = [\n {\n op: \"replace\",\n path: [],\n value: encoded,\n ...(meta !== undefined && { meta }),\n },\n ];\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 wake(s);\n void pump(s);\n};\n\nexport const useStatewireSession = (\n options: StatewireSessionOptions,\n): Session => {\n const [defaultStore] = useState(createMemorySessionStore);\n const store = options.sessionStore ?? defaultStore;\n const [s] = useState((): Session => {\n const stored = store.load();\n const record = stored ?? {\n clientId: newClientId(),\n nextSeq: 1,\n ctxNextSeq: 1,\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 ephemeral: false,\n sessionKnown: false,\n durableSeq: 0,\n resumeAt: 0,\n idle: false,\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 s.store = store;\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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"}
1
+ {"version":3,"file":"session.js","names":["useEffect","useState","applyOps","StatewirePath","StatewireCmd","StatewireSyn","encodeParams","encodeValue","reviveResponse","bindCommandsHost","CommandsInvocation","CommandsListener","Statewire","StatewireClient","createMemorySessionStore","StatewireSessionRecord","StatewireSessionStore","StatewireSessionStoreOptions","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","onDone","Session","record","ctx","recordPersisted","store","ephemeral","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","setIdle","level","cover","entry","onApplied","onCovered","settleEntry","outcome","ok","p","onSettle","type","settleAll","detach","cause","unmount","gone","superseded","const","batch","detachFailure","predecessorLost","some","fate","restateContext","undefined","ctxNextSeq","resetRecord","clientId","survivors","nextSeq","old","enqueue","ephemeralDetach","rejectedFailure","cmd","code","handleCmd","Number","isSafeInteger","dur","Math","max","find","String","handleCmds","cmds","ingestOps","state","changedPaths","publishIngested","RECORDS","snapClocks","seqWm","ctxWm","tail","cmdAligned","every","i","length","ctxAligned","c","handleHello","syn","includes","attachCmd","attachCtx","Set","has","ctxWatermark","ctxSeq","pump","handleOps","handleRefusal","watermark","retry","Date","now","firstCmd","firstCtx","clocksAhead","connection","reconnect","handleDetach","handleFinish","reason","isFinished","Lanes","frame","cmdEntries","ctxEntries","buildLanes","at","map","takeAttachLanes","wanted","lanes","status","resumeDelay","epoch","send","onPosted","start","stop","setTransport","ts","onStart","sendCommand","encoded","setContext","value","Array","isArray","op","path","useStatewireSession","options","defaultStore","sessionStore","stored","load","session","onHello","args","onOps","onCmds","onRefusal","onIdle","onDetach","onFinish","snapshot","takeChanged","setOnChange","listener","setListener"],"sources":["../../src/client/session.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { applyOps } from \"../wire/ops\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireCmd, StatewireSyn } from \"./connection\";\nimport { encodeParams, encodeValue, reviveResponse } 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 { createMemorySessionStore } from \"./sessionStore\";\nimport type {\n StatewireSessionRecord,\n StatewireSessionStore,\n StatewireSessionStoreOptions,\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 = StatewireSessionStoreOptions & {\n onDone?: (() => void) | undefined;\n};\n\ntype Session = {\n record: StatewireSessionRecord;\n ctx: StatewireRemoteProps;\n recordPersisted: boolean;\n store: StatewireSessionStore;\n ephemeral: boolean;\n sessionKnown: boolean;\n durableSeq: number;\n resumeAt: number;\n idle: boolean;\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: StatewireSessionRecord) => {\n s.record = record;\n if (!s.ephemeral) s.store.save(record);\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 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 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\" | \"superseded\") => {\n const cause = (\n {\n unmount: \"unmount\",\n gone: \"stream-gone\",\n superseded: \"superseded\",\n } as const\n )[detach];\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\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// from 1 on the reset lane clocks.\nconst resetRecord = (s: Session, clientId: string) => {\n const survivors: Pending[] = [];\n for (const entry of [...s.pending]) {\n if (entry.attempted || entry.applied) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, {\n ok: false,\n failure: { fate: \"lost\", cause: \"session-lost\" },\n });\n } else {\n survivors.push(entry);\n }\n }\n s.pending = [];\n s.durableSeq = 0;\n setRecord(s, { clientId, nextSeq: 1, ctxNextSeq: 1 });\n for (const old of survivors) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueue(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n restateContext(s);\n publish(s);\n wake(s);\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 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 if (!entry) return;\n cover(s, entry);\n const outcome =\n cmd.type === \"result\"\n ? { ok: true as const, payload: reviveResponse(cmd).payload }\n : cmd.type === \"rejected\"\n ? { ok: false as const, failure: rejectedFailure(reviveResponse(cmd)) }\n : cmd.type === \"failed\"\n ? {\n ok: false as const,\n failure: {\n fate: \"failed\" as const,\n cause: \"server\" as const,\n ...(cmd.message !== undefined && { message: cmd.message }),\n },\n }\n : cmd.type === \"crashed\"\n ? {\n ok: false as const,\n failure: { fate: \"crashed\" as const, cause: \"server\" as const },\n }\n : cmd.type === \"expired\"\n ? {\n ok: false as const,\n failure: {\n fate: \"expired\" as const,\n cause: \"server\" as const,\n },\n }\n : protocolError(`unknown cmd type: ${String(cmd.type)}`);\n settleEntry(s, entry, outcome);\n};\n\nconst handleCmds = (s: Session, cmds: StatewireCmd[]) => {\n for (const cmd of cmds) handleCmd(s, cmd);\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\nconst RECORDS = [\"fresh\", \"resumed\", \"ephemeral\"];\n\n// Snap a resumed session's lane clocks onto the record: seqs above the stated\n// watermark were never admitted, so a stale restored clock re-stamps its\n// never-admitted statements consecutively after the watermark.\nconst snapClocks = (s: Session, seqWm: number, ctxWm: number) => {\n const tail = s.pending.filter((p) => p.seq > seqWm);\n const cmdAligned =\n tail.every((p, i) => p.seq === seqWm + 1 + i) &&\n s.record.nextSeq === seqWm + tail.length + 1;\n if (!cmdAligned) {\n s.pending = s.pending.filter((p) => p.seq <= seqWm);\n setRecord(s, { ...s.record, nextSeq: seqWm + 1 });\n for (const old of tail) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueue(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n }\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\nconst handleHello = (\n s: Session,\n { ops, syn }: { ops: unknown[]; syn: StatewireSyn },\n) => {\n const record = syn.record ?? \"fresh\";\n if (!RECORDS.includes(record)) {\n protocolError(`unknown record: ${String(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 = record === \"ephemeral\";\n const [attachCmd, attachCtx] = s.attachLaneSeqs;\n s.attachLaneSeqs = [new Set(), new Set()];\n if (record === \"resumed\") {\n // Resending unsettled statements is exactly-once-safe: absorbed replays\n // re-emit their stored verdicts (applied while still in flight).\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 snapClocks(s, syn.seq ?? 0, ctxWatermark);\n } else {\n resetRecord(s, s.record.clientId);\n }\n s.sessionKnown = true;\n publishIngested(s);\n void pump(s);\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 publishIngested(s);\n};\n\n// A {syn} refusal never settles: reconcile the resend queues against the\n// stated watermarks; retry present means wait, absent means resend now.\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 }\n const firstCmd = s.pending.find((p) => !p.posted);\n const firstCtx = s.ctxPending.find((c) => !c.posted);\n const clocksAhead =\n (typeof syn.seq === \"number\" &&\n firstCmd !== undefined &&\n firstCmd.seq > Math.max(syn.seq, s.durableSeq) + 1) ||\n (typeof syn.ctxSeq === \"number\" &&\n firstCtx !== undefined &&\n firstCtx.seq > syn.ctxSeq + 1);\n // Clocks ahead of a record that cannot admit them: reattach first and let\n // the hello's record arbitrate.\n if (clocksAhead) s.transport?.connection.reconnect();\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, reason === \"superseded\" ? \"superseded\" : \"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 (transport?.connection.status === \"idle\") {\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 result = await transport.send(lanes.frame);\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.recordPersisted) {\n s.recordPersisted = true;\n s.store.save(s.record);\n }\n s.running = true;\n void pump(s);\n};\n\nconst stop = (s: Session) => {\n s.running = false;\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 enqueue = (\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 setRecord(s, { ...s.record, nextSeq: seq + 1 });\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 s.lifecycle?.onStart(entry.inv);\n void pump(s);\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 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 const { value: encoded, meta } = encodeValue(value);\n s.ctxOps = [\n {\n op: \"replace\",\n path: [],\n value: encoded,\n ...(meta !== undefined && { meta }),\n },\n ];\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 wake(s);\n void pump(s);\n};\n\nexport const useStatewireSession = (\n options: StatewireSessionOptions,\n): Session => {\n const [defaultStore] = useState(createMemorySessionStore);\n const store = options.sessionStore ?? defaultStore;\n const [s] = useState((): Session => {\n const stored = store.load();\n const record = stored ?? {\n clientId: newClientId(),\n nextSeq: 1,\n ctxNextSeq: 1,\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 ephemeral: false,\n sessionKnown: false,\n durableSeq: 0,\n resumeAt: 0,\n idle: false,\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 s.store = store;\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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"}
@@ -2,7 +2,9 @@
2
2
  declare const timing: {
3
3
  backoffBaseMs: number;
4
4
  backoffMaxMs: number;
5
+ backoffResetMs: number;
5
6
  heartbeatTimeoutMs: number;
7
+ random: () => number;
6
8
  };
7
9
  declare const backoff: (attempt: number) => number;
8
10
  //#endregion