statewire 0.19.3 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +5 -4
- package/dist/client/connection.js.map +1 -1
- package/dist/client/session.d.ts +8 -1
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +52 -12
- package/dist/client/session.js.map +1 -1
- package/dist/client/sessionStore.d.ts +2 -0
- package/dist/client/sessionStore.d.ts.map +1 -1
- package/dist/client/sessionStore.js.map +1 -1
- package/dist/client/timing.d.ts +2 -0
- package/dist/client/timing.d.ts.map +1 -1
- package/dist/client/timing.js +5 -4
- package/dist/client/timing.js.map +1 -1
- package/dist/host/host.d.ts +2 -1
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.js +6 -1
- package/dist/host/host.js.map +1 -1
- package/dist/host/http.js +1 -1
- package/dist/host/socket.d.ts +6 -1
- package/dist/host/socket.d.ts.map +1 -1
- package/dist/host/socket.js +79 -9
- package/dist/host/socket.js.map +1 -1
- package/dist/host-internal.d.ts +1 -1
- package/dist/host.d.ts +6 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/statewire.d.ts +3 -0
- package/dist/statewire.d.ts.map +1 -1
- package/dist/statewire.js +22 -5
- package/dist/statewire.js.map +1 -1
- package/dist/transports/remote.d.ts.map +1 -1
- package/dist/transports/remote.js +3 -2
- package/dist/transports/remote.js.map +1 -1
- package/dist/transports/sse.d.ts +4 -0
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js +5 -0
- package/dist/transports/sse.js.map +1 -1
- package/dist/transports/testing.d.ts +2 -0
- package/dist/transports/testing.d.ts.map +1 -1
- package/dist/transports/testing.js +11 -4
- package/dist/transports/testing.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/wire/context.d.ts +14 -0
- package/dist/wire/context.d.ts.map +1 -0
- package/dist/wire/context.js +31 -0
- package/dist/wire/context.js.map +1 -0
- package/dist/wire/limits.d.ts +2 -1
- package/dist/wire/limits.d.ts.map +1 -1
- package/dist/wire/limits.js +2 -1
- package/dist/wire/limits.js.map +1 -1
- package/dist/wire/protocol.d.ts +1 -1
- package/dist/wire/protocol.js +4 -4
- package/dist/wire/protocol.js.map +1 -1
- package/package.json +1 -1
- package/src/client/connection.ts +6 -3
- package/src/client/session.ts +74 -4
- package/src/client/sessionStore.ts +5 -1
- package/src/client/timing.ts +12 -7
- package/src/host/host.ts +9 -0
- package/src/host/socket.ts +121 -7
- package/src/host.ts +5 -0
- package/src/statewire.ts +29 -3
- package/src/transports/remote.ts +3 -0
- package/src/transports/sse.ts +7 -0
- package/src/transports/testing.ts +14 -3
- package/src/types.ts +12 -0
- package/src/wire/context.ts +40 -0
- package/src/wire/limits.ts +2 -0
- package/src/wire/protocol.ts +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ export const App = () => {
|
|
|
35
35
|
|
|
36
36
|
Connections negotiate date ranges through `Statewire-Version` and `Statewire-Protocol`. Protocols are additive and required by default. The server selects versions in `syn`; WebSockets use `statewire.v1`.
|
|
37
37
|
|
|
38
|
-
Each protocol owns its commands, context
|
|
38
|
+
Each protocol owns its commands, lease context, and state documents. The main document is independent of its optional read key. Command sequences and replay remain shared across protocols. Python hosts support lazy, chained compatibility adapters.
|
|
39
39
|
|
|
40
40
|
See the [protocol registration and migration guide](https://github.com/assistant-ui/harness-sdk/blob/main/apps/docs/app/statewire/docs/spec/statewire-protocol/protocols/page.mdx).
|
|
41
41
|
|
|
@@ -45,3 +45,17 @@ See the [protocol registration and migration guide](https://github.com/assistant
|
|
|
45
45
|
- Guide: https://github.com/assistant-ui/harness-sdk/blob/main/apps/docs/app/statewire/docs/guides/statewire/consume/page.mdx
|
|
46
46
|
- Reference: https://github.com/assistant-ui/harness-sdk/blob/main/apps/docs/app/statewire/docs/reference/statewire/page.mdx
|
|
47
47
|
- Spec: https://github.com/assistant-ui/harness-sdk/blob/main/apps/docs/app/statewire/docs/spec/statewire-protocol/page.mdx
|
|
48
|
+
|
|
49
|
+
## Lease context
|
|
50
|
+
|
|
51
|
+
Native context belongs to a protocol and a connection lease, independently of command history:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const client = new StatewireClient({
|
|
55
|
+
transport,
|
|
56
|
+
context: { "acme-chat": { locale: "en" } },
|
|
57
|
+
});
|
|
58
|
+
client.setContext("acme-chat", { locale: "de" });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The client restores its latest object on every attachment, including a fresh hello on a preserved socket. Hosts validate through `validateContext` and react through `contextChanged`. Command handlers read `this.context`, captured when the command was admitted; later replacements cannot change queued commands. Context uses document encoding (including dates), full replacements, and a 64 KiB limit per entry. Updates consume no command sequence numbers.
|
|
@@ -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;;cA4GW,qBAAsB,mBAAiB;cA0KvC,YAAa,GAAG,MAAM,KAAK,cAAc,QAAM;cAgE/C,iBACX,GAAG,MACH,mBACC;
|
|
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;;cA4GW,qBAAsB,mBAAiB;cA0KvC,YAAa,GAAG,MAAM,KAAK,cAAc,QAAM;cAgE/C,iBACX,GAAG,MACH,mBACC;cA6IU,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;cAuFU,WAAY,SAAS,gBAAW"}
|
|
@@ -281,13 +281,13 @@ const handleEnvelope = (c, value) => {
|
|
|
281
281
|
}
|
|
282
282
|
return null;
|
|
283
283
|
};
|
|
284
|
-
const dialing = (c) => setStatus(c, c.
|
|
285
|
-
status: "connecting",
|
|
286
|
-
degraded: false
|
|
287
|
-
} : {
|
|
284
|
+
const dialing = (c) => setStatus(c, c.connection.status === "retrying" ? {
|
|
288
285
|
status: "retrying",
|
|
289
286
|
attempt: c.attempt,
|
|
290
287
|
degraded: true
|
|
288
|
+
} : {
|
|
289
|
+
status: "connecting",
|
|
290
|
+
degraded: false
|
|
291
291
|
});
|
|
292
292
|
const scheduleRetry = (c, failure, immediate) => {
|
|
293
293
|
if (c.liveAt !== null && Date.now() - c.liveAt >= timing.backoffResetMs) c.attempt = 0;
|
|
@@ -295,6 +295,7 @@ const scheduleRetry = (c, failure, immediate) => {
|
|
|
295
295
|
c.attempt += 1;
|
|
296
296
|
c.episode ??= { cause: "dropped" };
|
|
297
297
|
const delay = Math.max(immediate ? 0 : backoff(c.attempt), c.retryAt - Date.now());
|
|
298
|
+
if (delay === 0) return delay;
|
|
298
299
|
setStatus(c, {
|
|
299
300
|
status: "retrying",
|
|
300
301
|
degraded: true,
|
|
@@ -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\nconst dialing = (c: Conn) =>\n setStatus(\n c,\n c.attempt === 0\n ? { status: \"connecting\", degraded: false }\n : { status: \"retrying\", attempt: c.attempt, degraded: true },\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 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","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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"}
|
package/dist/client/session.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { RemoteLink, StatewireRemoteProps } from "../transports/sse.js";
|
|
|
5
5
|
import { StatewireClient } from "../statewire.js";
|
|
6
6
|
import { Statewire } from "../types.js";
|
|
7
7
|
import { StatewirePath } from "../wire/ops.js";
|
|
8
|
+
import { encodeContext } from "../wire/context.js";
|
|
8
9
|
//#region src/client/session.d.ts
|
|
9
10
|
type WireCommand = {
|
|
10
11
|
protocol: string;
|
|
@@ -28,6 +29,7 @@ type Pending = {
|
|
|
28
29
|
};
|
|
29
30
|
type AttachState = "detached" | "attached" | "finished";
|
|
30
31
|
type StatewireSessionOptions = StatewireProtocol.Options & {
|
|
32
|
+
context?: Readonly<Record<string, Statewire.Context>>;
|
|
31
33
|
sessionStore?: StatewireClient.SessionStorage | undefined;
|
|
32
34
|
onSessionLost?: StatewireClient.OnSessionLost | undefined;
|
|
33
35
|
onDone?: (() => void) | undefined;
|
|
@@ -42,6 +44,10 @@ type Shared = {
|
|
|
42
44
|
};
|
|
43
45
|
type Session = {
|
|
44
46
|
options: StatewireSessionOptions;
|
|
47
|
+
configuredContext: StatewireSessionOptions["context"];
|
|
48
|
+
contexts: Map<string, ReturnType<typeof encodeContext>>;
|
|
49
|
+
dirtyContexts: Set<string>;
|
|
50
|
+
attachContexts: Map<string, ReturnType<typeof encodeContext>>;
|
|
45
51
|
selection: StatewireProtocol.Selection | undefined;
|
|
46
52
|
record: StatewireClient.SessionRecord;
|
|
47
53
|
ctx: StatewireRemoteProps;
|
|
@@ -93,7 +99,8 @@ declare const discardFailed: (s: Session, entry: StatewireClient.FailedCommand)
|
|
|
93
99
|
declare const retryFailed: (s: Session, entry: StatewireClient.FailedCommand) => Promise<unknown>;
|
|
94
100
|
declare const documentSource: (s: Session) => StatewireDocuments.Source;
|
|
95
101
|
declare const invokeProtocol: (s: Session, protocol: string, method: string, params: readonly unknown[]) => Promise<unknown>;
|
|
102
|
+
declare const setContext: (s: Session, protocol: string, value: Statewire.Context) => void;
|
|
96
103
|
declare const useStatewireSession: (options: StatewireSessionOptions) => Session;
|
|
97
104
|
//#endregion
|
|
98
|
-
export { StatewireSessionOptions, discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setTransport, useStatewireSession };
|
|
105
|
+
export { StatewireSessionOptions, discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setContext, setTransport, useStatewireSession };
|
|
99
106
|
//# sourceMappingURL=session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":"
|
|
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;;cA2MxC,iBACX,GAAG,qBACO,gBAAgB;cA+wBtB,eAAgB,GAAG,SAAS,WAAW;cAiNhC,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;cAoEf,aACX,GAAG,SACH,kBACA,OAAO,UAAU;cAcN,sBACX,SAAS,4BACR"}
|
package/dist/client/session.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { reviveDocumentValue } from "../document.js";
|
|
2
|
+
import "../wire/limits.js";
|
|
2
3
|
import { inRange, protocolOffers } from "../wire/protocol.js";
|
|
4
|
+
import { encodeContext } from "../wire/context.js";
|
|
3
5
|
import { createMethodProxy } from "../util/methodProxy.js";
|
|
4
6
|
import { StatewireSendError } from "../types.js";
|
|
5
7
|
import { bindCommandsHost } from "../host/host.js";
|
|
6
8
|
import { encodeParams, reviveResponse } from "../wire/meta.js";
|
|
7
|
-
import "../wire/limits.js";
|
|
8
9
|
import { applyDocumentOps, findDocument, mainDocument, resolveDocumentKey } from "../wire/documents.js";
|
|
9
10
|
import { DocumentStorageContext, SessionStorageContext, createMemorySessionStore } from "./sessionStore.js";
|
|
10
11
|
import { backoff, retryHint } from "./timing.js";
|
|
@@ -475,6 +476,13 @@ const selectionOf = (syn) => {
|
|
|
475
476
|
};
|
|
476
477
|
};
|
|
477
478
|
const handleHello = (s, { ops, syn }) => {
|
|
479
|
+
if (s.attach === "attached") {
|
|
480
|
+
s.ephemeralSeqs = {};
|
|
481
|
+
detachEphemeralLanes(s);
|
|
482
|
+
}
|
|
483
|
+
for (const [protocol, value] of s.contexts) if (s.attachContexts.get(protocol) === value) s.dirtyContexts.delete(protocol);
|
|
484
|
+
else s.dirtyContexts.add(protocol);
|
|
485
|
+
s.attachContexts.clear();
|
|
478
486
|
s.selection = selectionOf(syn);
|
|
479
487
|
s.documents = {
|
|
480
488
|
mode: null,
|
|
@@ -574,15 +582,19 @@ const buildLanes = (s, cmdGate = "all") => {
|
|
|
574
582
|
last[protocol] = entry.seq;
|
|
575
583
|
entries.push(entry);
|
|
576
584
|
}
|
|
577
|
-
|
|
585
|
+
const ctx = [...s.dirtyContexts].map((protocol) => s.contexts.get(protocol));
|
|
586
|
+
if (entries.length === 0 && ctx.length === 0) return null;
|
|
578
587
|
return {
|
|
579
|
-
frame: {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
...command
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
588
|
+
frame: {
|
|
589
|
+
...ctx.length > 0 && { ctx },
|
|
590
|
+
...entries.length > 0 && { cmd: entries.map((p) => {
|
|
591
|
+
const { produced: _produced, ...command } = p.command;
|
|
592
|
+
return {
|
|
593
|
+
...command,
|
|
594
|
+
seq: p.seq
|
|
595
|
+
};
|
|
596
|
+
}) }
|
|
597
|
+
},
|
|
586
598
|
entries
|
|
587
599
|
};
|
|
588
600
|
};
|
|
@@ -590,6 +602,8 @@ const takeAttachLanes = (s) => {
|
|
|
590
602
|
s.attachEntries = /* @__PURE__ */ new Set();
|
|
591
603
|
const wanted = s.lanesOnAttach;
|
|
592
604
|
s.lanesOnAttach = false;
|
|
605
|
+
for (const protocol of s.contexts.keys()) s.dirtyContexts.add(protocol);
|
|
606
|
+
s.attachContexts = new Map(s.contexts);
|
|
593
607
|
const lanes = buildLanes(s, wanted && s.sessionKnown ? "persisted" : "none");
|
|
594
608
|
if (!lanes) return null;
|
|
595
609
|
s.attachEntries = new Set(lanes.entries);
|
|
@@ -620,6 +634,7 @@ const pump = async (s) => {
|
|
|
620
634
|
if (!s.hydrated) await s.ready;
|
|
621
635
|
const transport = s.transport;
|
|
622
636
|
if (buildLanes(s) === null) return;
|
|
637
|
+
if (transport?.parked && s.pending.length === 0) return;
|
|
623
638
|
if (s.attach !== "attached" || !transport) {
|
|
624
639
|
if (transport?.connection.status === "standby" && transport.connection.reason === "idle" || transport?.parked && s.pending.length > 0) transport.connection.reconnect();
|
|
625
640
|
await waitForWake(s);
|
|
@@ -644,12 +659,21 @@ const pump = async (s) => {
|
|
|
644
659
|
result = await (s.shared && !s.deactivated ? s.store.lock(send) : send());
|
|
645
660
|
} catch {
|
|
646
661
|
if (!s.running || isFinished(s)) return;
|
|
662
|
+
if (lanes.frame.ctx?.length) {
|
|
663
|
+
s.lanesOnAttach = true;
|
|
664
|
+
transport.connection.reconnect();
|
|
665
|
+
await waitForWake(s);
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
647
668
|
s.frameFailures += 1;
|
|
648
669
|
await sleepUntilWake(s, backoff(s.frameFailures));
|
|
649
670
|
continue;
|
|
650
671
|
}
|
|
651
672
|
if (!s.running) return;
|
|
652
673
|
s.frameFailures = 0;
|
|
674
|
+
if (epoch === s.attachEpoch && (result.type === "ok" || result.type === "refusal")) {
|
|
675
|
+
for (const entry of lanes.frame.ctx ?? []) if (s.contexts.get(entry.protocol) === entry) s.dirtyContexts.delete(entry.protocol);
|
|
676
|
+
}
|
|
653
677
|
if (result.type === "ok") {
|
|
654
678
|
if (epoch === s.attachEpoch) {
|
|
655
679
|
for (const entry of lanes.entries) if (s.pending.includes(entry)) {
|
|
@@ -836,7 +860,7 @@ const sendCommand = (s, method, params, protocol = s.options.protocol ?? "defaul
|
|
|
836
860
|
enqueue(s, {
|
|
837
861
|
protocol,
|
|
838
862
|
produced: {
|
|
839
|
-
wire: s.options.wireVersion ?? { version: "2026-09-
|
|
863
|
+
wire: s.options.wireVersion ?? { version: "2026-09-30" },
|
|
840
864
|
protocols: protocolOffers(s.options) === "*" && s.selection ? s.selection.protocols : protocolOffers(s.options)
|
|
841
865
|
},
|
|
842
866
|
method,
|
|
@@ -968,7 +992,7 @@ const loadSessionRecord = (store, options) => {
|
|
|
968
992
|
let stored = store.load();
|
|
969
993
|
if (stored !== null) validateLanes(stored);
|
|
970
994
|
const current = {
|
|
971
|
-
wire: options.wireVersion ?? { version: "2026-09-
|
|
995
|
+
wire: options.wireVersion ?? { version: "2026-09-30" },
|
|
972
996
|
protocols: protocolOffers(options)
|
|
973
997
|
};
|
|
974
998
|
const compatible = (record) => Object.entries(record.lanes).every(([protocol, lane]) => lane.commands.every((command) => storedCommandCompatible(protocol, command, current)));
|
|
@@ -988,6 +1012,13 @@ const loadSessionRecord = (store, options) => {
|
|
|
988
1012
|
if (stored === null) store.save(record);
|
|
989
1013
|
return record;
|
|
990
1014
|
};
|
|
1015
|
+
const setContext = (s, protocol, value) => {
|
|
1016
|
+
if (s.selection ? !s.selection.protocols.some((p) => p.name === protocol) : !offered(s, protocol)) throw new Error(`statewire: protocol "${protocol}" is not negotiated`);
|
|
1017
|
+
s.contexts.set(protocol, encodeContext(protocol, value));
|
|
1018
|
+
s.dirtyContexts.add(protocol);
|
|
1019
|
+
wake(s);
|
|
1020
|
+
pump(s);
|
|
1021
|
+
};
|
|
991
1022
|
const useStatewireSession = (options) => {
|
|
992
1023
|
const [defaultStore] = useState(createMemorySessionStore);
|
|
993
1024
|
const mounted = useContext(SessionStorageContext);
|
|
@@ -1002,6 +1033,10 @@ const useStatewireSession = (options) => {
|
|
|
1002
1033
|
};
|
|
1003
1034
|
const session = {
|
|
1004
1035
|
options,
|
|
1036
|
+
configuredContext: options.context,
|
|
1037
|
+
contexts: new Map(Object.entries(options.context ?? {}).map(([protocol, value]) => [protocol, encodeContext(protocol, value)])),
|
|
1038
|
+
dirtyContexts: new Set(Object.keys(options.context ?? {})),
|
|
1039
|
+
attachContexts: /* @__PURE__ */ new Map(),
|
|
1005
1040
|
selection: void 0,
|
|
1006
1041
|
record,
|
|
1007
1042
|
ctx: {
|
|
@@ -1095,6 +1130,11 @@ const useStatewireSession = (options) => {
|
|
|
1095
1130
|
return session;
|
|
1096
1131
|
});
|
|
1097
1132
|
if (store.lock !== void 0 !== (s.shared !== false)) throw new Error("statewire: session storage changed sharedness across renders — lock/subscribe must be present from the first render or never");
|
|
1133
|
+
useEffect(() => {
|
|
1134
|
+
if (s.configuredContext === options.context) return;
|
|
1135
|
+
s.configuredContext = options.context;
|
|
1136
|
+
for (const [protocol_0, value_0] of Object.entries(options.context ?? {})) setContext(s, protocol_0, value_0);
|
|
1137
|
+
}, [s, options.context]);
|
|
1098
1138
|
s.options = options;
|
|
1099
1139
|
s.store = store;
|
|
1100
1140
|
s.documentStore = documentStore;
|
|
@@ -1118,6 +1158,6 @@ const useStatewireSession = (options) => {
|
|
|
1118
1158
|
return s;
|
|
1119
1159
|
};
|
|
1120
1160
|
//#endregion
|
|
1121
|
-
export { discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setTransport, useStatewireSession };
|
|
1161
|
+
export { discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setContext, setTransport, useStatewireSession };
|
|
1122
1162
|
|
|
1123
1163
|
//# sourceMappingURL=session.js.map
|