statewire 0.24.2 → 0.24.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/transports/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,gCAA6B;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAc;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAiB;
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/transports/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,gCAA6B;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAc;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAiB;AAU1C,8BAA2B;AAE3B,+EAA+E;AAC/E,eAAO,MAAM,IAAI,qBAAmD,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,mCAAgC;AAE1D,MAAM,MAAM,aAAa,CAAC,MAAM,IAAI;IAClC,iEAAiE;IACjE,SAAS,EAAE,eAAe,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/D,4CAA4C;IAC5C,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,EAAE,CAAC;IACpE,QAAQ,EAAE,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,2EAA2E;IAC3E,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,mDAAmD;IACnD,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,0DAA0D;IAC1D,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,mDAAmD;IACnD,YAAY,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,2EAA2E;IAC3E,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B,CAAC;AASF,eAAO,MAAM,mBAAmB,GAAI,MAAM,EACxC,cAAc,MAAM,EACpB,iBAAoB,EACpB,UAAS;IAAE,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAO,KAC9C,aAAa,CAAC,MAAM,CA+ItB,CAAC"}
|
|
@@ -48,7 +48,11 @@ const createMockTransport = (initialState, protocol = "default", options = {}) =
|
|
|
48
48
|
if (!clients.has(id)) clients.set(id, {});
|
|
49
49
|
const rec = clients.get(id);
|
|
50
50
|
const ephemeral = ephemeralLanes();
|
|
51
|
-
const
|
|
51
|
+
const negotiation = parseNegotiation(headers);
|
|
52
|
+
const offers = negotiation.applicationProtocols;
|
|
53
|
+
const offered = negotiation.wireVersion;
|
|
54
|
+
const wireVersion = offered.version < "2026-11-02" ? offered.version : WIRE_VERSION;
|
|
55
|
+
if (wireVersion < "2026-11-01" || offered.minVersion !== void 0 && wireVersion < offered.minVersion) throw new Error("mock wire version was not offered");
|
|
52
56
|
const applicationVersion = offers === "*" ? DEFAULT_PROTOCOL_VERSION : offers.find((offer) => offer.name === protocol)?.version;
|
|
53
57
|
if (applicationVersion === void 0) throw new Error("mock protocol was not offered");
|
|
54
58
|
for (const lane of ephemeral) delete rec[lane];
|
|
@@ -63,7 +67,7 @@ const createMockTransport = (initialState, protocol = "default", options = {}) =
|
|
|
63
67
|
value: state
|
|
64
68
|
}],
|
|
65
69
|
syn: {
|
|
66
|
-
version:
|
|
70
|
+
version: wireVersion,
|
|
67
71
|
protocols: [{
|
|
68
72
|
name: protocol,
|
|
69
73
|
version: applicationVersion,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","names":["ResourceElement","StatewireEnvelope","StatewireHttp","StatewireFrame","Statewire","openSSEStream","sseFrame","FakeStreamHandle","DEFAULT_PROTOCOL_VERSION","WIRE_VERSION","parseNegotiation","tick","Promise","r","setTimeout","applyOptimistic","MockTransport","transport","TState","commands","protocol","method","params","contexts","NonNullable","setState","state","applied","seq","settle","payload","sendEnvelope","envelope","finish","reason","message","clientId","attached","mockCount","createMockTransport","initialState","options","ephemeral","ephemeralLanes","map","child","finished","clients","Map","Record","streams","Set","stream","send","admit","id","frame","rec","get","push","ctx","statement","cmd","fakeFetch","input","RequestInfo","URL","init","RequestInit","Response","TypeError","url","String","headers","Headers","endsWith","has","set","offers","applicationProtocols","applicationVersion","find","offer","name","version","undefined","Error","lane","JSON","parse","body","handle","ops","op","main","value","syn","protocols","record","const","signal","json","status","fetch","next","path","type","fin","close","size"],"sources":["../../src/transports/testing.ts"],"sourcesContent":["import type { ResourceElement } from \"@assistant-ui/tap\";\nimport type { StatewireEnvelope } from \"../client/connection\";\nimport { StatewireHttp } from \"./sse\";\nimport type { StatewireFrame } from \"./sse\";\nimport type { Statewire } from \"../types\";\nimport { openSSEStream, sseFrame } from \"./fake-sse\";\nimport type { FakeStreamHandle } from \"./fake-sse\";\nimport {\n DEFAULT_PROTOCOL_VERSION,\n WIRE_VERSION,\n parseNegotiation,\n} from \"../wire/protocol\";\n\nexport * from \"./fixtures\";\n\n/** Let queued microtasks and op batches drain through the statewire client. */\nexport const tick = () => new Promise<void>((r) => setTimeout(r, 0));\n\nexport { applyOptimistic } from \"../util/recordMutations\";\n\nexport type MockTransport<TState> = {\n /** Pass as the `transport:` option of useStatewire / Harness. */\n transport: ResourceElement<Statewire<TState | undefined, any>>;\n /** Captured statements in arrival order. */\n commands: { protocol: string; method: string; params: unknown[] }[];\n contexts: NonNullable<StatewireFrame[\"ctx\"]>;\n /** Replace the replicated state and broadcast it as a root snapshot op. */\n setState: (state: TState) => Promise<void>;\n /** Deliver a bare ack cmd packet on the stream. */\n applied: (seq: number) => Promise<void>;\n /** Deliver a terminal result cmd packet on the stream. */\n settle: (seq: number, payload?: unknown) => Promise<void>;\n /** Deliver an arbitrary envelope on the stream. */\n sendEnvelope: (envelope: StatewireEnvelope) => Promise<void>;\n /** End the stream with a fin; further attaches fail like a dead server. */\n finish: (reason: string, message?: string) => Promise<void>;\n readonly clientId: string;\n readonly attached: boolean;\n};\n\n/**\n * A mock statewire backend: serves `initialState` as the attach snapshot,\n * records submitted frames (receipt only — acks and results are delivered\n * from test code), and exposes the wire as a transport ResourceElement.\n */\nlet mockCount = 0;\n\nexport const createMockTransport = <TState>(\n initialState: TState,\n protocol = \"default\",\n options: { ephemeral?: readonly string[] } = {},\n): MockTransport<TState> => {\n // Read per attach: a test can grow the lane set between connects.\n const ephemeralLanes = () =>\n (options.ephemeral ?? []).map((child) => `${protocol}/${child}`);\n let state: unknown = initialState;\n let clientId = \"\";\n let finished = false;\n const clients = new Map<string, Record<string, number>>();\n const streams = new Set<FakeStreamHandle>();\n const commands: MockTransport<unknown>[\"commands\"] = [];\n const contexts: MockTransport<unknown>[\"contexts\"] = [];\n\n const sendEnvelope = (envelope: StatewireEnvelope) => {\n for (const stream of streams) stream.send(sseFrame(envelope));\n return tick();\n };\n\n const admit = (id: string, frame: StatewireFrame) => {\n const rec = clients.get(id)!;\n contexts.push(...(frame.ctx ?? []));\n for (const statement of frame.cmd ?? []) {\n if (statement.seq <= (rec[statement.protocol] ?? 0)) continue;\n rec[statement.protocol] = statement.seq;\n commands.push({\n protocol: statement.protocol,\n method: statement.method,\n params: statement.params,\n });\n }\n };\n\n const fakeFetch = (async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n if (finished) throw new TypeError(\"fetch failed (finished)\");\n const url = String(input);\n const headers = new Headers(init?.headers);\n const id = headers.get(\"Statewire-Client-Id\") ?? \"\";\n if (url.endsWith(\"/stream\")) {\n clientId = id;\n if (!clients.has(id)) clients.set(id, {});\n const rec = clients.get(id)!;\n const ephemeral = ephemeralLanes();\n const offers = parseNegotiation(headers).applicationProtocols;\n const applicationVersion =\n offers === \"*\"\n ? DEFAULT_PROTOCOL_VERSION\n : offers.find((offer) => offer.name === protocol)?.version;\n if (applicationVersion === undefined)\n throw new Error(\"mock protocol was not offered\");\n for (const lane of ephemeral) delete rec[lane];\n const frame = JSON.parse(String(init?.body ?? \"{}\")) as StatewireFrame;\n admit(id, frame);\n return openSSEStream(\n streams,\n id,\n (handle) => {\n handle.send(\n sseFrame({\n ops: [{ op: \"mount\", protocol, main: true, value: state }],\n syn: {\n version: WIRE_VERSION,\n protocols: [\n {\n name: protocol,\n version: applicationVersion,\n seq: rec[protocol] ?? 0,\n },\n ...ephemeral.map((name) => ({\n name,\n version: applicationVersion,\n record: \"ephemeral\" as const,\n seq: 0,\n })),\n ],\n },\n }),\n );\n },\n init?.signal ?? undefined,\n { \"Statewire-Lease\": \"mock-lease\" },\n );\n }\n if (url.endsWith(\"/frames\")) {\n admit(clientId, JSON.parse(String(init?.body ?? \"{}\")) as StatewireFrame);\n return Response.json({});\n }\n return new Response(null, { status: 404 });\n }) as typeof fetch;\n\n return {\n transport: StatewireHttp({\n url: `http://mock-${++mockCount}/api`,\n fetch: fakeFetch,\n }),\n commands,\n contexts,\n setState: (next) => {\n state = next;\n return sendEnvelope({ ops: [{ op: \"replace\", path: [], value: next }] });\n },\n applied: (seq) =>\n sendEnvelope({ cmd: [{ protocol, seq, type: \"applied\" }] }),\n settle: (seq, payload) =>\n sendEnvelope({\n cmd: [\n {\n protocol,\n seq,\n type: \"result\",\n ...(payload !== undefined && { payload }),\n },\n ],\n }),\n sendEnvelope,\n finish: async (reason, message) => {\n await sendEnvelope({\n fin: { reason, ...(message !== undefined && { message }) },\n });\n finished = true;\n for (const stream of [...streams]) stream.close();\n await tick();\n },\n get clientId() {\n return clientId;\n },\n get attached() {\n return streams.size > 0;\n },\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"testing.js","names":["ResourceElement","StatewireEnvelope","StatewireHttp","StatewireFrame","Statewire","openSSEStream","sseFrame","FakeStreamHandle","DEFAULT_PROTOCOL_VERSION","GAP_FILL_VERSION","WIRE_VERSION","parseNegotiation","tick","Promise","r","setTimeout","applyOptimistic","MockTransport","transport","TState","commands","protocol","method","params","contexts","NonNullable","setState","state","applied","seq","settle","payload","sendEnvelope","envelope","finish","reason","message","clientId","attached","mockCount","createMockTransport","initialState","options","ephemeral","ephemeralLanes","map","child","finished","clients","Map","Record","streams","Set","stream","send","admit","id","frame","rec","get","push","ctx","statement","cmd","fakeFetch","input","RequestInfo","URL","init","RequestInit","Response","TypeError","url","String","headers","Headers","endsWith","has","set","negotiation","offers","applicationProtocols","offered","wireVersion","version","minVersion","undefined","Error","applicationVersion","find","offer","name","lane","JSON","parse","body","handle","ops","op","main","value","syn","protocols","record","const","signal","json","status","fetch","next","path","type","fin","close","size"],"sources":["../../src/transports/testing.ts"],"sourcesContent":["import type { ResourceElement } from \"@assistant-ui/tap\";\nimport type { StatewireEnvelope } from \"../client/connection\";\nimport { StatewireHttp } from \"./sse\";\nimport type { StatewireFrame } from \"./sse\";\nimport type { Statewire } from \"../types\";\nimport { openSSEStream, sseFrame } from \"./fake-sse\";\nimport type { FakeStreamHandle } from \"./fake-sse\";\nimport {\n DEFAULT_PROTOCOL_VERSION,\n GAP_FILL_VERSION,\n WIRE_VERSION,\n parseNegotiation,\n} from \"../wire/protocol\";\n\nexport * from \"./fixtures\";\n\n/** Let queued microtasks and op batches drain through the statewire client. */\nexport const tick = () => new Promise<void>((r) => setTimeout(r, 0));\n\nexport { applyOptimistic } from \"../util/recordMutations\";\n\nexport type MockTransport<TState> = {\n /** Pass as the `transport:` option of useStatewire / Harness. */\n transport: ResourceElement<Statewire<TState | undefined, any>>;\n /** Captured statements in arrival order. */\n commands: { protocol: string; method: string; params: unknown[] }[];\n contexts: NonNullable<StatewireFrame[\"ctx\"]>;\n /** Replace the replicated state and broadcast it as a root snapshot op. */\n setState: (state: TState) => Promise<void>;\n /** Deliver a bare ack cmd packet on the stream. */\n applied: (seq: number) => Promise<void>;\n /** Deliver a terminal result cmd packet on the stream. */\n settle: (seq: number, payload?: unknown) => Promise<void>;\n /** Deliver an arbitrary envelope on the stream. */\n sendEnvelope: (envelope: StatewireEnvelope) => Promise<void>;\n /** End the stream with a fin; further attaches fail like a dead server. */\n finish: (reason: string, message?: string) => Promise<void>;\n readonly clientId: string;\n readonly attached: boolean;\n};\n\n/**\n * A mock statewire backend: serves `initialState` as the attach snapshot,\n * records submitted frames (receipt only — acks and results are delivered\n * from test code), and exposes the wire as a transport ResourceElement.\n */\nlet mockCount = 0;\n\nexport const createMockTransport = <TState>(\n initialState: TState,\n protocol = \"default\",\n options: { ephemeral?: readonly string[] } = {},\n): MockTransport<TState> => {\n // Read per attach: a test can grow the lane set between connects.\n const ephemeralLanes = () =>\n (options.ephemeral ?? []).map((child) => `${protocol}/${child}`);\n let state: unknown = initialState;\n let clientId = \"\";\n let finished = false;\n const clients = new Map<string, Record<string, number>>();\n const streams = new Set<FakeStreamHandle>();\n const commands: MockTransport<unknown>[\"commands\"] = [];\n const contexts: MockTransport<unknown>[\"contexts\"] = [];\n\n const sendEnvelope = (envelope: StatewireEnvelope) => {\n for (const stream of streams) stream.send(sseFrame(envelope));\n return tick();\n };\n\n const admit = (id: string, frame: StatewireFrame) => {\n const rec = clients.get(id)!;\n contexts.push(...(frame.ctx ?? []));\n for (const statement of frame.cmd ?? []) {\n if (statement.seq <= (rec[statement.protocol] ?? 0)) continue;\n rec[statement.protocol] = statement.seq;\n commands.push({\n protocol: statement.protocol,\n method: statement.method,\n params: statement.params,\n });\n }\n };\n\n const fakeFetch = (async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n if (finished) throw new TypeError(\"fetch failed (finished)\");\n const url = String(input);\n const headers = new Headers(init?.headers);\n const id = headers.get(\"Statewire-Client-Id\") ?? \"\";\n if (url.endsWith(\"/stream\")) {\n clientId = id;\n if (!clients.has(id)) clients.set(id, {});\n const rec = clients.get(id)!;\n const ephemeral = ephemeralLanes();\n const negotiation = parseNegotiation(headers);\n const offers = negotiation.applicationProtocols;\n // The newest wire this mock speaks that the client offered. It speaks\n // GAP_FILL_VERSION and newer: it skips a re-sent seq instead of\n // re-emitting its verdict, as older wires require.\n const offered = negotiation.wireVersion;\n const wireVersion =\n offered.version < WIRE_VERSION ? offered.version : WIRE_VERSION;\n if (\n wireVersion < GAP_FILL_VERSION ||\n (offered.minVersion !== undefined && wireVersion < offered.minVersion)\n )\n throw new Error(\"mock wire version was not offered\");\n const applicationVersion =\n offers === \"*\"\n ? DEFAULT_PROTOCOL_VERSION\n : offers.find((offer) => offer.name === protocol)?.version;\n if (applicationVersion === undefined)\n throw new Error(\"mock protocol was not offered\");\n for (const lane of ephemeral) delete rec[lane];\n const frame = JSON.parse(String(init?.body ?? \"{}\")) as StatewireFrame;\n admit(id, frame);\n return openSSEStream(\n streams,\n id,\n (handle) => {\n handle.send(\n sseFrame({\n ops: [{ op: \"mount\", protocol, main: true, value: state }],\n syn: {\n version: wireVersion,\n protocols: [\n {\n name: protocol,\n version: applicationVersion,\n seq: rec[protocol] ?? 0,\n },\n ...ephemeral.map((name) => ({\n name,\n version: applicationVersion,\n record: \"ephemeral\" as const,\n seq: 0,\n })),\n ],\n },\n }),\n );\n },\n init?.signal ?? undefined,\n { \"Statewire-Lease\": \"mock-lease\" },\n );\n }\n if (url.endsWith(\"/frames\")) {\n admit(clientId, JSON.parse(String(init?.body ?? \"{}\")) as StatewireFrame);\n return Response.json({});\n }\n return new Response(null, { status: 404 });\n }) as typeof fetch;\n\n return {\n transport: StatewireHttp({\n url: `http://mock-${++mockCount}/api`,\n fetch: fakeFetch,\n }),\n commands,\n contexts,\n setState: (next) => {\n state = next;\n return sendEnvelope({ ops: [{ op: \"replace\", path: [], value: next }] });\n },\n applied: (seq) =>\n sendEnvelope({ cmd: [{ protocol, seq, type: \"applied\" }] }),\n settle: (seq, payload) =>\n sendEnvelope({\n cmd: [\n {\n protocol,\n seq,\n type: \"result\",\n ...(payload !== undefined && { payload }),\n },\n ],\n }),\n sendEnvelope,\n finish: async (reason, message) => {\n await sendEnvelope({\n fin: { reason, ...(message !== undefined && { message }) },\n });\n finished = true;\n for (const stream of [...streams]) stream.close();\n await tick();\n },\n get clientId() {\n return clientId;\n },\n get attached() {\n return streams.size > 0;\n },\n };\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ import { openSSEStream, sseFrame } from "./fake-sse";
|
|
|
7
7
|
import type { FakeStreamHandle } from "./fake-sse";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_PROTOCOL_VERSION,
|
|
10
|
+
GAP_FILL_VERSION,
|
|
10
11
|
WIRE_VERSION,
|
|
11
12
|
parseNegotiation,
|
|
12
13
|
} from "../wire/protocol";
|
|
@@ -93,7 +94,19 @@ export const createMockTransport = <TState>(
|
|
|
93
94
|
if (!clients.has(id)) clients.set(id, {});
|
|
94
95
|
const rec = clients.get(id)!;
|
|
95
96
|
const ephemeral = ephemeralLanes();
|
|
96
|
-
const
|
|
97
|
+
const negotiation = parseNegotiation(headers);
|
|
98
|
+
const offers = negotiation.applicationProtocols;
|
|
99
|
+
// The newest wire this mock speaks that the client offered. It speaks
|
|
100
|
+
// GAP_FILL_VERSION and newer: it skips a re-sent seq instead of
|
|
101
|
+
// re-emitting its verdict, as older wires require.
|
|
102
|
+
const offered = negotiation.wireVersion;
|
|
103
|
+
const wireVersion =
|
|
104
|
+
offered.version < WIRE_VERSION ? offered.version : WIRE_VERSION;
|
|
105
|
+
if (
|
|
106
|
+
wireVersion < GAP_FILL_VERSION ||
|
|
107
|
+
(offered.minVersion !== undefined && wireVersion < offered.minVersion)
|
|
108
|
+
)
|
|
109
|
+
throw new Error("mock wire version was not offered");
|
|
97
110
|
const applicationVersion =
|
|
98
111
|
offers === "*"
|
|
99
112
|
? DEFAULT_PROTOCOL_VERSION
|
|
@@ -111,7 +124,7 @@ export const createMockTransport = <TState>(
|
|
|
111
124
|
sseFrame({
|
|
112
125
|
ops: [{ op: "mount", protocol, main: true, value: state }],
|
|
113
126
|
syn: {
|
|
114
|
-
version:
|
|
127
|
+
version: wireVersion,
|
|
115
128
|
protocols: [
|
|
116
129
|
{
|
|
117
130
|
name: protocol,
|