statewire 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +18 -4
- package/dist/client/connection.js.map +1 -1
- package/dist/client/session.d.ts +3 -1
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +41 -16
- package/dist/client/session.js.map +1 -1
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.js +14 -11
- package/dist/host/host.js.map +1 -1
- package/dist/host/http.d.ts.map +1 -1
- package/dist/host/http.js +13 -8
- package/dist/host/http.js.map +1 -1
- package/dist/host/socket.d.ts +8 -2
- package/dist/host/socket.d.ts.map +1 -1
- package/dist/host/socket.js +83 -11
- package/dist/host/socket.js.map +1 -1
- package/dist/host-internal.d.ts +4 -1
- package/dist/host-internal.d.ts.map +1 -1
- package/dist/statewire.d.ts.map +1 -1
- package/dist/statewire.js +6 -5
- package/dist/statewire.js.map +1 -1
- package/dist/transports/sse.d.ts +1 -0
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js +7 -0
- package/dist/transports/sse.js.map +1 -1
- package/package.json +1 -1
- package/src/client/connection.ts +16 -4
- package/src/client/session.ts +54 -15
- package/src/host/host.ts +9 -3
- package/src/host/http.ts +37 -5
- package/src/host/socket.ts +111 -6
- package/src/host-internal.ts +4 -0
- package/src/statewire.ts +11 -6
- package/src/transports/sse.ts +12 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","names":[],"sources":["../../src/client/connection.ts"],"mappings":";;;;;KAqBY;EACV;EACA;EACA;;;cAIW;KAQD;EACV;EACA;EACA,2BAA2B;EAC3B;EACA;EACA;EACA;;EAEA;;KAGU;EACV;EACA;IACE;IACA;IACA;IACA;;EAEF;EACA;EACA;;KAGU;EACV;EACA,MAAM;EACN;EACA;EACA,MAAM;EACN,MAAM,cAAc;;KAGV;EAAS;EAAkB;;KAoC3B;KAEA;EACV,cAAc,kBAAkB;EAChC,YAAY,gBAAgB;EAC5B;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO,gBAAgB;EACvB,SAAS;EACT;EACA,MAAM;EACN,MAAM;EACN,OAAO;EACP,UAAU;EACV,KAAK;EACL,UAAU,OAAO,gBAAgB;EACjC,WAAW,YAAY,gBAAgB;EACvC,cAAc,OAAO,oBAAoB,QAAQ;EACjD,SAAS,YAAY,gBAAgB;EACrC;;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","names":[],"sources":["../../src/client/connection.ts"],"mappings":";;;;;KAqBY;EACV;EACA;EACA;;;cAIW;KAQD;EACV;EACA;EACA,2BAA2B;EAC3B;EACA;EACA;EACA;;EAEA;;KAGU;EACV;EACA;IACE;IACA;IACA;IACA;;EAEF;EACA;EACA;;KAGU;EACV;EACA,MAAM;EACN;EACA;EACA,MAAM;EACN,MAAM,cAAc;;KAGV;EAAS;EAAkB;;KAoC3B;KAEA;EACV,cAAc,kBAAkB;EAChC,YAAY,gBAAgB;EAC5B;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO,gBAAgB;EACvB,SAAS;EACT;EACA,MAAM;EACN,MAAM;EACN,OAAO;EACP,UAAU;EACV,KAAK;EACL,UAAU,OAAO,gBAAgB;EACjC,WAAW,YAAY,gBAAgB;EACvC,cAAc,OAAO,oBAAoB,QAAQ;EACjD,SAAS,YAAY,gBAAgB;EACrC;;cAoHW,qBAAsB,mBAAiB;cA0KvC,YAAa,GAAG,MAAM,KAAK,cAAc,QAAM;cAgE/C,iBACX,GAAG,MACH,mBACC;cA8IU,qBAAsB,GAAG,MAAM,oBAAkB;cAUjD,iBACX,SAAS,gBAAgB,2BACzB,uBACC,QAAQ;cAME,cACX,GAAG,MACH,SAAS,gBAAgB,8BAAyB;;;;cAwBvC,UACX,OAAO,kBAAkB;EACvB;EACA;EACA,aAAa,YAAY,gBAAgB;EACzC,YAAY,OAAO,gBAAgB;EACnC,KAAK;EACL,cAAc,GAAG,MAAM,OAAO,oBAAoB,QAAQ;EAC1D,OAAO,GAAG,MAAM,OAAO,mBAAmB,QAAQ;MAEnD;cA0FU,WAAY,SAAS,gBAAW"}
|
|
@@ -61,12 +61,12 @@ const setStatus = (c, next) => {
|
|
|
61
61
|
c.notify(c.connection);
|
|
62
62
|
c.onChange(c.connection);
|
|
63
63
|
};
|
|
64
|
-
const
|
|
64
|
+
const stopForError = ({ connection: c, error, reason }) => {
|
|
65
65
|
c.error = error;
|
|
66
66
|
c.onError(error);
|
|
67
67
|
flushTapSync(() => setStatus(c, {
|
|
68
68
|
status: "stopped",
|
|
69
|
-
reason
|
|
69
|
+
reason,
|
|
70
70
|
degraded: true,
|
|
71
71
|
message: error.message
|
|
72
72
|
}));
|
|
@@ -270,6 +270,7 @@ const handleEnvelope = (c, value) => {
|
|
|
270
270
|
return null;
|
|
271
271
|
}
|
|
272
272
|
deliverEnvelope(c, env);
|
|
273
|
+
if (c.connection.status === "stopped") return "stop";
|
|
273
274
|
if (env.fin !== void 0) return settleFin(c, env.fin);
|
|
274
275
|
if (c.connection.status !== "connected") {
|
|
275
276
|
c.attempt = 0;
|
|
@@ -344,7 +345,11 @@ const run = async (c, lifetime, gate) => {
|
|
|
344
345
|
} catch (error) {
|
|
345
346
|
if (!abort.signal.aborted) {
|
|
346
347
|
if (isStorageError(error)) {
|
|
347
|
-
|
|
348
|
+
stopForError({
|
|
349
|
+
connection: c,
|
|
350
|
+
error,
|
|
351
|
+
reason: "storage-error"
|
|
352
|
+
});
|
|
348
353
|
outcome = "stop";
|
|
349
354
|
} else if (error instanceof SyntaxError || error instanceof Error && /^(statewire: protocol error:|Statewire cannot apply)/.test(error.message)) outcome = flushTapSync(() => settleFin(c, {
|
|
350
355
|
reason: "protocol-error",
|
|
@@ -451,7 +456,16 @@ const useLink = (props) => {
|
|
|
451
456
|
return c.parked;
|
|
452
457
|
},
|
|
453
458
|
send: (frame) => latest.current.send(c, frame),
|
|
454
|
-
storageFailed: (error_0) =>
|
|
459
|
+
storageFailed: (error_0) => stopForError({
|
|
460
|
+
connection: c,
|
|
461
|
+
error: error_0,
|
|
462
|
+
reason: "storage-error"
|
|
463
|
+
}),
|
|
464
|
+
protocolFailed: (error_1) => stopForError({
|
|
465
|
+
connection: c,
|
|
466
|
+
error: error_1,
|
|
467
|
+
reason: "protocol-error"
|
|
468
|
+
})
|
|
455
469
|
}));
|
|
456
470
|
const negotiation = JSON.stringify([
|
|
457
471
|
props.protocol,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","names":["negotiationHeaders","validateSelection","parseNegotiation","StatewireProtocol","useEffect","useRef","useState","flushTapSync","reviveOps","reviveValue","backoff","retryHint","timing","isStorageError","ConnectionState","RemoteLink","StatewireFrame","StatewireRemoteProps","StatewireSubmitResult","StatewireClient","StatewireHost","Episode","cause","message","code","TERMINAL","const","StatewireCmd","protocol","seq","type","payload","meta","dur","StatewireSyn","version","protocols","name","record","id","idle","retry","StatewireEnvelope","ops","cmd","next","syn","fin","Fin","Gate","latched","wake","newGate","undefined","takeGate","g","was","waitGate","timeoutMs","Promise","resolve","timer","setTimeout","clearTimeout","openGate","AttemptOutcome","Conn","negotiation","Options","connection","Connection","parked","lease","attempt","authDenials","authStale","liveAt","retryAt","error","ConnectionError","episode","awaitingHello","held","gate","abort","AbortController","lifetime","ctx","onError","onChange","attemptOnce","notify","reconnect","sameState","a","b","status","nextRetryAt","lastError","reason","setStatus","c","storageFailed","Error","degraded","protocolError","isObject","value","Record","Array","isArray","isNonnegativeSafeInteger","Number","isSafeInteger","isPositiveSafeInteger","validateOptionalString","field","validateSynProtocols","hello","entry","validateSynScalars","validateRefusalSyn","validateCmd","validateFin","validateEnvelope","releaseHeld","length","onCmds","cmdsOf","env","snapshotOf","helloSynOf","isWakeHello","handleHello","onHello","onIdle","Date","now","warnedUnknownSynFact","warnUnknownSynFact","console","warn","deliverSyn","onRefusal","Object","keys","deliverEnvelope","onOps","cmds","push","settleFin","finish","denial","terminal","report","assign","onFinish","handleEnvelope","dialing","scheduleRetry","failure","immediate","backoffResetMs","delay","Math","max","reconnectConn","run","alive","outcome","pending","beforeAttach","signal","aborted","SyntaxError","test","onDetach","unsupportedVersion","resolveHeaders","headers","HeadersOption","staleAuth","Headers","attachFrame","resolved","entries","has","set","persistence","lanes","takeAttachLanes","body","JSON","stringify","fromEntries","useLink","props","url","isNew","send","frame","latest","current","setConnection","conn","link","wireVersion","applicationProtocols","classify","timeout","AbortSignal"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import {\n negotiationHeaders,\n validateSelection,\n parseNegotiation,\n} from \"../wire/protocol\";\nimport type { StatewireProtocol } from \"../wire/protocol\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveValue } from \"../wire/meta\";\nimport { backoff, retryHint, timing } from \"./timing\";\nimport { isStorageError } from \"./storageError\";\nimport type {\n ConnectionState,\n RemoteLink,\n StatewireFrame,\n StatewireRemoteProps,\n StatewireSubmitResult,\n} from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"reconnect\" | \"error\" | \"unauthorized\";\n message?: string;\n code?: string;\n};\n\n/** The terminal cmd verdict types; \"applied\" is the sole non-terminal type. */\nexport const TERMINAL = [\n \"result\",\n \"rejected\",\n \"failed\",\n \"crashed\",\n \"expired\",\n] as const;\n\nexport type StatewireCmd = {\n protocol: string;\n seq: number;\n type?: \"applied\" | (typeof TERMINAL)[number];\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n /** Cumulative: resending through this seq will never be needed. */\n dur?: boolean;\n};\n\nexport type StatewireSyn = {\n version?: string;\n protocols?: {\n name: string;\n version?: string;\n record?: \"ephemeral\";\n seq?: number;\n }[];\n id?: string;\n idle?: boolean;\n retry?: number;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n cmd?: StatewireCmd[];\n next?: true;\n idle?: boolean;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nexport type Gate = { latched: boolean; wake: (() => void) | undefined };\n\nconst newGate = (): Gate => ({ latched: false, wake: undefined });\n\nconst takeGate = (g: Gate) => {\n const was = g.latched;\n g.latched = false;\n return was;\n};\n\nconst waitGate = (g: Gate, timeoutMs?: number) => {\n if (g.latched) {\n g.latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n g.wake = undefined;\n resolve();\n }, timeoutMs);\n g.wake = () => {\n clearTimeout(timer);\n g.wake = undefined;\n resolve();\n };\n });\n};\n\nconst openGate = (g: Gate) => {\n if (g.wake) g.wake();\n else g.latched = true;\n};\n\nexport type AttemptOutcome = \"stop\" | \"reattach\" | \"ended\" | \"idle\";\n\nexport type Conn = {\n negotiation?: StatewireProtocol.Options;\n connection: StatewireClient.Connection;\n parked: boolean;\n lease: string | null;\n attempt: number;\n authDenials: number;\n authStale: boolean;\n liveAt: number | null;\n retryAt: number;\n error: StatewireClient.ConnectionError | undefined;\n episode: Episode | null;\n awaitingHello: boolean;\n held: StatewireCmd[];\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onError: (error: StatewireClient.ConnectionError) => void;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (abort: AbortController) => Promise<AttemptOutcome>;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nconst sameState = (a: ConnectionState, b: ConnectionState): boolean => {\n if (a.status !== b.status) return false;\n if (a.status === \"retrying\" && b.status === \"retrying\") {\n return (\n a.attempt === b.attempt &&\n a.cause === b.cause &&\n a.code === b.code &&\n a.nextRetryAt === b.nextRetryAt &&\n a.lastError === b.lastError &&\n a.message === b.message\n );\n }\n if (a.status === \"standby\" && b.status === \"standby\") {\n return a.reason === b.reason;\n }\n if (a.status === \"stopped\" && b.status === \"stopped\") {\n return (\n a.reason === b.reason &&\n a.message === b.message &&\n a.payload === b.payload\n );\n }\n return true;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n if (sameState(next, c.connection) && c.connection.error === c.error) return;\n c.connection = {\n ...next,\n ...(c.error === undefined ? {} : { error: c.error }),\n reconnect: c.reconnect,\n };\n c.notify(c.connection);\n c.onChange(c.connection);\n};\n\nconst storageFailed = (c: Conn, error: Error) => {\n c.error = error;\n c.onError(error);\n flushTapSync(() =>\n setStatus(c, {\n status: \"stopped\",\n reason: \"storage-error\",\n degraded: true,\n message: error.message,\n }),\n );\n c.abort?.abort();\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 validateSynProtocols = (value: unknown, hello: boolean): void => {\n if (value === undefined) return;\n if (!Array.isArray(value))\n return protocolError(\"syn.protocols must be an array\");\n for (const entry of value) {\n if (!isObject(entry))\n return protocolError(\"syn.protocols entry must be an object\");\n if (typeof entry[\"name\"] !== \"string\")\n protocolError(\"syn.protocols[].name must be a string\");\n if (\n !hello &&\n (entry[\"version\"] !== undefined || entry[\"record\"] !== undefined)\n )\n protocolError(\"invalid mid-stream syn\");\n if (\n hello\n ? !isNonnegativeSafeInteger(entry[\"seq\"])\n : entry[\"seq\"] !== undefined && !isNonnegativeSafeInteger(entry[\"seq\"])\n )\n protocolError(\"syn.protocols[].seq must be a nonnegative safe integer\");\n if (hello && entry[\"record\"] === \"ephemeral\" && entry[\"seq\"] !== 0)\n protocolError(\"ephemeral lane hello seq must be 0\");\n }\n};\n\nconst validateSynScalars = (syn: Record<string, unknown>, hello: boolean) => {\n validateSynProtocols(syn[\"protocols\"], hello);\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};\n\nexport const validateRefusalSyn = (value: unknown): StatewireSyn => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value, false);\n if (\n value[\"id\"] !== undefined ||\n value[\"idle\"] !== undefined ||\n value[\"version\"] !== undefined\n ) {\n protocolError(\"invalid refusal syn\");\n }\n if (value[\"protocols\"] === undefined && value[\"retry\"] === undefined) {\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 (typeof value[\"protocol\"] !== \"string\") {\n protocolError(\"cmd.protocol must be a string\");\n }\n if (!isPositiveSafeInteger(value[\"seq\"])) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n validateOptionalString(value[\"type\"], \"cmd.type\");\n validateOptionalString(value[\"code\"], \"cmd.code\");\n validateOptionalString(value[\"message\"], \"cmd.message\");\n if (value[\"dur\"] !== undefined && value[\"dur\"] !== true) {\n protocolError(\"cmd.dur must be true\");\n }\n return true;\n};\n\nconst validateFin = (value: unknown): value is StatewireHost.Fin => {\n if (!isObject(value)) return protocolError(\"fin must be an object\");\n if (typeof value[\"reason\"] !== \"string\") {\n protocolError(\"fin.reason must be a string\");\n }\n validateOptionalString(value[\"message\"], \"fin.message\");\n validateOptionalString(value[\"code\"], \"fin.code\");\n if (\n value[\"status\"] !== undefined &&\n !isNonnegativeSafeInteger(value[\"status\"])\n )\n protocolError(\"fin.status must be a nonnegative safe integer\");\n if (value[\"retry\"] !== undefined && !isNonnegativeSafeInteger(value[\"retry\"]))\n protocolError(\"fin.retry must be a nonnegative safe integer\");\n return true;\n};\n\nconst validateEnvelope = (value: unknown): StatewireEnvelope => {\n if (!isObject(value)) return protocolError(\"packet must be an object\");\n if (value[\"ops\"] !== undefined && !Array.isArray(value[\"ops\"])) {\n protocolError(\"ops must be an array\");\n }\n if (value[\"cmd\"] !== undefined) {\n const cmd = value[\"cmd\"];\n if (!Array.isArray(cmd)) return protocolError(\"cmd must be an array\");\n for (const entry of cmd) validateCmd(entry);\n }\n if (value[\"idle\"] !== undefined && typeof value[\"idle\"] !== \"boolean\") {\n protocolError(\"idle must be a boolean\");\n }\n if (value[\"next\"] !== undefined) {\n if (value[\"next\"] !== true) protocolError(\"next must be true\");\n if (\n value[\"cmd\"] === undefined ||\n value[\"ops\"] !== undefined ||\n value[\"fin\"] !== undefined\n ) {\n protocolError(\"next must ride a cmd-only packet\");\n }\n }\n if (value[\"fin\"] !== undefined) validateFin(value[\"fin\"]);\n return value as StatewireEnvelope;\n};\n\n// A hold's release delivers, never settles: fin and bare close both drain it.\nconst releaseHeld = (c: Conn) => {\n if (c.held.length === 0) return;\n const held = c.held;\n c.held = [];\n c.ctx.onCmds(held);\n};\n\nconst cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {\n if (env.cmd === undefined) return [];\n return env.cmd;\n};\n\nconst snapshotOf = (env: StatewireEnvelope): unknown[] => {\n const ops = env.ops;\n if (ops === undefined) return protocolError(\"hello missing snapshot\");\n return reviveOps(ops);\n};\n\nconst helloSynOf = (env: StatewireEnvelope): StatewireSyn => {\n if (!isObject(env.syn)) return protocolError(\"expected hello\");\n validateSynScalars(env.syn, true);\n if (env.syn[\"retry\"] !== undefined) {\n protocolError(\"hello syn cannot carry retry\");\n }\n return env.syn as StatewireSyn;\n};\n\n// A host that woke on a retained socket re-sends its hello; the snapshot\n// replaces the session the way a fresh attach would.\nconst isWakeHello = (env: StatewireEnvelope) =>\n isObject(env.syn) && env.syn[\"version\"] !== undefined;\n\nconst handleHello = (c: Conn, env: StatewireEnvelope) => {\n const syn = helloSynOf(env);\n if (c.negotiation !== undefined) validateSelection(syn, c.negotiation);\n const ops = snapshotOf(env);\n c.ctx.onHello({\n ops,\n syn,\n });\n if (env.cmd !== undefined) c.ctx.onCmds(env.cmd);\n c.ctx.onIdle(syn.idle ?? false);\n c.awaitingHello = false;\n c.error = undefined;\n c.liveAt = Date.now();\n c.authDenials = 0;\n c.episode = null;\n setStatus(c, { status: \"connected\", degraded: false });\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, false);\n if (value[\"version\"] !== undefined || value[\"idle\"] !== undefined) {\n protocolError(\"invalid mid-stream syn\");\n }\n if (value[\"protocols\"] !== undefined || value[\"retry\"] !== undefined) {\n c.ctx.onRefusal(validateRefusalSyn(value));\n return;\n }\n if (value[\"id\"] !== undefined) return;\n if (Object.keys(value).length === 0) {\n protocolError(\"invalid mid-stream syn\");\n }\n warnUnknownSynFact();\n};\n\nconst deliverEnvelope = (c: Conn, env: StatewireEnvelope) => {\n if (env.syn !== undefined) deliverSyn(c, env.syn);\n if (env.ops !== undefined) {\n const held = c.held;\n c.held = [];\n c.ctx.onOps({\n ops: reviveOps(env.ops),\n cmds: [...held, ...cmdsOf(env)],\n });\n } else if (env.cmd !== undefined) {\n const cmds = cmdsOf(env);\n if (env.next === true) c.held.push(...cmds);\n else c.ctx.onCmds(cmds);\n }\n if (typeof env.idle === \"boolean\") c.ctx.onIdle(env.idle);\n};\n\nexport const settleFin = (c: Conn, fin: StatewireHost.Fin): AttemptOutcome => {\n const finish =\n fin.meta === undefined\n ? fin\n : { ...fin, payload: reviveValue(fin.payload, fin.meta) };\n releaseHeld(c);\n c.retryAt = Date.now() + retryHint(finish.retry ?? 0);\n if (finish.reason === \"idle\") {\n c.ctx.onIdle(true);\n c.attempt = 0;\n c.episode = null;\n c.error = undefined;\n setStatus(c, { status: \"standby\", reason: \"idle\", degraded: false });\n return \"idle\";\n }\n const denial = finish.reason === \"unauthorized\";\n const terminal =\n finish.reason === \"gone\" ||\n finish.reason === \"forbidden\" ||\n finish.reason === \"protocol-error\" ||\n (denial && c.authDenials > 0);\n if (denial) {\n c.authDenials += 1;\n c.authStale = true;\n }\n const report =\n finish.reason !== \"reconnect\" &&\n finish.reason !== \"gone\" &&\n (!denial || terminal);\n c.error = report\n ? Object.assign(new Error(finish.message ?? finish.reason), { fin: finish })\n : undefined;\n if (c.error) c.onError(c.error);\n if (!terminal) {\n c.episode = {\n cause:\n finish.reason === \"reconnect\"\n ? \"reconnect\"\n : denial\n ? \"unauthorized\"\n : \"error\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.code !== undefined && { code: finish.code }),\n };\n if (denial) openGate(c.gate);\n return \"reattach\";\n }\n c.ctx.onFinish(finish);\n setStatus(c, {\n status: \"stopped\",\n degraded: true,\n reason: denial\n ? \"unauthorized\"\n : finish.reason === \"forbidden\"\n ? \"forbidden\"\n : finish.reason === \"protocol-error\"\n ? \"protocol-error\"\n : \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n};\n\nexport const handleEnvelope = (\n c: Conn,\n value: unknown,\n): AttemptOutcome | null => {\n const env = validateEnvelope(value);\n if (c.awaitingHello || isWakeHello(env)) {\n if (env.fin !== undefined) return settleFin(c, env.fin);\n handleHello(c, env);\n return null;\n }\n deliverEnvelope(c, env);\n if (env.fin !== undefined) return settleFin(c, env.fin);\n if (c.connection.status !== \"connected\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"connected\", degraded: false });\n }\n return null;\n};\n\n// A dial that no wait preceded is part of the current connect: only a\n// scheduled delay surfaces `retrying`, and the dial after it keeps that status.\nconst dialing = (c: Conn) =>\n setStatus(\n c,\n c.connection.status === \"retrying\"\n ? { status: \"retrying\", attempt: c.attempt, degraded: true }\n : { status: \"connecting\", degraded: false },\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 = Math.max(\n immediate ? 0 : backoff(c.attempt),\n c.retryAt - Date.now(),\n );\n if (delay === 0) return delay;\n setStatus(c, {\n status: \"retrying\",\n degraded: true,\n attempt: c.attempt,\n ...c.episode,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"standby\" || c.connection.status === \"stopped\") {\n // A reconnect out of a park starts a fresh episode: first dial, attempt 0.\n c.attempt = 0;\n c.authDenials = 0;\n c.episode = null;\n flushTapSync(() => dialing(c));\n }\n openGate(c.gate);\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n if (c.parked) {\n await waitGate(gate);\n if (!alive()) return;\n c.parked = false;\n }\n while (alive()) {\n if (c.retryAt > Date.now()) {\n await waitGate(gate, c.retryAt - Date.now());\n continue;\n }\n // The dial is in flight: attempt alone, no backoff fields.\n flushTapSync(() => dialing(c));\n const abort = new AbortController();\n c.abort = abort;\n c.awaitingHello = true;\n c.held = [];\n let outcome: AttemptOutcome | undefined;\n let failure: string | undefined;\n try {\n const pending = c.ctx.beforeAttach?.();\n if (pending) await pending;\n if (!alive()) return;\n outcome = await c.attemptOnce(abort);\n } catch (error) {\n if (!abort.signal.aborted) {\n if (isStorageError(error)) {\n storageFailed(c, error);\n outcome = \"stop\";\n } else if (\n error instanceof SyntaxError ||\n (error instanceof Error &&\n /^(statewire: protocol error:|Statewire cannot apply)/.test(\n error.message,\n ))\n ) {\n outcome = flushTapSync(() =>\n settleFin(c, { reason: \"protocol-error\", message: error.message }),\n );\n } else if (c.authStale) {\n outcome = flushTapSync(() =>\n settleFin(c, {\n reason: \"unauthorized\",\n message:\n error instanceof Error\n ? error.message\n : \"credential refresh failed\",\n }),\n );\n }\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n }\n }\n abort.abort();\n if (!alive()) return;\n flushTapSync(() => {\n releaseHeld(c);\n c.ctx.onDetach();\n });\n if (!alive()) return;\n if (c.connection.status === \"stopped\") outcome = \"stop\";\n if (outcome === \"stop\" || outcome === \"idle\") {\n await waitGate(gate);\n continue;\n }\n const immediate = takeGate(gate);\n const delay = flushTapSync(() => scheduleRetry(c, failure, immediate));\n if (delay === 0) continue;\n await waitGate(gate, delay);\n }\n};\n\nexport const unsupportedVersion = (c: Conn, version: string): AttemptOutcome =>\n flushTapSync(() =>\n handleEnvelope(c, {\n fin: {\n reason: \"protocol-error\",\n message: `unsupported protocol version: ${version || '\"\"'}`,\n },\n }),\n ) ?? \"stop\";\n\nexport const resolveHeaders = async (\n headers: StatewireClient.HeadersOption | undefined,\n staleAuth: boolean,\n): Promise<Headers> =>\n new Headers(\n typeof headers === \"function\" ? await headers({ staleAuth }) : headers,\n );\n\n// The stale flag clears only once the resolver returns: a throwing refresh keeps it for the next attempt.\nexport const attachFrame = async (\n c: Conn,\n headers: StatewireClient.HeadersOption | undefined,\n) => {\n const pending = c.ctx.beforeAttach?.();\n if (pending) await pending;\n const resolved = await resolveHeaders(headers, c.authStale);\n for (const [name, value] of Object.entries(\n negotiationHeaders(c.negotiation ?? {}),\n )) {\n if (!resolved.has(name)) resolved.set(name, value);\n }\n c.negotiation = parseNegotiation(resolved);\n c.authStale = false;\n const persistence = c.ctx.beforeAttach?.();\n if (persistence) await persistence;\n const lanes = flushTapSync(() => c.ctx.takeAttachLanes());\n return {\n headers: resolved,\n body: JSON.stringify({\n headers: Object.fromEntries(resolved),\n ...(lanes ?? {}),\n }),\n };\n};\n\nexport const useLink = (\n props: StatewireProtocol.Options & {\n url: string;\n isNew?: boolean | undefined;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n onError?: ((error: StatewireClient.ConnectionError) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;\n send: (c: Conn, frame: StatewireFrame) => Promise<StatewireSubmitResult>;\n },\n): RemoteLink => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n parked: props.isNew ?? false,\n lease: null,\n attempt: 0,\n authDenials: 0,\n authStale: false,\n liveAt: null,\n retryAt: 0,\n error: undefined,\n episode: null,\n awaitingHello: true,\n held: [],\n abort: null,\n gate: newGate(),\n lifetime: null,\n get ctx() {\n return latest.current.ctx;\n },\n onError: (error) => latest.current.onError?.(error),\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => {\n conn.negotiation = latest.current;\n return latest.current.attemptOnce(conn, abort);\n },\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: {\n ...((props.isNew ?? false)\n ? { status: \"standby\", reason: \"deferred\", degraded: false }\n : { status: \"connecting\", degraded: false }),\n reconnect: () => conn.reconnect(),\n },\n };\n return conn;\n });\n const [link] = useState(\n (): RemoteLink => ({\n get connection() {\n return c.connection;\n },\n get parked() {\n return c.parked;\n },\n send: (frame) => latest.current.send(c, frame),\n storageFailed: (error) => storageFailed(c, error),\n }),\n );\n\n const negotiation = JSON.stringify([\n props.protocol,\n props.wireVersion,\n props.applicationProtocols,\n ]);\n useEffect(() => {\n c.lease = null;\n c.attempt = 0;\n c.authDenials = 0;\n c.authStale = false;\n c.liveAt = null;\n c.retryAt = 0;\n c.episode = null;\n setStatus(\n c,\n c.parked\n ? { status: \"standby\", reason: \"deferred\", degraded: false }\n : { status: \"connecting\", degraded: false },\n );\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = newGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n openGate(c.gate);\n };\n }, [c, props.url, negotiation]);\n\n return link;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connection.js","names":["negotiationHeaders","validateSelection","parseNegotiation","StatewireProtocol","useEffect","useRef","useState","flushTapSync","reviveOps","reviveValue","backoff","retryHint","timing","isStorageError","ConnectionState","RemoteLink","StatewireFrame","StatewireRemoteProps","StatewireSubmitResult","StatewireClient","StatewireHost","Episode","cause","message","code","TERMINAL","const","StatewireCmd","protocol","seq","type","payload","meta","dur","StatewireSyn","version","protocols","name","record","id","idle","retry","StatewireEnvelope","ops","cmd","next","syn","fin","Fin","Gate","latched","wake","newGate","undefined","takeGate","g","was","waitGate","timeoutMs","Promise","resolve","timer","setTimeout","clearTimeout","openGate","AttemptOutcome","Conn","negotiation","Options","connection","Connection","parked","lease","attempt","authDenials","authStale","liveAt","retryAt","error","ConnectionError","episode","awaitingHello","held","gate","abort","AbortController","lifetime","ctx","onError","onChange","attemptOnce","notify","reconnect","sameState","a","b","status","nextRetryAt","lastError","reason","setStatus","c","stopForError","Error","degraded","protocolError","isObject","value","Record","Array","isArray","isNonnegativeSafeInteger","Number","isSafeInteger","isPositiveSafeInteger","validateOptionalString","field","validateSynProtocols","hello","entry","validateSynScalars","validateRefusalSyn","validateCmd","validateFin","validateEnvelope","releaseHeld","length","onCmds","cmdsOf","env","snapshotOf","helloSynOf","isWakeHello","handleHello","onHello","onIdle","Date","now","warnedUnknownSynFact","warnUnknownSynFact","console","warn","deliverSyn","onRefusal","Object","keys","deliverEnvelope","onOps","cmds","push","settleFin","finish","denial","terminal","report","assign","onFinish","handleEnvelope","dialing","scheduleRetry","failure","immediate","backoffResetMs","delay","Math","max","reconnectConn","run","alive","outcome","pending","beforeAttach","signal","aborted","SyntaxError","test","onDetach","unsupportedVersion","resolveHeaders","headers","HeadersOption","staleAuth","Headers","attachFrame","resolved","entries","has","set","persistence","lanes","takeAttachLanes","body","JSON","stringify","fromEntries","useLink","props","url","isNew","send","frame","latest","current","setConnection","conn","link","storageFailed","protocolFailed","wireVersion","applicationProtocols","classify","timeout","AbortSignal"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import {\n negotiationHeaders,\n validateSelection,\n parseNegotiation,\n} from \"../wire/protocol\";\nimport type { StatewireProtocol } from \"../wire/protocol\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveValue } from \"../wire/meta\";\nimport { backoff, retryHint, timing } from \"./timing\";\nimport { isStorageError } from \"./storageError\";\nimport type {\n ConnectionState,\n RemoteLink,\n StatewireFrame,\n StatewireRemoteProps,\n StatewireSubmitResult,\n} from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"reconnect\" | \"error\" | \"unauthorized\";\n message?: string;\n code?: string;\n};\n\n/** The terminal cmd verdict types; \"applied\" is the sole non-terminal type. */\nexport const TERMINAL = [\n \"result\",\n \"rejected\",\n \"failed\",\n \"crashed\",\n \"expired\",\n] as const;\n\nexport type StatewireCmd = {\n protocol: string;\n seq: number;\n type?: \"applied\" | (typeof TERMINAL)[number];\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n /** Cumulative: resending through this seq will never be needed. */\n dur?: boolean;\n};\n\nexport type StatewireSyn = {\n version?: string;\n protocols?: {\n name: string;\n version?: string;\n record?: \"ephemeral\";\n seq?: number;\n }[];\n id?: string;\n idle?: boolean;\n retry?: number;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n cmd?: StatewireCmd[];\n next?: true;\n idle?: boolean;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nexport type Gate = { latched: boolean; wake: (() => void) | undefined };\n\nconst newGate = (): Gate => ({ latched: false, wake: undefined });\n\nconst takeGate = (g: Gate) => {\n const was = g.latched;\n g.latched = false;\n return was;\n};\n\nconst waitGate = (g: Gate, timeoutMs?: number) => {\n if (g.latched) {\n g.latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n g.wake = undefined;\n resolve();\n }, timeoutMs);\n g.wake = () => {\n clearTimeout(timer);\n g.wake = undefined;\n resolve();\n };\n });\n};\n\nconst openGate = (g: Gate) => {\n if (g.wake) g.wake();\n else g.latched = true;\n};\n\nexport type AttemptOutcome = \"stop\" | \"reattach\" | \"ended\" | \"idle\";\n\nexport type Conn = {\n negotiation?: StatewireProtocol.Options;\n connection: StatewireClient.Connection;\n parked: boolean;\n lease: string | null;\n attempt: number;\n authDenials: number;\n authStale: boolean;\n liveAt: number | null;\n retryAt: number;\n error: StatewireClient.ConnectionError | undefined;\n episode: Episode | null;\n awaitingHello: boolean;\n held: StatewireCmd[];\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onError: (error: StatewireClient.ConnectionError) => void;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (abort: AbortController) => Promise<AttemptOutcome>;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nconst sameState = (a: ConnectionState, b: ConnectionState): boolean => {\n if (a.status !== b.status) return false;\n if (a.status === \"retrying\" && b.status === \"retrying\") {\n return (\n a.attempt === b.attempt &&\n a.cause === b.cause &&\n a.code === b.code &&\n a.nextRetryAt === b.nextRetryAt &&\n a.lastError === b.lastError &&\n a.message === b.message\n );\n }\n if (a.status === \"standby\" && b.status === \"standby\") {\n return a.reason === b.reason;\n }\n if (a.status === \"stopped\" && b.status === \"stopped\") {\n return (\n a.reason === b.reason &&\n a.message === b.message &&\n a.payload === b.payload\n );\n }\n return true;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n if (sameState(next, c.connection) && c.connection.error === c.error) return;\n c.connection = {\n ...next,\n ...(c.error === undefined ? {} : { error: c.error }),\n reconnect: c.reconnect,\n };\n c.notify(c.connection);\n c.onChange(c.connection);\n};\n\nconst stopForError = ({\n connection: c,\n error,\n reason,\n}: {\n connection: Conn;\n error: Error;\n reason: \"storage-error\" | \"protocol-error\";\n}) => {\n c.error = error;\n c.onError(error);\n flushTapSync(() =>\n setStatus(c, {\n status: \"stopped\",\n reason,\n degraded: true,\n message: error.message,\n }),\n );\n c.abort?.abort();\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 validateSynProtocols = (value: unknown, hello: boolean): void => {\n if (value === undefined) return;\n if (!Array.isArray(value))\n return protocolError(\"syn.protocols must be an array\");\n for (const entry of value) {\n if (!isObject(entry))\n return protocolError(\"syn.protocols entry must be an object\");\n if (typeof entry[\"name\"] !== \"string\")\n protocolError(\"syn.protocols[].name must be a string\");\n if (\n !hello &&\n (entry[\"version\"] !== undefined || entry[\"record\"] !== undefined)\n )\n protocolError(\"invalid mid-stream syn\");\n if (\n hello\n ? !isNonnegativeSafeInteger(entry[\"seq\"])\n : entry[\"seq\"] !== undefined && !isNonnegativeSafeInteger(entry[\"seq\"])\n )\n protocolError(\"syn.protocols[].seq must be a nonnegative safe integer\");\n if (hello && entry[\"record\"] === \"ephemeral\" && entry[\"seq\"] !== 0)\n protocolError(\"ephemeral lane hello seq must be 0\");\n }\n};\n\nconst validateSynScalars = (syn: Record<string, unknown>, hello: boolean) => {\n validateSynProtocols(syn[\"protocols\"], hello);\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};\n\nexport const validateRefusalSyn = (value: unknown): StatewireSyn => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value, false);\n if (\n value[\"id\"] !== undefined ||\n value[\"idle\"] !== undefined ||\n value[\"version\"] !== undefined\n ) {\n protocolError(\"invalid refusal syn\");\n }\n if (value[\"protocols\"] === undefined && value[\"retry\"] === undefined) {\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 (typeof value[\"protocol\"] !== \"string\") {\n protocolError(\"cmd.protocol must be a string\");\n }\n if (!isPositiveSafeInteger(value[\"seq\"])) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n validateOptionalString(value[\"type\"], \"cmd.type\");\n validateOptionalString(value[\"code\"], \"cmd.code\");\n validateOptionalString(value[\"message\"], \"cmd.message\");\n if (value[\"dur\"] !== undefined && value[\"dur\"] !== true) {\n protocolError(\"cmd.dur must be true\");\n }\n return true;\n};\n\nconst validateFin = (value: unknown): value is StatewireHost.Fin => {\n if (!isObject(value)) return protocolError(\"fin must be an object\");\n if (typeof value[\"reason\"] !== \"string\") {\n protocolError(\"fin.reason must be a string\");\n }\n validateOptionalString(value[\"message\"], \"fin.message\");\n validateOptionalString(value[\"code\"], \"fin.code\");\n if (\n value[\"status\"] !== undefined &&\n !isNonnegativeSafeInteger(value[\"status\"])\n )\n protocolError(\"fin.status must be a nonnegative safe integer\");\n if (value[\"retry\"] !== undefined && !isNonnegativeSafeInteger(value[\"retry\"]))\n protocolError(\"fin.retry must be a nonnegative safe integer\");\n return true;\n};\n\nconst validateEnvelope = (value: unknown): StatewireEnvelope => {\n if (!isObject(value)) return protocolError(\"packet must be an object\");\n if (value[\"ops\"] !== undefined && !Array.isArray(value[\"ops\"])) {\n protocolError(\"ops must be an array\");\n }\n if (value[\"cmd\"] !== undefined) {\n const cmd = value[\"cmd\"];\n if (!Array.isArray(cmd)) return protocolError(\"cmd must be an array\");\n for (const entry of cmd) validateCmd(entry);\n }\n if (value[\"idle\"] !== undefined && typeof value[\"idle\"] !== \"boolean\") {\n protocolError(\"idle must be a boolean\");\n }\n if (value[\"next\"] !== undefined) {\n if (value[\"next\"] !== true) protocolError(\"next must be true\");\n if (\n value[\"cmd\"] === undefined ||\n value[\"ops\"] !== undefined ||\n value[\"fin\"] !== undefined\n ) {\n protocolError(\"next must ride a cmd-only packet\");\n }\n }\n if (value[\"fin\"] !== undefined) validateFin(value[\"fin\"]);\n return value as StatewireEnvelope;\n};\n\n// A hold's release delivers, never settles: fin and bare close both drain it.\nconst releaseHeld = (c: Conn) => {\n if (c.held.length === 0) return;\n const held = c.held;\n c.held = [];\n c.ctx.onCmds(held);\n};\n\nconst cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {\n if (env.cmd === undefined) return [];\n return env.cmd;\n};\n\nconst snapshotOf = (env: StatewireEnvelope): unknown[] => {\n const ops = env.ops;\n if (ops === undefined) return protocolError(\"hello missing snapshot\");\n return reviveOps(ops);\n};\n\nconst helloSynOf = (env: StatewireEnvelope): StatewireSyn => {\n if (!isObject(env.syn)) return protocolError(\"expected hello\");\n validateSynScalars(env.syn, true);\n if (env.syn[\"retry\"] !== undefined) {\n protocolError(\"hello syn cannot carry retry\");\n }\n return env.syn as StatewireSyn;\n};\n\n// A host that woke on a retained socket re-sends its hello; the snapshot\n// replaces the session the way a fresh attach would.\nconst isWakeHello = (env: StatewireEnvelope) =>\n isObject(env.syn) && env.syn[\"version\"] !== undefined;\n\nconst handleHello = (c: Conn, env: StatewireEnvelope) => {\n const syn = helloSynOf(env);\n if (c.negotiation !== undefined) validateSelection(syn, c.negotiation);\n const ops = snapshotOf(env);\n c.ctx.onHello({\n ops,\n syn,\n });\n if (env.cmd !== undefined) c.ctx.onCmds(env.cmd);\n c.ctx.onIdle(syn.idle ?? false);\n c.awaitingHello = false;\n c.error = undefined;\n c.liveAt = Date.now();\n c.authDenials = 0;\n c.episode = null;\n setStatus(c, { status: \"connected\", degraded: false });\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, false);\n if (value[\"version\"] !== undefined || value[\"idle\"] !== undefined) {\n protocolError(\"invalid mid-stream syn\");\n }\n if (value[\"protocols\"] !== undefined || value[\"retry\"] !== undefined) {\n c.ctx.onRefusal(validateRefusalSyn(value));\n return;\n }\n if (value[\"id\"] !== undefined) return;\n if (Object.keys(value).length === 0) {\n protocolError(\"invalid mid-stream syn\");\n }\n warnUnknownSynFact();\n};\n\nconst deliverEnvelope = (c: Conn, env: StatewireEnvelope) => {\n if (env.syn !== undefined) deliverSyn(c, env.syn);\n if (env.ops !== undefined) {\n const held = c.held;\n c.held = [];\n c.ctx.onOps({\n ops: reviveOps(env.ops),\n cmds: [...held, ...cmdsOf(env)],\n });\n } else if (env.cmd !== undefined) {\n const cmds = cmdsOf(env);\n if (env.next === true) c.held.push(...cmds);\n else c.ctx.onCmds(cmds);\n }\n if (typeof env.idle === \"boolean\") c.ctx.onIdle(env.idle);\n};\n\nexport const settleFin = (c: Conn, fin: StatewireHost.Fin): AttemptOutcome => {\n const finish =\n fin.meta === undefined\n ? fin\n : { ...fin, payload: reviveValue(fin.payload, fin.meta) };\n releaseHeld(c);\n c.retryAt = Date.now() + retryHint(finish.retry ?? 0);\n if (finish.reason === \"idle\") {\n c.ctx.onIdle(true);\n c.attempt = 0;\n c.episode = null;\n c.error = undefined;\n setStatus(c, { status: \"standby\", reason: \"idle\", degraded: false });\n return \"idle\";\n }\n const denial = finish.reason === \"unauthorized\";\n const terminal =\n finish.reason === \"gone\" ||\n finish.reason === \"forbidden\" ||\n finish.reason === \"protocol-error\" ||\n (denial && c.authDenials > 0);\n if (denial) {\n c.authDenials += 1;\n c.authStale = true;\n }\n const report =\n finish.reason !== \"reconnect\" &&\n finish.reason !== \"gone\" &&\n (!denial || terminal);\n c.error = report\n ? Object.assign(new Error(finish.message ?? finish.reason), { fin: finish })\n : undefined;\n if (c.error) c.onError(c.error);\n if (!terminal) {\n c.episode = {\n cause:\n finish.reason === \"reconnect\"\n ? \"reconnect\"\n : denial\n ? \"unauthorized\"\n : \"error\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.code !== undefined && { code: finish.code }),\n };\n if (denial) openGate(c.gate);\n return \"reattach\";\n }\n c.ctx.onFinish(finish);\n setStatus(c, {\n status: \"stopped\",\n degraded: true,\n reason: denial\n ? \"unauthorized\"\n : finish.reason === \"forbidden\"\n ? \"forbidden\"\n : finish.reason === \"protocol-error\"\n ? \"protocol-error\"\n : \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n};\n\nexport const handleEnvelope = (\n c: Conn,\n value: unknown,\n): AttemptOutcome | null => {\n const env = validateEnvelope(value);\n if (c.awaitingHello || isWakeHello(env)) {\n if (env.fin !== undefined) return settleFin(c, env.fin);\n handleHello(c, env);\n return null;\n }\n deliverEnvelope(c, env);\n if (c.connection.status === \"stopped\") return \"stop\";\n if (env.fin !== undefined) return settleFin(c, env.fin);\n if (c.connection.status !== \"connected\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"connected\", degraded: false });\n }\n return null;\n};\n\n// A dial that no wait preceded is part of the current connect: only a\n// scheduled delay surfaces `retrying`, and the dial after it keeps that status.\nconst dialing = (c: Conn) =>\n setStatus(\n c,\n c.connection.status === \"retrying\"\n ? { status: \"retrying\", attempt: c.attempt, degraded: true }\n : { status: \"connecting\", degraded: false },\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 = Math.max(\n immediate ? 0 : backoff(c.attempt),\n c.retryAt - Date.now(),\n );\n if (delay === 0) return delay;\n setStatus(c, {\n status: \"retrying\",\n degraded: true,\n attempt: c.attempt,\n ...c.episode,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"standby\" || c.connection.status === \"stopped\") {\n // A reconnect out of a park starts a fresh episode: first dial, attempt 0.\n c.attempt = 0;\n c.authDenials = 0;\n c.episode = null;\n flushTapSync(() => dialing(c));\n }\n openGate(c.gate);\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n if (c.parked) {\n await waitGate(gate);\n if (!alive()) return;\n c.parked = false;\n }\n while (alive()) {\n if (c.retryAt > Date.now()) {\n await waitGate(gate, c.retryAt - Date.now());\n continue;\n }\n // The dial is in flight: attempt alone, no backoff fields.\n flushTapSync(() => dialing(c));\n const abort = new AbortController();\n c.abort = abort;\n c.awaitingHello = true;\n c.held = [];\n let outcome: AttemptOutcome | undefined;\n let failure: string | undefined;\n try {\n const pending = c.ctx.beforeAttach?.();\n if (pending) await pending;\n if (!alive()) return;\n outcome = await c.attemptOnce(abort);\n } catch (error) {\n if (!abort.signal.aborted) {\n if (isStorageError(error)) {\n stopForError({ connection: c, error, reason: \"storage-error\" });\n outcome = \"stop\";\n } else if (\n error instanceof SyntaxError ||\n (error instanceof Error &&\n /^(statewire: protocol error:|Statewire cannot apply)/.test(\n error.message,\n ))\n ) {\n outcome = flushTapSync(() =>\n settleFin(c, { reason: \"protocol-error\", message: error.message }),\n );\n } else if (c.authStale) {\n outcome = flushTapSync(() =>\n settleFin(c, {\n reason: \"unauthorized\",\n message:\n error instanceof Error\n ? error.message\n : \"credential refresh failed\",\n }),\n );\n }\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n }\n }\n abort.abort();\n if (!alive()) return;\n flushTapSync(() => {\n releaseHeld(c);\n c.ctx.onDetach();\n });\n if (!alive()) return;\n if (c.connection.status === \"stopped\") outcome = \"stop\";\n if (outcome === \"stop\" || outcome === \"idle\") {\n await waitGate(gate);\n continue;\n }\n const immediate = takeGate(gate);\n const delay = flushTapSync(() => scheduleRetry(c, failure, immediate));\n if (delay === 0) continue;\n await waitGate(gate, delay);\n }\n};\n\nexport const unsupportedVersion = (c: Conn, version: string): AttemptOutcome =>\n flushTapSync(() =>\n handleEnvelope(c, {\n fin: {\n reason: \"protocol-error\",\n message: `unsupported protocol version: ${version || '\"\"'}`,\n },\n }),\n ) ?? \"stop\";\n\nexport const resolveHeaders = async (\n headers: StatewireClient.HeadersOption | undefined,\n staleAuth: boolean,\n): Promise<Headers> =>\n new Headers(\n typeof headers === \"function\" ? await headers({ staleAuth }) : headers,\n );\n\n// The stale flag clears only once the resolver returns: a throwing refresh keeps it for the next attempt.\nexport const attachFrame = async (\n c: Conn,\n headers: StatewireClient.HeadersOption | undefined,\n) => {\n const pending = c.ctx.beforeAttach?.();\n if (pending) await pending;\n const resolved = await resolveHeaders(headers, c.authStale);\n for (const [name, value] of Object.entries(\n negotiationHeaders(c.negotiation ?? {}),\n )) {\n if (!resolved.has(name)) resolved.set(name, value);\n }\n c.negotiation = parseNegotiation(resolved);\n c.authStale = false;\n const persistence = c.ctx.beforeAttach?.();\n if (persistence) await persistence;\n const lanes = flushTapSync(() => c.ctx.takeAttachLanes());\n return {\n headers: resolved,\n body: JSON.stringify({\n headers: Object.fromEntries(resolved),\n ...(lanes ?? {}),\n }),\n };\n};\n\nexport const useLink = (\n props: StatewireProtocol.Options & {\n url: string;\n isNew?: boolean | undefined;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n onError?: ((error: StatewireClient.ConnectionError) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;\n send: (c: Conn, frame: StatewireFrame) => Promise<StatewireSubmitResult>;\n },\n): RemoteLink => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n parked: props.isNew ?? false,\n lease: null,\n attempt: 0,\n authDenials: 0,\n authStale: false,\n liveAt: null,\n retryAt: 0,\n error: undefined,\n episode: null,\n awaitingHello: true,\n held: [],\n abort: null,\n gate: newGate(),\n lifetime: null,\n get ctx() {\n return latest.current.ctx;\n },\n onError: (error) => latest.current.onError?.(error),\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => {\n conn.negotiation = latest.current;\n return latest.current.attemptOnce(conn, abort);\n },\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: {\n ...((props.isNew ?? false)\n ? { status: \"standby\", reason: \"deferred\", degraded: false }\n : { status: \"connecting\", degraded: false }),\n reconnect: () => conn.reconnect(),\n },\n };\n return conn;\n });\n const [link] = useState(\n (): RemoteLink => ({\n get connection() {\n return c.connection;\n },\n get parked() {\n return c.parked;\n },\n send: (frame) => latest.current.send(c, frame),\n storageFailed: (error) =>\n stopForError({ connection: c, error, reason: \"storage-error\" }),\n protocolFailed: (error) =>\n stopForError({ connection: c, error, reason: \"protocol-error\" }),\n }),\n );\n\n const negotiation = JSON.stringify([\n props.protocol,\n props.wireVersion,\n props.applicationProtocols,\n ]);\n useEffect(() => {\n c.lease = null;\n c.attempt = 0;\n c.authDenials = 0;\n c.authStale = false;\n c.liveAt = null;\n c.retryAt = 0;\n c.episode = null;\n setStatus(\n c,\n c.parked\n ? { status: \"standby\", reason: \"deferred\", degraded: false }\n : { status: \"connecting\", degraded: false },\n );\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = newGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n openGate(c.gate);\n };\n }, [c, props.url, negotiation]);\n\n return link;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n"],"mappings":"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"}
|
package/dist/client/session.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ type StatewireSessionOptions = StatewireProtocol.Options & {
|
|
|
36
36
|
};
|
|
37
37
|
type Shared = {
|
|
38
38
|
txq: Promise<void>;
|
|
39
|
+
syncQueued: boolean;
|
|
39
40
|
parked: {
|
|
40
41
|
protocol: string;
|
|
41
42
|
verdict: StatewireClient.SessionVerdict;
|
|
@@ -94,6 +95,7 @@ type Session = {
|
|
|
94
95
|
commands: Record<string, (...params: unknown[]) => Promise<unknown>>;
|
|
95
96
|
};
|
|
96
97
|
declare const failedCommands: (s: Session) => readonly StatewireClient.FailedCommand[];
|
|
98
|
+
declare const MAX_FAILED_RETAINED = 256;
|
|
97
99
|
declare const setTransport: (s: Session, transport: RemoteLink) => void;
|
|
98
100
|
declare const discardFailed: (s: Session, entry: StatewireClient.FailedCommand) => void;
|
|
99
101
|
declare const retryFailed: (s: Session, entry: StatewireClient.FailedCommand) => Promise<unknown>;
|
|
@@ -102,5 +104,5 @@ declare const invokeProtocol: (s: Session, protocol: string, method: string, par
|
|
|
102
104
|
declare const setContext: (s: Session, protocol: string, value: Statewire.Context) => void;
|
|
103
105
|
declare const useStatewireSession: (options: StatewireSessionOptions) => Session;
|
|
104
106
|
//#endregion
|
|
105
|
-
export { StatewireSessionOptions, discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setContext, setTransport, useStatewireSession };
|
|
107
|
+
export { MAX_FAILED_RETAINED, StatewireSessionOptions, discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setContext, setTransport, useStatewireSession };
|
|
106
108
|
//# sourceMappingURL=session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":";;;;;;;;;KA0CK;EACH;EACA,WAAW,YAAY,gBAAgB;EACvC;EACA;EACA;;KAGG;WACM;WACA,SAAS;WACT,KAAK;;EAEd;;EAEA;;EAEA;EACA,UAAU;EACV,SAAS;;KAeN;KAEO,0BAA0B,kBAAkB;EACtD,UAAU,SAAS,eAAe,UAAU;EAC5C,eAAe,gBAAgB;EAC/B,gBAAgB,gBAAgB;EAChC;;KAGG;EACH,KAAK;EACL;IAAU;IAAkB,SAAS,gBAAgB;;EACrD;;KAGG;EACH,SAAS;EACT,mBAAmB;EACnB,UAAU,YAAY,kBAAkB;EACxC,eAAe;EACf,gBAAgB,YAAY,kBAAkB;EAC9C,WAAW,kBAAkB;EAC7B,QAAQ,gBAAgB;EACxB,KAAK;EACL;EACA;EACA,OAAO;EACP;EACA,iBAAiB,gBAAgB;EACjC,OAAO,gBAAgB;EACvB,eAAe,mBAAmB;EAClC,QAAQ;;EAER;;EAEA;EACA;EACA,YAAY;;EAEZ,eAAe;EACf;EACA;EACA,eAAe,gBAAgB;EAC/B;EACA;EACA,eAAe,YAAY;EAC3B;EACA,SAAS;EACT,qBAAqB,gBAAgB;EACrC,gCAAgC,gBAAgB;EAChD;EACA,mBAAmB;EACnB,WAAW,mBAAmB;EAC9B;EACA,SAAS;EACT,QAAQ,UAAU;EAClB,QAAQ;EACR;EACA;EACA;EACA,WAAW;EACX;EACA,WAAW;EACX;EACA,UAAU,mBAAmB,sBAAsB;;
|
|
1
|
+
{"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":";;;;;;;;;KA0CK;EACH;EACA,WAAW,YAAY,gBAAgB;EACvC;EACA;EACA;;KAGG;WACM;WACA,SAAS;WACT,KAAK;;EAEd;;EAEA;;EAEA;EACA,UAAU;EACV,SAAS;;KAeN;KAEO,0BAA0B,kBAAkB;EACtD,UAAU,SAAS,eAAe,UAAU;EAC5C,eAAe,gBAAgB;EAC/B,gBAAgB,gBAAgB;EAChC;;KAGG;EACH,KAAK;EACL;EACA;IAAU;IAAkB,SAAS,gBAAgB;;EACrD;;KAGG;EACH,SAAS;EACT,mBAAmB;EACnB,UAAU,YAAY,kBAAkB;EACxC,eAAe;EACf,gBAAgB,YAAY,kBAAkB;EAC9C,WAAW,kBAAkB;EAC7B,QAAQ,gBAAgB;EACxB,KAAK;EACL;EACA;EACA,OAAO;EACP;EACA,iBAAiB,gBAAgB;EACjC,OAAO,gBAAgB;EACvB,eAAe,mBAAmB;EAClC,QAAQ;;EAER;;EAEA;EACA;EACA,YAAY;;EAEZ,eAAe;EACf;EACA;EACA,eAAe,gBAAgB;EAC/B;EACA;EACA,eAAe,YAAY;EAC3B;EACA,SAAS;EACT,qBAAqB,gBAAgB;EACrC,gCAAgC,gBAAgB;EAChD;EACA,mBAAmB;EACnB,WAAW,mBAAmB;EAC9B;EACA,SAAS;EACT,QAAQ,UAAU;EAClB,QAAQ;EACR;EACA;EACA;EACA,WAAW;EACX;EACA,WAAW;EACX;EACA,UAAU,mBAAmB,sBAAsB;;cAmNxC,iBACX,GAAG,qBACO,gBAAgB;cAcf;cAoxBP,eAAgB,GAAG,SAAS,WAAW;cAoNhC,gBACX,GAAG,SACH,OAAO,gBAAgB;cAYZ,cACX,GAAG,SACH,OAAO,gBAAgB,kBACtB;cA4DU,iBAAkB,GAAG,YAAU,mBAAmB;cA+BlD,iBACX,GAAG,SACH,kBACA,gBACA,+BAA0B;cAuEf,aACX,GAAG,SACH,kBACA,OAAO,UAAU;cAcN,sBACX,SAAS,4BACR"}
|
package/dist/client/session.js
CHANGED
|
@@ -66,13 +66,13 @@ const storageFailed = (s, cause) => {
|
|
|
66
66
|
s.transport?.storageFailed(error);
|
|
67
67
|
};
|
|
68
68
|
const setRecord = (s, record) => {
|
|
69
|
-
s.record = record;
|
|
70
69
|
if (!s.deactivated) try {
|
|
71
70
|
s.store.save(record);
|
|
72
71
|
} catch (cause) {
|
|
73
72
|
storageFailed(s, cause);
|
|
74
73
|
throw s.storageError;
|
|
75
74
|
}
|
|
75
|
+
s.record = record;
|
|
76
76
|
};
|
|
77
77
|
const toStored = (p) => {
|
|
78
78
|
const { protocol: _protocol, ...command } = p.command;
|
|
@@ -114,8 +114,16 @@ const syncBacklogInner = (s) => {
|
|
|
114
114
|
});
|
|
115
115
|
};
|
|
116
116
|
const syncBacklog = (s) => {
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
const shared = s.shared;
|
|
118
|
+
if (!shared) return syncBacklogInner(s);
|
|
119
|
+
if (shared.syncQueued) return;
|
|
120
|
+
shared.syncQueued = true;
|
|
121
|
+
transact(s, () => {
|
|
122
|
+
shared.syncQueued = false;
|
|
123
|
+
syncBacklogInner(s);
|
|
124
|
+
}).catch(() => {
|
|
125
|
+
shared.syncQueued = false;
|
|
126
|
+
});
|
|
119
127
|
};
|
|
120
128
|
const transact = (s, fn) => {
|
|
121
129
|
if (!s.shared || s.deactivated) {
|
|
@@ -126,7 +134,7 @@ const transact = (s, fn) => {
|
|
|
126
134
|
const result = shared.txq.then(() => s.store.lock(async () => {
|
|
127
135
|
const stored = s.store.load();
|
|
128
136
|
if (stored !== null && stored.clientId !== s.record.clientId) adoptReset(s, stored);
|
|
129
|
-
else if (stored !== null) s.record = stored;
|
|
137
|
+
else if (stored !== null) s.record = boundRecord(stored);
|
|
130
138
|
fn();
|
|
131
139
|
const persistence = s.store.flush?.();
|
|
132
140
|
if (persistence) await persistence;
|
|
@@ -160,11 +168,27 @@ const failedCommands = (s) => {
|
|
|
160
168
|
}
|
|
161
169
|
return s.failedList;
|
|
162
170
|
};
|
|
171
|
+
const MAX_FAILED_RETAINED = 256;
|
|
172
|
+
const boundFailed = (failed) => failed.length > 256 ? [...failed].sort((a, b) => a.ts - b.ts).slice(-256) : failed;
|
|
173
|
+
const boundRecord = (record) => {
|
|
174
|
+
let lanes = record.lanes;
|
|
175
|
+
for (const [protocol, lane] of Object.entries(lanes)) if (lane.failed !== void 0 && lane.failed.length > 256) lanes = {
|
|
176
|
+
...lanes,
|
|
177
|
+
[protocol]: {
|
|
178
|
+
...lane,
|
|
179
|
+
failed: boundFailed(lane.failed)
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
return lanes === record.lanes ? record : {
|
|
183
|
+
...record,
|
|
184
|
+
lanes
|
|
185
|
+
};
|
|
186
|
+
};
|
|
163
187
|
const retainFailedInner = (s, entry, failure) => {
|
|
164
188
|
const lane = laneOf(s.record, entry.command.protocol);
|
|
165
189
|
setRecord(s, withLane(s.record, entry.command.protocol, {
|
|
166
190
|
...lane,
|
|
167
|
-
failed: [...lane.failed ?? [], {
|
|
191
|
+
failed: boundFailed([...lane.failed ?? [], {
|
|
168
192
|
protocol: entry.command.protocol,
|
|
169
193
|
...entry.command.produced !== void 0 && { produced: entry.command.produced },
|
|
170
194
|
command: entry.command.method,
|
|
@@ -173,7 +197,7 @@ const retainFailedInner = (s, entry, failure) => {
|
|
|
173
197
|
failure,
|
|
174
198
|
ts: entry.inv.ts,
|
|
175
199
|
seq: entry.seq
|
|
176
|
-
}]
|
|
200
|
+
}])
|
|
177
201
|
}));
|
|
178
202
|
s.notify();
|
|
179
203
|
};
|
|
@@ -264,7 +288,7 @@ const rebaseRecord = (s, adopt) => {
|
|
|
264
288
|
...lanes,
|
|
265
289
|
[protocol]: {
|
|
266
290
|
...current,
|
|
267
|
-
failed: [...current.failed ?? [], ...failed]
|
|
291
|
+
failed: boundFailed([...current.failed ?? [], ...failed])
|
|
268
292
|
}
|
|
269
293
|
};
|
|
270
294
|
}
|
|
@@ -283,7 +307,7 @@ const resetRecord = (s, clientId) => rebaseRecord(s, () => setRecord(s, {
|
|
|
283
307
|
}));
|
|
284
308
|
const adoptReset = (s, stored) => {
|
|
285
309
|
rebaseRecord(s, () => {
|
|
286
|
-
s.record = stored;
|
|
310
|
+
s.record = boundRecord(stored);
|
|
287
311
|
});
|
|
288
312
|
if (s.attach === "attached") s.transport?.connection.reconnect();
|
|
289
313
|
};
|
|
@@ -520,7 +544,7 @@ const handleHello = (s, { ops, syn }) => {
|
|
|
520
544
|
const handleOps = (s, { ops, cmds }) => {
|
|
521
545
|
ingestOps(s, ops);
|
|
522
546
|
for (const cmd of cmds) handleCmd(s, cmd);
|
|
523
|
-
syncBacklog(s);
|
|
547
|
+
if (cmds.length > 0) syncBacklog(s);
|
|
524
548
|
publishIngested(s);
|
|
525
549
|
};
|
|
526
550
|
const handleRefusal = (s, syn) => {
|
|
@@ -656,7 +680,7 @@ const pump = async (s) => {
|
|
|
656
680
|
let result;
|
|
657
681
|
try {
|
|
658
682
|
const send = () => transport.send(lanes.frame);
|
|
659
|
-
result = await (s.shared && !s.deactivated ? s.store.lock(send) : send());
|
|
683
|
+
result = await (s.shared && !s.deactivated && lanes.entries.length > 0 ? s.store.lock(send) : send());
|
|
660
684
|
} catch {
|
|
661
685
|
if (!s.running || isFinished(s)) return;
|
|
662
686
|
if (lanes.frame.ctx?.length) {
|
|
@@ -807,7 +831,7 @@ const adoptStored = (s) => {
|
|
|
807
831
|
const known = new Set(laneEntries(s, protocol).map((p) => p.seq));
|
|
808
832
|
for (const { seq, ...command } of lane.commands) {
|
|
809
833
|
if (known.has(seq)) continue;
|
|
810
|
-
const params = command.meta === void 0 ? command.params : reviveDocumentValue(
|
|
834
|
+
const params = command.meta === void 0 ? command.params : reviveDocumentValue(structuredClone(command.params), command.meta);
|
|
811
835
|
const entry = {
|
|
812
836
|
seq,
|
|
813
837
|
command: {
|
|
@@ -905,7 +929,7 @@ const retryFailed = (s, entry) => {
|
|
|
905
929
|
});
|
|
906
930
|
const found = findFailed(s, entry);
|
|
907
931
|
if (found === void 0) throw unknownFailed(entry);
|
|
908
|
-
const params = found.meta === void 0 ? found.params : reviveDocumentValue(
|
|
932
|
+
const params = found.meta === void 0 ? found.params : reviveDocumentValue(structuredClone(found.params), found.meta);
|
|
909
933
|
const result = new Promise((resolve, reject) => {
|
|
910
934
|
const retry = () => {
|
|
911
935
|
if (!s.running) {
|
|
@@ -1005,11 +1029,11 @@ const loadSessionRecord = (store, options) => {
|
|
|
1005
1029
|
store.save(stored);
|
|
1006
1030
|
}
|
|
1007
1031
|
}
|
|
1008
|
-
const record = stored
|
|
1032
|
+
const record = stored === null ? {
|
|
1009
1033
|
clientId: randomId(),
|
|
1010
1034
|
lanes: {}
|
|
1011
|
-
};
|
|
1012
|
-
if (
|
|
1035
|
+
} : boundRecord(stored);
|
|
1036
|
+
if (record !== stored) store.save(record);
|
|
1013
1037
|
return record;
|
|
1014
1038
|
};
|
|
1015
1039
|
const setContext = (s, protocol, value) => {
|
|
@@ -1062,6 +1086,7 @@ const useStatewireSession = (options) => {
|
|
|
1062
1086
|
documentStore,
|
|
1063
1087
|
shared: store.lock !== void 0 ? {
|
|
1064
1088
|
txq: Promise.resolve(),
|
|
1089
|
+
syncQueued: false,
|
|
1065
1090
|
parked: [],
|
|
1066
1091
|
unsubscribe: null
|
|
1067
1092
|
} : false,
|
|
@@ -1158,6 +1183,6 @@ const useStatewireSession = (options) => {
|
|
|
1158
1183
|
return s;
|
|
1159
1184
|
};
|
|
1160
1185
|
//#endregion
|
|
1161
|
-
export { discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setContext, setTransport, useStatewireSession };
|
|
1186
|
+
export { MAX_FAILED_RETAINED, discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setContext, setTransport, useStatewireSession };
|
|
1162
1187
|
|
|
1163
1188
|
//# sourceMappingURL=session.js.map
|