statewire 0.21.0 → 0.22.1
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/changes.d.ts +3 -6
- package/dist/client/changes.d.ts.map +1 -1
- package/dist/client/changes.js +1 -2
- package/dist/client/connection.d.ts +80 -83
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +2 -3
- package/dist/client/connection.js.map +1 -1
- package/dist/client/core.d.ts +39 -41
- package/dist/client/core.d.ts.map +1 -1
- package/dist/client/core.js +2 -3
- package/dist/client/session.d.ts +93 -95
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +6 -7
- package/dist/client/session.js.map +1 -1
- package/dist/client/sessionStore.d.ts +11 -14
- package/dist/client/sessionStore.d.ts.map +1 -1
- package/dist/client/sessionStore.js +1 -2
- package/dist/client/storageError.d.ts +2 -5
- package/dist/client/storageError.d.ts.map +1 -1
- package/dist/client/storageError.js +1 -2
- package/dist/client/timing.d.ts +11 -14
- package/dist/client/timing.d.ts.map +1 -1
- package/dist/client/timing.js +1 -2
- package/dist/document.d.ts +17 -20
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +1 -2
- package/dist/host/adapter.d.ts +4 -7
- package/dist/host/adapter.d.ts.map +1 -1
- package/dist/host/adapter.js +1 -2
- package/dist/host/draft.d.ts +13 -16
- package/dist/host/draft.d.ts.map +1 -1
- package/dist/host/draft.js +1 -2
- package/dist/host/engine.d.ts +7 -10
- package/dist/host/engine.d.ts.map +1 -1
- package/dist/host/engine.js +1 -2
- package/dist/host/host.d.ts +42 -45
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.js +1 -2
- package/dist/host/http.d.ts +4 -7
- package/dist/host/http.d.ts.map +1 -1
- package/dist/host/http.js +2 -3
- package/dist/host/socket.d.ts +148 -145
- package/dist/host/socket.d.ts.map +1 -1
- package/dist/host/socket.js +30 -12
- package/dist/host/socket.js.map +1 -1
- package/dist/host/synced.d.ts +3 -6
- package/dist/host/synced.d.ts.map +1 -1
- package/dist/host/synced.js +1 -2
- package/dist/host/work.d.ts +2 -5
- package/dist/host/work.d.ts.map +1 -1
- package/dist/host/work.js +1 -2
- package/dist/host-internal.d.ts +101 -93
- package/dist/host-internal.d.ts.map +1 -1
- package/dist/host.d.ts +90 -91
- package/dist/host.d.ts.map +1 -1
- package/dist/index.d.ts +11 -8
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -1
- package/dist/statewire.d.ts +265 -268
- package/dist/statewire.d.ts.map +1 -1
- package/dist/statewire.js +1 -2
- package/dist/storage.d.ts +23 -26
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +1 -2
- package/dist/transports/fake-sse.d.ts +7 -10
- package/dist/transports/fake-sse.d.ts.map +1 -1
- package/dist/transports/fake-sse.js +1 -2
- package/dist/transports/fixtures.d.ts +19 -25
- package/dist/transports/fixtures.d.ts.map +1 -1
- package/dist/transports/fixtures.js +1 -2
- package/dist/transports/remote.d.ts +8 -11
- package/dist/transports/remote.d.ts.map +1 -1
- package/dist/transports/remote.js +1 -2
- package/dist/transports/sse-parser.d.ts +1 -4
- package/dist/transports/sse-parser.d.ts.map +1 -1
- package/dist/transports/sse-parser.js +1 -2
- package/dist/transports/sse.d.ts +50 -53
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js +2 -3
- package/dist/transports/testing.d.ts +31 -34
- package/dist/transports/testing.d.ts.map +1 -1
- package/dist/transports/testing.js +1 -2
- package/dist/transports/ws.d.ts +5 -7
- package/dist/transports/ws.d.ts.map +1 -1
- package/dist/transports/ws.js +3 -4
- package/dist/transports/ws.js.map +1 -1
- package/dist/types.d.ts +81 -78
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -2
- package/dist/util/draftTraps.d.ts +2 -4
- package/dist/util/draftTraps.d.ts.map +1 -1
- package/dist/util/draftTraps.js +1 -2
- package/dist/util/macrotask.d.ts +1 -4
- package/dist/util/macrotask.d.ts.map +1 -1
- package/dist/util/macrotask.js +1 -2
- package/dist/util/methodProxy.d.ts +1 -4
- package/dist/util/methodProxy.d.ts.map +1 -1
- package/dist/util/methodProxy.js +1 -2
- package/dist/util/randomId.d.ts +1 -4
- package/dist/util/randomId.d.ts.map +1 -1
- package/dist/util/randomId.js +1 -2
- package/dist/util/recordMutations.d.ts +5 -7
- package/dist/util/recordMutations.d.ts.map +1 -1
- package/dist/util/recordMutations.js +1 -2
- package/dist/util/statePath.d.ts +9 -12
- package/dist/util/statePath.d.ts.map +1 -1
- package/dist/util/statePath.js +1 -2
- package/dist/wire/context.d.ts +7 -12
- package/dist/wire/context.d.ts.map +1 -1
- package/dist/wire/context.js +2 -3
- package/dist/wire/documents.d.ts +36 -39
- package/dist/wire/documents.d.ts.map +1 -1
- package/dist/wire/documents.js +2 -3
- package/dist/wire/documents.js.map +1 -1
- package/dist/wire/limits.d.ts +7 -10
- package/dist/wire/limits.d.ts.map +1 -1
- package/dist/wire/limits.js +1 -2
- package/dist/wire/meta.d.ts +9 -11
- package/dist/wire/meta.d.ts.map +1 -1
- package/dist/wire/meta.js +1 -2
- package/dist/wire/meta.js.map +1 -1
- package/dist/wire/ops.d.ts +9 -12
- package/dist/wire/ops.d.ts.map +1 -1
- package/dist/wire/ops.js +1 -2
- package/dist/wire/protocol.d.ts +53 -56
- package/dist/wire/protocol.d.ts.map +1 -1
- package/dist/wire/protocol.js +1 -2
- package/dist/wire/version.d.ts +1 -4
- package/dist/wire/version.d.ts.map +1 -1
- package/dist/wire/version.js +1 -2
- package/package.json +6 -6
- package/src/client/connection.ts +13 -15
- package/src/host/socket.ts +63 -6
- package/src/host-internal.ts +12 -0
package/dist/wire/documents.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { reviveDocumentValue } from "../document.js";
|
|
2
1
|
import { protocolToken } from "./protocol.js";
|
|
2
|
+
import { reviveDocumentValue } from "../document.js";
|
|
3
3
|
import { applyOps } from "./ops.js";
|
|
4
|
-
|
|
4
|
+
// src/wire/documents.ts
|
|
5
5
|
const invalid = (message) => {
|
|
6
6
|
throw new Error(`statewire: protocol error: ${message}`);
|
|
7
7
|
};
|
|
@@ -88,7 +88,6 @@ const findDocument = (state, protocol, key, prefix) => {
|
|
|
88
88
|
const resolved = resolveDocumentKey(key, prefix);
|
|
89
89
|
return [...state.documents.values()].find((document) => document.protocol === protocol && document.key !== null && (JSON.stringify(document.key) === JSON.stringify(key) || resolved !== void 0 && JSON.stringify(resolveDocumentKey(document.key, prefix)) === JSON.stringify(resolved)));
|
|
90
90
|
};
|
|
91
|
-
//#endregion
|
|
92
91
|
export { applyDocumentOps, findDocument, mainDocument, resolveDocumentKey };
|
|
93
92
|
|
|
94
93
|
//# sourceMappingURL=documents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.js","names":["applyOps","reviveValue","protocolToken","StatewirePath","StatewireDocuments","CacheEntry","version","value","Storage","namespace","load","identity","save","entry","subscribe","listener","Source","get","protocol","key","prefix","list","ReadonlyMap","Document","main","State","mode","documents","invalid","message","Error","applyDocumentOps","previous","ops","protocols","name","strict","undefined","length","Map","changedPaths","raw","Array","isArray","op","Record","doc","Number","isSafeInteger","includes","_doc","unknown","path","set","has","every","test","some","p","values","d","JSON","stringify","meta","rejectUnknown","push","document","delete","part","mutation","applied","state","mainDocument","find","resolveDocumentKey","slice","findDocument","resolved"],"sources":["../../src/wire/documents.ts"],"sourcesContent":["import { applyOps } from \"./ops\";\nimport { reviveValue } from \"./meta\";\nimport { protocolToken } from \"./protocol\";\nimport type { StatewirePath } from \"./ops\";\n\nexport namespace StatewireDocuments {\n export type CacheEntry = { version: string; value: unknown };\n export type Storage = {\n namespace?: string;\n load: (identity: readonly string[]) => CacheEntry | undefined;\n save: (identity: readonly string[], entry: CacheEntry) => void;\n subscribe?: (listener: () => void) => () => void;\n };\n export type Source = {\n get: (\n protocol: string,\n key?: readonly string[],\n prefix?: readonly string[],\n ) => unknown;\n list: () => ReadonlyMap<number, Document>;\n subscribe: (listener: () => void) => () => void;\n };\n export type Document = {\n key: readonly string[] | null;\n protocol?: string;\n main?: boolean;\n value: unknown;\n };\n export type State = {\n mode: \"mounted\" | \"keyless\" | null;\n documents: ReadonlyMap<number, Document>;\n };\n}\n\nconst invalid: (message: string) => never = (message) => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nexport const applyDocumentOps = (\n previous: StatewireDocuments.State,\n ops: readonly unknown[],\n protocols?: readonly { name: string; version: string }[],\n strict = false,\n) => {\n let mode =\n previous.mode ??\n (protocols !== undefined && ops.length === 0 ? \"mounted\" : null);\n const documents = new Map(previous.documents);\n const changedPaths: StatewirePath[] = [];\n for (const raw of ops) {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n invalid(\"operation must be an object\");\n }\n const op = raw as Record<string, unknown>;\n const doc = op.doc === undefined ? 0 : op.doc;\n if (typeof doc !== \"number\" || !Number.isSafeInteger(doc) || doc < 0) {\n invalid(\"doc must be a nonnegative safe integer\");\n }\n if (\n ![\"mount\", \"unmount\", \"add\", \"replace\", \"remove\"].includes(\n op.op as string,\n )\n ) {\n if (strict) invalid(\"unknown context operation\");\n const { doc: _doc, ...unknown } = op;\n applyOps(undefined, [unknown]);\n continue;\n }\n if (protocols !== undefined && mode === null && op.op !== \"mount\")\n invalid(\"negotiated state must start with mounts\");\n if (mode === null) {\n if (op.op === \"mount\") mode = \"mounted\";\n else if (\n op.op === \"replace\" &&\n doc === 0 &&\n Array.isArray(op.path) &&\n op.path.length === 0 &&\n \"value\" in op\n ) {\n mode = \"keyless\";\n documents.set(0, { key: null, value: undefined });\n } else\n invalid(\n \"first operation must mount a document or replace document 0 at the root\",\n );\n }\n if (\n mode === \"keyless\" &&\n (doc !== 0 || op.op === \"mount\" || op.op === \"unmount\")\n ) {\n invalid(\"keyless mode only supports mutations of document 0\");\n }\n if (op.op === \"mount\") {\n if (documents.has(doc)) invalid(\"document is already mounted\");\n if (\n (op.key !== undefined &&\n (!Array.isArray(op.key) ||\n !op.key.every((key) => typeof key === \"string\"))) ||\n !(\"value\" in op)\n ) {\n invalid(\"mount requires value and an optional key array\");\n }\n if (\n op.protocol !== undefined &&\n (typeof op.protocol !== \"string\" ||\n !protocolToken.test(op.protocol) ||\n op.protocol === \"*\")\n )\n invalid(\"invalid mount protocol\");\n if (\n protocols !== undefined &&\n !protocols.some((p) => p.name === op.protocol)\n )\n invalid(\"mount protocol was not negotiated\");\n if (op.main !== undefined && typeof op.main !== \"boolean\")\n invalid(\"main must be boolean\");\n if (\n op.main === true &&\n [...documents.values()].some(\n (d) => d.protocol === op.protocol && d.main,\n )\n )\n invalid(\"protocol already has a main document\");\n if (\n op.key !== undefined &&\n [...documents.values()].some(\n (d) =>\n d.protocol === op.protocol &&\n JSON.stringify(d.key) === JSON.stringify(op.key),\n )\n )\n invalid(\"protocol document key is already mounted\");\n documents.set(doc, {\n key: op.key === undefined ? null : (op.key as string[]),\n ...(op.protocol === undefined\n ? {}\n : { protocol: op.protocol as string }),\n ...(op.main === undefined ? {} : { main: op.main as boolean }),\n value:\n op.meta === undefined\n ? op.value\n : reviveValue(op.value, op.meta, { rejectUnknown: strict }),\n });\n if (doc === 0) changedPaths.push([]);\n } else if (op.op === \"unmount\") {\n const document = documents.get(doc);\n if (\n protocols !== undefined &&\n document !== undefined &&\n !protocols.some((p) => p.name === document.protocol)\n )\n invalid(\"document protocol was not negotiated\");\n if (!documents.delete(doc)) invalid(\"document is not mounted\");\n if (doc === 0) changedPaths.push([]);\n } else if (op.op === \"add\" || op.op === \"replace\" || op.op === \"remove\") {\n const document = documents.get(doc);\n if (\n protocols !== undefined &&\n document !== undefined &&\n !protocols.some((p) => p.name === document.protocol)\n )\n invalid(\"document protocol was not negotiated\");\n if (!document) invalid(\"document is not mounted\");\n if (\n !Array.isArray(op.path) ||\n !op.path.every(\n (part) =>\n typeof part === \"string\" ||\n (typeof part === \"number\" &&\n Number.isSafeInteger(part) &&\n part >= 0),\n )\n ) {\n invalid(\"operation requires a valid path\");\n }\n if (op.op !== \"remove\" && !(\"value\" in op))\n invalid(\"operation requires a value\");\n const { doc: _doc, meta, ...mutation } = op;\n if (meta !== undefined)\n mutation.value = reviveValue(mutation.value, meta, {\n rejectUnknown: strict,\n });\n const applied = applyOps(document.value, [mutation]);\n documents.set(doc, { ...document, value: applied.state });\n if (doc === 0) changedPaths.push(...applied.changedPaths);\n }\n }\n if (mode === null) invalid(\"hello missing snapshot\");\n return { mode, documents, changedPaths };\n};\n\nexport const mainDocument = (\n state: StatewireDocuments.State,\n protocol: string,\n) =>\n [...state.documents.values()].find(\n (document) => document.protocol === protocol && document.main,\n );\n\nexport const resolveDocumentKey = (\n key: readonly string[],\n prefix?: readonly string[],\n) =>\n key[0] === \".\"\n ? prefix === undefined\n ? undefined\n : [...prefix, ...key.slice(1)]\n : key;\n\nexport const findDocument = (\n state: StatewireDocuments.State,\n protocol: string,\n key?: readonly string[],\n prefix?: readonly string[],\n) => {\n if (key === undefined) return mainDocument(state, protocol);\n const resolved = resolveDocumentKey(key, prefix);\n return [...state.documents.values()].find(\n (document) =>\n document.protocol === protocol &&\n document.key !== null &&\n (JSON.stringify(document.key) === JSON.stringify(key) ||\n (resolved !== undefined &&\n JSON.stringify(resolveDocumentKey(document.key, prefix)) ===\n JSON.stringify(resolved))),\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"documents.js","names":["applyOps","reviveValue","protocolToken","StatewirePath","StatewireDocuments","CacheEntry","version","value","Storage","namespace","load","identity","save","entry","subscribe","listener","Source","get","protocol","key","prefix","list","ReadonlyMap","Document","main","State","mode","documents","invalid","message","Error","applyDocumentOps","previous","ops","protocols","name","strict","undefined","length","Map","changedPaths","raw","Array","isArray","op","Record","doc","Number","isSafeInteger","includes","_doc","unknown","path","set","has","every","test","some","p","values","d","JSON","stringify","meta","rejectUnknown","push","document","delete","part","mutation","applied","state","mainDocument","find","resolveDocumentKey","slice","findDocument","resolved","reviveValue"],"sources":["../../src/wire/documents.ts"],"sourcesContent":["import { applyOps } from \"./ops\";\nimport { reviveValue } from \"./meta\";\nimport { protocolToken } from \"./protocol\";\nimport type { StatewirePath } from \"./ops\";\n\nexport namespace StatewireDocuments {\n export type CacheEntry = { version: string; value: unknown };\n export type Storage = {\n namespace?: string;\n load: (identity: readonly string[]) => CacheEntry | undefined;\n save: (identity: readonly string[], entry: CacheEntry) => void;\n subscribe?: (listener: () => void) => () => void;\n };\n export type Source = {\n get: (\n protocol: string,\n key?: readonly string[],\n prefix?: readonly string[],\n ) => unknown;\n list: () => ReadonlyMap<number, Document>;\n subscribe: (listener: () => void) => () => void;\n };\n export type Document = {\n key: readonly string[] | null;\n protocol?: string;\n main?: boolean;\n value: unknown;\n };\n export type State = {\n mode: \"mounted\" | \"keyless\" | null;\n documents: ReadonlyMap<number, Document>;\n };\n}\n\nconst invalid: (message: string) => never = (message) => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nexport const applyDocumentOps = (\n previous: StatewireDocuments.State,\n ops: readonly unknown[],\n protocols?: readonly { name: string; version: string }[],\n strict = false,\n) => {\n let mode =\n previous.mode ??\n (protocols !== undefined && ops.length === 0 ? \"mounted\" : null);\n const documents = new Map(previous.documents);\n const changedPaths: StatewirePath[] = [];\n for (const raw of ops) {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n invalid(\"operation must be an object\");\n }\n const op = raw as Record<string, unknown>;\n const doc = op.doc === undefined ? 0 : op.doc;\n if (typeof doc !== \"number\" || !Number.isSafeInteger(doc) || doc < 0) {\n invalid(\"doc must be a nonnegative safe integer\");\n }\n if (\n ![\"mount\", \"unmount\", \"add\", \"replace\", \"remove\"].includes(\n op.op as string,\n )\n ) {\n if (strict) invalid(\"unknown context operation\");\n const { doc: _doc, ...unknown } = op;\n applyOps(undefined, [unknown]);\n continue;\n }\n if (protocols !== undefined && mode === null && op.op !== \"mount\")\n invalid(\"negotiated state must start with mounts\");\n if (mode === null) {\n if (op.op === \"mount\") mode = \"mounted\";\n else if (\n op.op === \"replace\" &&\n doc === 0 &&\n Array.isArray(op.path) &&\n op.path.length === 0 &&\n \"value\" in op\n ) {\n mode = \"keyless\";\n documents.set(0, { key: null, value: undefined });\n } else\n invalid(\n \"first operation must mount a document or replace document 0 at the root\",\n );\n }\n if (\n mode === \"keyless\" &&\n (doc !== 0 || op.op === \"mount\" || op.op === \"unmount\")\n ) {\n invalid(\"keyless mode only supports mutations of document 0\");\n }\n if (op.op === \"mount\") {\n if (documents.has(doc)) invalid(\"document is already mounted\");\n if (\n (op.key !== undefined &&\n (!Array.isArray(op.key) ||\n !op.key.every((key) => typeof key === \"string\"))) ||\n !(\"value\" in op)\n ) {\n invalid(\"mount requires value and an optional key array\");\n }\n if (\n op.protocol !== undefined &&\n (typeof op.protocol !== \"string\" ||\n !protocolToken.test(op.protocol) ||\n op.protocol === \"*\")\n )\n invalid(\"invalid mount protocol\");\n if (\n protocols !== undefined &&\n !protocols.some((p) => p.name === op.protocol)\n )\n invalid(\"mount protocol was not negotiated\");\n if (op.main !== undefined && typeof op.main !== \"boolean\")\n invalid(\"main must be boolean\");\n if (\n op.main === true &&\n [...documents.values()].some(\n (d) => d.protocol === op.protocol && d.main,\n )\n )\n invalid(\"protocol already has a main document\");\n if (\n op.key !== undefined &&\n [...documents.values()].some(\n (d) =>\n d.protocol === op.protocol &&\n JSON.stringify(d.key) === JSON.stringify(op.key),\n )\n )\n invalid(\"protocol document key is already mounted\");\n documents.set(doc, {\n key: op.key === undefined ? null : (op.key as string[]),\n ...(op.protocol === undefined\n ? {}\n : { protocol: op.protocol as string }),\n ...(op.main === undefined ? {} : { main: op.main as boolean }),\n value:\n op.meta === undefined\n ? op.value\n : reviveValue(op.value, op.meta, { rejectUnknown: strict }),\n });\n if (doc === 0) changedPaths.push([]);\n } else if (op.op === \"unmount\") {\n const document = documents.get(doc);\n if (\n protocols !== undefined &&\n document !== undefined &&\n !protocols.some((p) => p.name === document.protocol)\n )\n invalid(\"document protocol was not negotiated\");\n if (!documents.delete(doc)) invalid(\"document is not mounted\");\n if (doc === 0) changedPaths.push([]);\n } else if (op.op === \"add\" || op.op === \"replace\" || op.op === \"remove\") {\n const document = documents.get(doc);\n if (\n protocols !== undefined &&\n document !== undefined &&\n !protocols.some((p) => p.name === document.protocol)\n )\n invalid(\"document protocol was not negotiated\");\n if (!document) invalid(\"document is not mounted\");\n if (\n !Array.isArray(op.path) ||\n !op.path.every(\n (part) =>\n typeof part === \"string\" ||\n (typeof part === \"number\" &&\n Number.isSafeInteger(part) &&\n part >= 0),\n )\n ) {\n invalid(\"operation requires a valid path\");\n }\n if (op.op !== \"remove\" && !(\"value\" in op))\n invalid(\"operation requires a value\");\n const { doc: _doc, meta, ...mutation } = op;\n if (meta !== undefined)\n mutation.value = reviveValue(mutation.value, meta, {\n rejectUnknown: strict,\n });\n const applied = applyOps(document.value, [mutation]);\n documents.set(doc, { ...document, value: applied.state });\n if (doc === 0) changedPaths.push(...applied.changedPaths);\n }\n }\n if (mode === null) invalid(\"hello missing snapshot\");\n return { mode, documents, changedPaths };\n};\n\nexport const mainDocument = (\n state: StatewireDocuments.State,\n protocol: string,\n) =>\n [...state.documents.values()].find(\n (document) => document.protocol === protocol && document.main,\n );\n\nexport const resolveDocumentKey = (\n key: readonly string[],\n prefix?: readonly string[],\n) =>\n key[0] === \".\"\n ? prefix === undefined\n ? undefined\n : [...prefix, ...key.slice(1)]\n : key;\n\nexport const findDocument = (\n state: StatewireDocuments.State,\n protocol: string,\n key?: readonly string[],\n prefix?: readonly string[],\n) => {\n if (key === undefined) return mainDocument(state, protocol);\n const resolved = resolveDocumentKey(key, prefix);\n return [...state.documents.values()].find(\n (document) =>\n document.protocol === protocol &&\n document.key !== null &&\n (JSON.stringify(document.key) === JSON.stringify(key) ||\n (resolved !== undefined &&\n JSON.stringify(resolveDocumentKey(document.key, prefix)) ===\n JSON.stringify(resolved))),\n );\n};\n"],"mappings":"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"}
|
package/dist/wire/limits.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
declare const
|
|
3
|
-
declare const
|
|
4
|
-
declare const
|
|
5
|
-
declare const
|
|
6
|
-
declare const
|
|
7
|
-
declare const
|
|
8
|
-
declare const MAX_CONTEXT_BYTES: number;
|
|
9
|
-
//#endregion
|
|
10
|
-
export { COMMAND_CAPACITY_RETRY_MS, MAX_COMMANDS_PER_FRAME, MAX_CONTEXT_BYTES, MAX_EPHEMERAL_DOCUMENT_BYTES, MAX_FRAME_BODY_BYTES, MAX_INFLIGHT_COMMANDS_PER_CLIENT, MAX_INFLIGHT_COMMANDS_PER_HOST };
|
|
1
|
+
export declare const MAX_COMMANDS_PER_FRAME = 256;
|
|
2
|
+
export declare const MAX_INFLIGHT_COMMANDS_PER_CLIENT = 256;
|
|
3
|
+
export declare const MAX_FRAME_BODY_BYTES: number;
|
|
4
|
+
export declare const MAX_EPHEMERAL_DOCUMENT_BYTES: number;
|
|
5
|
+
export declare const MAX_INFLIGHT_COMMANDS_PER_HOST = 1024;
|
|
6
|
+
export declare const COMMAND_CAPACITY_RETRY_MS = 1000;
|
|
7
|
+
export declare const MAX_CONTEXT_BYTES: number;
|
|
11
8
|
//# sourceMappingURL=limits.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"limits.d.ts","
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/wire/limits.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,oBAAoB,QAAkB,CAAC;AACpD,eAAO,MAAM,4BAA4B,QAAY,CAAC;AACtD,eAAO,MAAM,8BAA8B,OAAO,CAAC;AACnD,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C,eAAO,MAAM,iBAAiB,QAAY,CAAC"}
|
package/dist/wire/limits.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/wire/limits.ts
|
|
2
2
|
const MAX_COMMANDS_PER_FRAME = 256;
|
|
3
3
|
const MAX_INFLIGHT_COMMANDS_PER_CLIENT = 256;
|
|
4
4
|
const MAX_FRAME_BODY_BYTES = 8388608;
|
|
@@ -6,7 +6,6 @@ const MAX_EPHEMERAL_DOCUMENT_BYTES = 65536;
|
|
|
6
6
|
const MAX_INFLIGHT_COMMANDS_PER_HOST = 1024;
|
|
7
7
|
const COMMAND_CAPACITY_RETRY_MS = 1e3;
|
|
8
8
|
const MAX_CONTEXT_BYTES = 65536;
|
|
9
|
-
//#endregion
|
|
10
9
|
export { COMMAND_CAPACITY_RETRY_MS, MAX_COMMANDS_PER_FRAME, MAX_CONTEXT_BYTES, MAX_EPHEMERAL_DOCUMENT_BYTES, MAX_FRAME_BODY_BYTES, MAX_INFLIGHT_COMMANDS_PER_CLIENT, MAX_INFLIGHT_COMMANDS_PER_HOST };
|
|
11
10
|
|
|
12
11
|
//# sourceMappingURL=limits.js.map
|
package/dist/wire/meta.d.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { StatewireDocument
|
|
2
|
-
|
|
3
|
-
declare const reviveOps: (ops: unknown[]) => unknown[];
|
|
4
|
-
declare const reviveResponse: <T extends {
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import type { StatewireDocument } from "../document.js";
|
|
2
|
+
export { reviveDocumentValue as reviveValue } from "../document.js";
|
|
3
|
+
export declare const reviveOps: (ops: unknown[]) => unknown[];
|
|
4
|
+
export declare const reviveResponse: <T extends {
|
|
5
|
+
payload?: unknown;
|
|
6
|
+
meta?: unknown;
|
|
7
7
|
}>(response: T) => T;
|
|
8
|
-
declare const encodeParams: (params: readonly unknown[]) => {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export declare const encodeParams: (params: readonly unknown[]) => {
|
|
9
|
+
params: unknown[];
|
|
10
|
+
meta?: StatewireDocument.MetaEntry[];
|
|
11
11
|
};
|
|
12
|
-
//#endregion
|
|
13
|
-
export { encodeParams, reviveOps, reviveResponse, reviveDocumentValue as reviveValue };
|
|
14
12
|
//# sourceMappingURL=meta.d.ts.map
|
package/dist/wire/meta.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meta.d.ts","
|
|
1
|
+
{"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../src/wire/meta.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,uBAAoB;AAErD,OAAO,EAAE,mBAAmB,IAAI,WAAW,EAAE,uBAAoB;AAEjE,eAAO,MAAM,SAAS,GAAI,KAAK,OAAO,EAAE,KAAG,OAAO,EAK9C,CAAC;AAEL,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,EAC5E,UAAU,CAAC,KACV,CAIF,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,QAAQ,SAAS,OAAO,EAAE,KACzB;IAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,iBAAiB,CAAC,SAAS,EAAE,CAAA;CAK3D,CAAC"}
|
package/dist/wire/meta.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { encodeDocument, reviveDocumentValue } from "../document.js";
|
|
2
|
-
|
|
2
|
+
// src/wire/meta.ts
|
|
3
3
|
const reviveOps = (ops) => ops.map((op) => {
|
|
4
4
|
if (typeof op !== "object" || op === null || !("meta" in op)) return op;
|
|
5
5
|
const { meta, ...rest } = op;
|
|
@@ -23,7 +23,6 @@ const encodeParams = (params) => {
|
|
|
23
23
|
meta
|
|
24
24
|
} : { params: value };
|
|
25
25
|
};
|
|
26
|
-
//#endregion
|
|
27
26
|
export { encodeParams, reviveOps, reviveResponse, reviveDocumentValue as reviveValue };
|
|
28
27
|
|
|
29
28
|
//# sourceMappingURL=meta.js.map
|
package/dist/wire/meta.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meta.js","names":["encodeDocument","reviveDocumentValue","reviveValue","StatewireDocument","reviveOps","ops","map","op","meta","rest","value","reviveResponse","payload","response","T","undefined","encodeParams","params","MetaEntry"],"sources":["../../src/wire/meta.ts"],"sourcesContent":["import {\n encodeDocument,\n reviveDocumentValue as reviveValue,\n} from \"../document\";\nimport type { StatewireDocument } from \"../document\";\n\nexport { reviveDocumentValue as reviveValue } from \"../document\";\n\nexport const reviveOps = (ops: unknown[]): unknown[] =>\n ops.map((op) => {\n if (typeof op !== \"object\" || op === null || !(\"meta\" in op)) return op;\n const { meta, ...rest } = op as { meta: unknown; value?: unknown };\n return { ...rest, value: reviveValue(rest.value, meta) };\n });\n\nexport const reviveResponse = <T extends { payload?: unknown; meta?: unknown }>(\n response: T,\n): T => {\n if (response.meta === undefined) return response;\n const { meta, ...rest } = response;\n return { ...rest, payload: reviveValue(rest.payload, meta) } as T;\n};\n\nexport const encodeParams = (\n params: readonly unknown[],\n): { params: unknown[]; meta?: StatewireDocument.MetaEntry[] } => {\n const { value, meta } = encodeDocument(params);\n return meta\n ? { params: value as unknown[], meta }\n : { params: value as unknown[] };\n};\n"],"mappings":";;AAQA,MAAaI,aAAaC,QACxBA,IAAIC,KAAKC,OAAO;CACd,IAAI,OAAOA,OAAO,YAAYA,OAAO,QAAQ,EAAE,UAAUA,KAAK,OAAOA;CACrE,MAAM,EAAEC,MAAM,GAAGC,SAASF;CAC1B,OAAO;EAAE,GAAGE;EAAMC,OAAOR,oBAAYO,KAAKC,OAAOF,IAAI;CAAE;AACzD,CAAC;AAEH,MAAaG,kBACXE,aACM;CACN,IAAIA,SAASL,SAASO,KAAAA,GAAW,OAAOF;CACxC,MAAM,EAAEL,MAAM,GAAGC,SAASI;CAC1B,OAAO;EAAE,GAAGJ;EAAMG,SAASV,oBAAYO,KAAKG,SAASJ,IAAI;CAAE;AAC7D;AAEA,MAAaQ,gBACXC,WACgE;CAChE,MAAM,EAAEP,OAAOF,SAASR,eAAeiB,MAAM;CAC7C,OAAOT,OACH;EAAES,QAAQP;EAAoBF;CAAK,IACnC,EAAES,QAAQP,MAAmB;AACnC"}
|
|
1
|
+
{"version":3,"file":"meta.js","names":["encodeDocument","reviveDocumentValue","reviveValue","StatewireDocument","reviveOps","ops","map","op","meta","rest","value","reviveResponse","payload","response","T","undefined","encodeParams","params","MetaEntry","reviveValue"],"sources":["../../src/wire/meta.ts"],"sourcesContent":["import {\n encodeDocument,\n reviveDocumentValue as reviveValue,\n} from \"../document\";\nimport type { StatewireDocument } from \"../document\";\n\nexport { reviveDocumentValue as reviveValue } from \"../document\";\n\nexport const reviveOps = (ops: unknown[]): unknown[] =>\n ops.map((op) => {\n if (typeof op !== \"object\" || op === null || !(\"meta\" in op)) return op;\n const { meta, ...rest } = op as { meta: unknown; value?: unknown };\n return { ...rest, value: reviveValue(rest.value, meta) };\n });\n\nexport const reviveResponse = <T extends { payload?: unknown; meta?: unknown }>(\n response: T,\n): T => {\n if (response.meta === undefined) return response;\n const { meta, ...rest } = response;\n return { ...rest, payload: reviveValue(rest.payload, meta) } as T;\n};\n\nexport const encodeParams = (\n params: readonly unknown[],\n): { params: unknown[]; meta?: StatewireDocument.MetaEntry[] } => {\n const { value, meta } = encodeDocument(params);\n return meta\n ? { params: value as unknown[], meta }\n : { params: value as unknown[] };\n};\n"],"mappings":";;AAQA,MAAaI,aAAaC,QACxBA,IAAIC,KAAKC,OAAO;CACd,IAAI,OAAOA,OAAO,YAAYA,OAAO,QAAQ,EAAE,UAAUA,KAAK,OAAOA;CACrE,MAAM,EAAEC,MAAM,GAAGC,SAASF;CAC1B,OAAO;EAAE,GAAGE;EAAMC,OAAOR,oBAAYO,KAAKC,OAAOF,IAAI;CAAE;AACzD,CAAC;AAEH,MAAaG,kBACXE,aACM;CACN,IAAIA,SAASL,SAASO,KAAAA,GAAW,OAAOF;CACxC,MAAM,EAAEL,MAAM,GAAGC,SAASI;CAC1B,OAAO;EAAE,GAAGJ;EAAMG,SAASV,oBAAYO,KAAKG,SAASJ,IAAI;CAAE;AAC7D;AAEA,MAAaQ,gBACXC,WACgE;CAChE,MAAM,EAAEP,OAAOF,SAASR,eAAeiB,MAAM;CAC7C,OAAOT,OACH;EAAES,QAAQP;EAAoBF;CAAK,IACnC,EAAES,QAAQP,MAAmB;AACnC"}
|
package/dist/wire/ops.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { Statewire } from "../types.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
declare const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
changedPaths: StatewirePath[];
|
|
1
|
+
import type { Statewire } from "../types.js";
|
|
2
|
+
export type StatewirePath = readonly (string | number)[];
|
|
3
|
+
export declare const sanitizeValue: (value: unknown, parent?: string) => unknown;
|
|
4
|
+
export declare const applyOp: (root: unknown, op: Statewire.Op) => {
|
|
5
|
+
state: unknown;
|
|
6
|
+
changedPaths: StatewirePath[];
|
|
8
7
|
};
|
|
9
|
-
declare const applyOps: (state: unknown, ops: readonly unknown[]) => {
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
export declare const applyOps: (state: unknown, ops: readonly unknown[]) => {
|
|
9
|
+
state: unknown;
|
|
10
|
+
changedPaths: StatewirePath[];
|
|
12
11
|
};
|
|
13
|
-
//#endregion
|
|
14
|
-
export { StatewirePath, applyOp, applyOps, sanitizeValue };
|
|
15
12
|
//# sourceMappingURL=ops.d.ts.map
|
package/dist/wire/ops.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.d.ts","
|
|
1
|
+
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../src/wire/ops.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAiB;AAE1C,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AAwDzD,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,EAAE,SAAS,MAAM,KAAG,OACC,CAAC;AA+HlE,eAAO,MAAM,OAAO,GAClB,MAAM,OAAO,EACb,IAAI,SAAS,CAAC,EAAE,KACf;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,aAAa,EAAE,CAAA;CAQjD,CAAC;AAEF,eAAO,MAAM,QAAQ,GACnB,OAAO,OAAO,EACd,KAAK,SAAS,OAAO,EAAE,KACtB;IACD,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,aAAa,EAAE,CAAC;CAkB/B,CAAC"}
|
package/dist/wire/ops.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isUnsafeKey, walkStatePath } from "../util/statePath.js";
|
|
2
2
|
import { recordMutations } from "../util/recordMutations.js";
|
|
3
|
-
|
|
3
|
+
// src/wire/ops.ts
|
|
4
4
|
const warnStripped = (key, parent) => {
|
|
5
5
|
if (typeof process === "undefined" || process.env["NODE_ENV"] !== "production") console.warn(`statewire: stripped unsafe key "${key}"` + (parent === void 0 ? "" : ` under "${parent}"`));
|
|
6
6
|
};
|
|
@@ -130,7 +130,6 @@ const applyOps = (state, ops) => {
|
|
|
130
130
|
changedPaths: unboxPaths(recorded.changedPaths)
|
|
131
131
|
};
|
|
132
132
|
};
|
|
133
|
-
//#endregion
|
|
134
133
|
export { applyOp, applyOps, sanitizeValue };
|
|
135
134
|
|
|
136
135
|
//# sourceMappingURL=ops.js.map
|
package/dist/wire/protocol.d.ts
CHANGED
|
@@ -1,60 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
};
|
|
1
|
+
export declare namespace StatewireProtocol {
|
|
2
|
+
type Range = {
|
|
3
|
+
version: string;
|
|
4
|
+
minVersion?: string;
|
|
5
|
+
};
|
|
6
|
+
type Offer = Range & {
|
|
7
|
+
name: string;
|
|
8
|
+
optional?: boolean;
|
|
9
|
+
};
|
|
10
|
+
type Selection = {
|
|
11
|
+
version: string;
|
|
12
|
+
protocols: {
|
|
13
|
+
name: string;
|
|
14
|
+
version: string;
|
|
15
|
+
record?: "ephemeral";
|
|
16
|
+
}[];
|
|
17
|
+
};
|
|
18
|
+
type Options = {
|
|
19
|
+
wireVersion?: Range;
|
|
20
|
+
applicationProtocols?: readonly Offer[] | "*";
|
|
21
|
+
protocol?: string;
|
|
22
|
+
keyPrefixes?: Readonly<Record<string, readonly string[]>>;
|
|
23
|
+
};
|
|
24
|
+
type Definition = Range & {
|
|
25
|
+
name: string;
|
|
26
|
+
requires?: Readonly<Record<string, Range>>;
|
|
27
|
+
subprotocols?: readonly {
|
|
28
|
+
name: string;
|
|
29
|
+
record?: "ephemeral";
|
|
30
|
+
}[];
|
|
31
|
+
};
|
|
33
32
|
}
|
|
34
|
-
declare const WIRE_VERSION = "2026-09-30";
|
|
35
|
-
declare const DEFAULT_PROTOCOL = "default";
|
|
36
|
-
declare const PROTOCOL_HEADER = "Statewire-Protocol";
|
|
37
|
-
declare const VERSION_HEADER = "Statewire-Version";
|
|
38
|
-
declare const protocolToken: RegExp;
|
|
39
|
-
declare const validateVersion: (value: unknown) => string;
|
|
40
|
-
declare const validateRange: (range: StatewireProtocol.Range) => {
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
export declare const WIRE_VERSION = "2026-09-30";
|
|
34
|
+
export declare const DEFAULT_PROTOCOL = "default";
|
|
35
|
+
export declare const PROTOCOL_HEADER = "Statewire-Protocol";
|
|
36
|
+
export declare const VERSION_HEADER = "Statewire-Version";
|
|
37
|
+
export declare const protocolToken: RegExp;
|
|
38
|
+
export declare const validateVersion: (value: unknown) => string;
|
|
39
|
+
export declare const validateRange: (range: StatewireProtocol.Range) => {
|
|
40
|
+
version: string;
|
|
41
|
+
minVersion: string;
|
|
43
42
|
};
|
|
44
|
-
declare const inRange: (value: string, range: StatewireProtocol.Range) => boolean;
|
|
45
|
-
declare const protocolOffers: (options: StatewireProtocol.Options) => readonly StatewireProtocol.Offer[] | "*";
|
|
46
|
-
declare const negotiationHeaders: (options: StatewireProtocol.Options) => Record<string, string>;
|
|
47
|
-
declare const parseNegotiation: (headers: Headers) => Required<Pick<StatewireProtocol.Options, "wireVersion" | "applicationProtocols">>;
|
|
48
|
-
declare const validateSelection: (value: unknown, options: StatewireProtocol.Options) => StatewireProtocol.Selection;
|
|
49
|
-
declare const negotiateProtocols: (headers: Headers, wire: StatewireProtocol.Range, definitions: readonly StatewireProtocol.Definition[]) => StatewireProtocol.Selection | {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
export declare const inRange: (value: string, range: StatewireProtocol.Range) => boolean;
|
|
44
|
+
export declare const protocolOffers: (options: StatewireProtocol.Options) => readonly StatewireProtocol.Offer[] | "*";
|
|
45
|
+
export declare const negotiationHeaders: (options: StatewireProtocol.Options) => Record<string, string>;
|
|
46
|
+
export declare const parseNegotiation: (headers: Headers) => Required<Pick<StatewireProtocol.Options, "wireVersion" | "applicationProtocols">>;
|
|
47
|
+
export declare const validateSelection: (value: unknown, options: StatewireProtocol.Options) => StatewireProtocol.Selection;
|
|
48
|
+
export declare const negotiateProtocols: (headers: Headers, wire: StatewireProtocol.Range, definitions: readonly StatewireProtocol.Definition[]) => StatewireProtocol.Selection | {
|
|
49
|
+
fin: {
|
|
50
|
+
reason: "protocol-error";
|
|
51
|
+
code: string;
|
|
52
|
+
status: number;
|
|
53
|
+
message: string;
|
|
54
|
+
payload?: unknown;
|
|
55
|
+
};
|
|
57
56
|
};
|
|
58
|
-
//#endregion
|
|
59
|
-
export { DEFAULT_PROTOCOL, PROTOCOL_HEADER, StatewireProtocol, VERSION_HEADER, WIRE_VERSION, inRange, negotiateProtocols, negotiationHeaders, parseNegotiation, protocolOffers, protocolToken, validateRange, validateSelection, validateVersion };
|
|
60
57
|
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/wire/protocol.ts"],"names":[],"mappings":"AAAA,yBAAiB,iBAAiB,CAAC;IACjC,KAAY,KAAK,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,KAAY,KAAK,GAAG,KAAK,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACjE,KAAY,SAAS,GAAG;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,WAAW,CAAA;SAAE,EAAE,CAAC;KACtE,CAAC;IACF,KAAY,OAAO,GAAG;QACpB,WAAW,CAAC,EAAE,KAAK,CAAC;QACpB,oBAAoB,CAAC,EAAE,SAAS,KAAK,EAAE,GAAG,GAAG,CAAC;QAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;KAC3D,CAAC;IACF,KAAY,UAAU,GAAG,KAAK,GAAG;QAC/B,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAC3C,YAAY,CAAC,EAAE,SAAS;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,WAAW,CAAA;SAAE,EAAE,CAAC;KAClE,CAAC;CACH;AAED,eAAO,MAAM,YAAY,eAAe,CAAC;AACzC,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAC1C,eAAO,MAAM,eAAe,uBAAuB,CAAC;AACpD,eAAO,MAAM,cAAc,sBAAsB,CAAC;AAClD,eAAO,MAAM,aAAa,QAA6C,CAAC;AAMxE,eAAO,MAAM,eAAe,GAAI,OAAO,OAAO,KAAG,MAWhD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,iBAAiB,CAAC,KAAK;;;CAQ3D,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,OAAO,MAAM,EAAE,OAAO,iBAAiB,CAAC,KAAK,YAGpE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,iBAAiB,CAAC,OAAO,6CAG9D,CAAC;AAEJ,eAAO,MAAM,kBAAkB,GAC7B,SAAS,iBAAiB,CAAC,OAAO,KACjC,MAAM,CAAC,MAAM,EAAE,MAAM,CAgCvB,CAAC;AA6BF,eAAO,MAAM,gBAAgB,GAC3B,SAAS,OAAO,KACf,QAAQ,CACT,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,sBAAsB,CAAC,CAwDxE,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,OAAO,OAAO,EACd,SAAS,iBAAiB,CAAC,OAAO,KACjC,iBAAiB,CAAC,SA2CpB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,SAAS,OAAO,EAChB,MAAM,iBAAiB,CAAC,KAAK,EAC7B,aAAa,SAAS,iBAAiB,CAAC,UAAU,EAAE,KAElD,iBAAiB,CAAC,SAAS,GAC3B;IACE,GAAG,EAAE;QACH,MAAM,EAAE,gBAAgB,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CA2GP,CAAC"}
|
package/dist/wire/protocol.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/wire/protocol.ts
|
|
2
2
|
const WIRE_VERSION = "2026-09-30";
|
|
3
3
|
const DEFAULT_PROTOCOL = "default";
|
|
4
4
|
const PROTOCOL_HEADER = "Statewire-Protocol";
|
|
@@ -236,7 +236,6 @@ const negotiateProtocols = (headers, wire, definitions) => {
|
|
|
236
236
|
})
|
|
237
237
|
};
|
|
238
238
|
};
|
|
239
|
-
//#endregion
|
|
240
239
|
export { DEFAULT_PROTOCOL, PROTOCOL_HEADER, VERSION_HEADER, WIRE_VERSION, inRange, negotiateProtocols, negotiationHeaders, parseNegotiation, protocolOffers, protocolToken, validateRange, validateSelection, validateVersion };
|
|
241
240
|
|
|
242
241
|
//# sourceMappingURL=protocol.js.map
|
package/dist/wire/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/wire/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,iBAAiB,CAAC"}
|
package/dist/wire/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "statewire",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"description": "State over the wire: snapshot-first delta streaming and command submission for any state and any command",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -47,16 +47,16 @@
|
|
|
47
47
|
"test": "vitest run"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@assistant-ui/tap": "^0.9.
|
|
50
|
+
"@assistant-ui/tap": "^0.9.24"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": "^18 || ^19"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@assistant-ui/x-buildutils": "^0.0.
|
|
57
|
-
"@types/react": "^19.
|
|
56
|
+
"@assistant-ui/x-buildutils": "^0.0.31",
|
|
57
|
+
"@types/react": "^19.3.0",
|
|
58
58
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
59
|
-
"react": "^19.
|
|
60
|
-
"vitest": "^
|
|
59
|
+
"react": "^19.3.1",
|
|
60
|
+
"vitest": "^5.0.5"
|
|
61
61
|
}
|
|
62
62
|
}
|
package/src/client/connection.ts
CHANGED
|
@@ -718,21 +718,19 @@ export const useLink = (
|
|
|
718
718
|
};
|
|
719
719
|
return conn;
|
|
720
720
|
});
|
|
721
|
-
const [link] = useState(
|
|
722
|
-
()
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
}),
|
|
735
|
-
);
|
|
721
|
+
const [link] = useState((): RemoteLink => ({
|
|
722
|
+
get connection() {
|
|
723
|
+
return c.connection;
|
|
724
|
+
},
|
|
725
|
+
get parked() {
|
|
726
|
+
return c.parked;
|
|
727
|
+
},
|
|
728
|
+
send: (frame) => latest.current.send(c, frame),
|
|
729
|
+
storageFailed: (error) =>
|
|
730
|
+
stopForError({ connection: c, error, reason: "storage-error" }),
|
|
731
|
+
protocolFailed: (error) =>
|
|
732
|
+
stopForError({ connection: c, error, reason: "protocol-error" }),
|
|
733
|
+
}));
|
|
736
734
|
|
|
737
735
|
const negotiation = JSON.stringify([
|
|
738
736
|
props.protocol,
|
package/src/host/socket.ts
CHANGED
|
@@ -130,10 +130,14 @@ export type Conn = {
|
|
|
130
130
|
auth: unknown;
|
|
131
131
|
authorizedAt: number | undefined;
|
|
132
132
|
leaseTimer: ReturnType<typeof setTimeout> | null;
|
|
133
|
+
timedLease: boolean;
|
|
133
134
|
lanes: Map<string, Lane>;
|
|
134
135
|
contexts: Map<string, Statewire.Context>;
|
|
135
136
|
documents: Map<string, StatewireHost.Document>;
|
|
136
137
|
included: Set<string>;
|
|
138
|
+
onIncludedChange:
|
|
139
|
+
| ((included: readonly StatewireHostInternal.IncludedDocument[]) => void)
|
|
140
|
+
| undefined;
|
|
137
141
|
view: Map<string, { doc: number; value: unknown }>;
|
|
138
142
|
nextDoc: number;
|
|
139
143
|
pendingApplied: Cmd[];
|
|
@@ -357,6 +361,7 @@ export type SocketHostState = {
|
|
|
357
361
|
wireVersion: StatewireProtocol.Range;
|
|
358
362
|
heartbeatMs: number;
|
|
359
363
|
maxLeaseLifetimeMs: number | null;
|
|
364
|
+
leaseTimers: boolean;
|
|
360
365
|
wsInitTimeoutMs: number;
|
|
361
366
|
maxSubscribers: number;
|
|
362
367
|
maxInflightCommands: number;
|
|
@@ -508,7 +513,12 @@ export const expireLease = (h: SocketHostState, conn: Conn): boolean => {
|
|
|
508
513
|
const armLeaseTimer = (h: SocketHostState, conn: Conn) => {
|
|
509
514
|
if (conn.leaseTimer !== null) clearTimeout(conn.leaseTimer);
|
|
510
515
|
conn.leaseTimer = null;
|
|
511
|
-
if (
|
|
516
|
+
if (
|
|
517
|
+
h.disposed ||
|
|
518
|
+
h.maxLeaseLifetimeMs === null ||
|
|
519
|
+
expireLease(h, conn) ||
|
|
520
|
+
!conn.timedLease
|
|
521
|
+
)
|
|
512
522
|
return;
|
|
513
523
|
const delay = h.maxLeaseLifetimeMs - (Date.now() - conn.authorizedAt!);
|
|
514
524
|
conn.leaseTimer = setTimeout(
|
|
@@ -540,7 +550,8 @@ const ensureHeartbeat = (h: SocketHostState) => {
|
|
|
540
550
|
h.heartbeatTimer = setInterval(() => {
|
|
541
551
|
const now = Date.now();
|
|
542
552
|
for (const conn of [...h.conns]) {
|
|
543
|
-
if (now - conn.lastSentAt >= h.heartbeatMs
|
|
553
|
+
if (now - conn.lastSentAt >= h.heartbeatMs && !expireLease(h, conn))
|
|
554
|
+
sendTo(h, conn, "{}");
|
|
544
555
|
}
|
|
545
556
|
}, h.heartbeatMs);
|
|
546
557
|
(h.heartbeatTimer as unknown as { unref?: () => void }).unref?.();
|
|
@@ -641,6 +652,33 @@ const diffView = (h: SocketHostState, conn: Conn): WireOp[] => {
|
|
|
641
652
|
return ops;
|
|
642
653
|
};
|
|
643
654
|
|
|
655
|
+
const notifyIncluded = (conn: Conn) =>
|
|
656
|
+
conn.onIncludedChange?.(
|
|
657
|
+
[...conn.included].map(
|
|
658
|
+
(id) => JSON.parse(id) as StatewireHostInternal.IncludedDocument,
|
|
659
|
+
),
|
|
660
|
+
);
|
|
661
|
+
|
|
662
|
+
const restoredIncluded = (
|
|
663
|
+
included: readonly StatewireHostInternal.IncludedDocument[],
|
|
664
|
+
): Set<string> =>
|
|
665
|
+
new Set(
|
|
666
|
+
included.map((entry) => {
|
|
667
|
+
if (
|
|
668
|
+
!Array.isArray(entry) ||
|
|
669
|
+
entry.length !== 2 ||
|
|
670
|
+
typeof entry[0] !== "string" ||
|
|
671
|
+
!(
|
|
672
|
+
entry[1] === null ||
|
|
673
|
+
(Array.isArray(entry[1]) &&
|
|
674
|
+
entry[1].every((part) => typeof part === "string"))
|
|
675
|
+
)
|
|
676
|
+
)
|
|
677
|
+
throw new TypeError("statewire: invalid restored include");
|
|
678
|
+
return documentIdentity(entry[0], entry[1] ?? undefined);
|
|
679
|
+
}),
|
|
680
|
+
);
|
|
681
|
+
|
|
644
682
|
const attachOf = (h: SocketHostState, conn: Conn): StatewireHost.Attach => {
|
|
645
683
|
const requireSelected = (protocol: string) => {
|
|
646
684
|
const entry = conn.selection.protocols.find((p) => p.name === protocol);
|
|
@@ -700,11 +738,15 @@ const attachOf = (h: SocketHostState, conn: Conn): StatewireHost.Attach => {
|
|
|
700
738
|
include: (protocol, key) => {
|
|
701
739
|
if (requireSelected(protocol).record !== undefined)
|
|
702
740
|
throw new Error(`statewire: protocol ${protocol} is not durable`);
|
|
703
|
-
|
|
741
|
+
const id = documentIdentity(protocol, key);
|
|
742
|
+
if (conn.included.has(id)) return;
|
|
743
|
+
conn.included.add(id);
|
|
744
|
+
notifyIncluded(conn);
|
|
704
745
|
markViews(h);
|
|
705
746
|
},
|
|
706
747
|
exclude: (protocol, key) => {
|
|
707
|
-
conn.included.delete(documentIdentity(protocol, key));
|
|
748
|
+
if (!conn.included.delete(documentIdentity(protocol, key))) return;
|
|
749
|
+
notifyIncluded(conn);
|
|
708
750
|
markViews(h);
|
|
709
751
|
},
|
|
710
752
|
};
|
|
@@ -751,7 +793,7 @@ export const flush = (h: SocketHostState, fin?: StatewireHost.Fin) => {
|
|
|
751
793
|
h.pendingCmds = new Map();
|
|
752
794
|
// One packet per flush: ops first, then applied entries, then verdicts.
|
|
753
795
|
for (const conn of [...h.conns]) {
|
|
754
|
-
if (!conn.ready) continue;
|
|
796
|
+
if (!conn.ready || expireLease(h, conn)) continue;
|
|
755
797
|
const forConn = (list: Cmd[] | undefined) =>
|
|
756
798
|
(list ?? []).filter((cmd) => selects(conn, cmd.protocol));
|
|
757
799
|
const ops = [
|
|
@@ -1343,6 +1385,7 @@ const connectAuthorized = (
|
|
|
1343
1385
|
options.selection,
|
|
1344
1386
|
undefined,
|
|
1345
1387
|
options.authorizedAt,
|
|
1388
|
+
{ ...options, timedLease: h.leaseTimers },
|
|
1346
1389
|
);
|
|
1347
1390
|
return registration?.connection ?? null;
|
|
1348
1391
|
}
|
|
@@ -1496,6 +1539,12 @@ const connectAuthorized = (
|
|
|
1496
1539
|
selection,
|
|
1497
1540
|
frame,
|
|
1498
1541
|
authorizedAt,
|
|
1542
|
+
{
|
|
1543
|
+
timedLease: h.leaseTimers,
|
|
1544
|
+
...(options.onIncludedChange !== undefined && {
|
|
1545
|
+
onIncludedChange: options.onIncludedChange,
|
|
1546
|
+
}),
|
|
1547
|
+
},
|
|
1499
1548
|
);
|
|
1500
1549
|
} catch (error) {
|
|
1501
1550
|
if (violationReason(error) === null) throw error;
|
|
@@ -1559,7 +1608,12 @@ export const register = (
|
|
|
1559
1608
|
},
|
|
1560
1609
|
frame: ParsedFrame = { cmd: [] },
|
|
1561
1610
|
authorizedAt?: number,
|
|
1611
|
+
included: Pick<
|
|
1612
|
+
StatewireHostInternal.SocketConnectOptions,
|
|
1613
|
+
"included" | "onIncludedChange"
|
|
1614
|
+
> & { timedLease?: boolean } = {},
|
|
1562
1615
|
): Registration | null => {
|
|
1616
|
+
const restored = restoredIncluded(included.included ?? []);
|
|
1563
1617
|
const refuse = (code: number, reason: string) => {
|
|
1564
1618
|
try {
|
|
1565
1619
|
socket.close(code, reason);
|
|
@@ -1633,10 +1687,12 @@ export const register = (
|
|
|
1633
1687
|
auth,
|
|
1634
1688
|
authorizedAt,
|
|
1635
1689
|
leaseTimer: null,
|
|
1690
|
+
timedLease: included.timedLease ?? true,
|
|
1636
1691
|
lanes: new Map(),
|
|
1637
1692
|
contexts: new Map(),
|
|
1638
1693
|
documents: new Map(),
|
|
1639
|
-
included:
|
|
1694
|
+
included: restored,
|
|
1695
|
+
onIncludedChange: included.onIncludedChange,
|
|
1640
1696
|
view: new Map(),
|
|
1641
1697
|
nextDoc: 1,
|
|
1642
1698
|
pendingApplied: [],
|
|
@@ -1814,6 +1870,7 @@ const useSocketHost = (
|
|
|
1814
1870
|
wireVersion: { version: WIRE_VERSION },
|
|
1815
1871
|
heartbeatMs: 15_000,
|
|
1816
1872
|
maxLeaseLifetimeMs: 86_400_000,
|
|
1873
|
+
leaseTimers: persistence?.hibernatable !== true,
|
|
1817
1874
|
wsInitTimeoutMs: 5_000,
|
|
1818
1875
|
maxSubscribers: MAX_SUBSCRIBERS,
|
|
1819
1876
|
maxInflightCommands: MAX_INFLIGHT_COMMANDS_PER_HOST,
|