statewire 0.0.0-0 → 0.0.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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -1
  3. package/dist/client/changes.d.ts +7 -0
  4. package/dist/client/changes.d.ts.map +1 -0
  5. package/dist/client/changes.js +32 -0
  6. package/dist/client/changes.js.map +1 -0
  7. package/dist/client/connection.d.ts +84 -0
  8. package/dist/client/connection.d.ts.map +1 -0
  9. package/dist/client/connection.js +204 -0
  10. package/dist/client/connection.js.map +1 -0
  11. package/dist/client/core.d.ts +18 -0
  12. package/dist/client/core.d.ts.map +1 -0
  13. package/dist/client/core.js +269 -0
  14. package/dist/client/core.js.map +1 -0
  15. package/dist/client/optimistic.d.ts +10 -0
  16. package/dist/client/optimistic.d.ts.map +1 -0
  17. package/dist/client/optimistic.js +128 -0
  18. package/dist/client/optimistic.js.map +1 -0
  19. package/dist/client/session.d.ts +88 -0
  20. package/dist/client/session.d.ts.map +1 -0
  21. package/dist/client/session.js +509 -0
  22. package/dist/client/session.js.map +1 -0
  23. package/dist/client/sessionStore.d.ts +16 -0
  24. package/dist/client/sessionStore.d.ts.map +1 -0
  25. package/dist/client/sessionStore.js +14 -0
  26. package/dist/client/sessionStore.js.map +1 -0
  27. package/dist/client/timing.d.ts +10 -0
  28. package/dist/client/timing.d.ts.map +1 -0
  29. package/dist/client/timing.js +11 -0
  30. package/dist/client/timing.js.map +1 -0
  31. package/dist/host/draft.d.ts +14 -0
  32. package/dist/host/draft.d.ts.map +1 -0
  33. package/dist/host/draft.js +124 -0
  34. package/dist/host/draft.js.map +1 -0
  35. package/dist/host/engine.d.ts +14 -0
  36. package/dist/host/engine.d.ts.map +1 -0
  37. package/dist/host/engine.js +17 -0
  38. package/dist/host/engine.js.map +1 -0
  39. package/dist/host/host.d.ts +79 -0
  40. package/dist/host/host.d.ts.map +1 -0
  41. package/dist/host/host.js +303 -0
  42. package/dist/host/host.js.map +1 -0
  43. package/dist/index.d.ts +28 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +6 -0
  46. package/dist/server.d.ts +15 -0
  47. package/dist/server.d.ts.map +1 -0
  48. package/dist/server.js +3 -0
  49. package/dist/statewire.d.ts +20 -0
  50. package/dist/statewire.d.ts.map +1 -0
  51. package/dist/statewire.js +65 -0
  52. package/dist/statewire.js.map +1 -0
  53. package/dist/transports/remote.d.ts +19 -0
  54. package/dist/transports/remote.d.ts.map +1 -0
  55. package/dist/transports/remote.js +40 -0
  56. package/dist/transports/remote.js.map +1 -0
  57. package/dist/transports/sse-parser.d.ts +5 -0
  58. package/dist/transports/sse-parser.d.ts.map +1 -0
  59. package/dist/transports/sse-parser.js +26 -0
  60. package/dist/transports/sse-parser.js.map +1 -0
  61. package/dist/transports/sse.d.ts +74 -0
  62. package/dist/transports/sse.d.ts.map +1 -0
  63. package/dist/transports/sse.js +136 -0
  64. package/dist/transports/sse.js.map +1 -0
  65. package/dist/transports/testing.d.ts +31 -0
  66. package/dist/transports/testing.d.ts.map +1 -0
  67. package/dist/transports/testing.js +121 -0
  68. package/dist/transports/testing.js.map +1 -0
  69. package/dist/transports/ws.d.ts +18 -0
  70. package/dist/transports/ws.d.ts.map +1 -0
  71. package/dist/transports/ws.js +172 -0
  72. package/dist/transports/ws.js.map +1 -0
  73. package/dist/types.d.ts +107 -0
  74. package/dist/types.d.ts.map +1 -0
  75. package/dist/types.js +24 -0
  76. package/dist/types.js.map +1 -0
  77. package/dist/wire/meta.d.ts +22 -0
  78. package/dist/wire/meta.d.ts.map +1 -0
  79. package/dist/wire/meta.js +73 -0
  80. package/dist/wire/meta.js.map +1 -0
  81. package/dist/wire/ops.d.ts +40 -0
  82. package/dist/wire/ops.d.ts.map +1 -0
  83. package/dist/wire/ops.js +125 -0
  84. package/dist/wire/ops.js.map +1 -0
  85. package/package.json +49 -6
  86. package/src/client/changes.ts +48 -0
  87. package/src/client/connection.ts +327 -0
  88. package/src/client/core.ts +346 -0
  89. package/src/client/optimistic.ts +0 -0
  90. package/src/client/session.ts +679 -0
  91. package/src/client/sessionStore.ts +23 -0
  92. package/src/client/timing.ts +8 -0
  93. package/src/host/draft.ts +155 -0
  94. package/src/host/engine.ts +13 -0
  95. package/src/host/host.ts +481 -0
  96. package/src/index.ts +65 -0
  97. package/src/server.ts +32 -0
  98. package/src/statewire.ts +107 -0
  99. package/src/transports/remote.ts +72 -0
  100. package/src/transports/sse-parser.ts +24 -0
  101. package/src/transports/sse.ts +280 -0
  102. package/src/transports/testing.ts +155 -0
  103. package/src/transports/ws.ts +272 -0
  104. package/src/types.ts +169 -0
  105. package/src/wire/meta.ts +106 -0
  106. package/src/wire/ops.ts +201 -0
  107. package/index.js +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft.d.ts","names":[],"sources":["../../src/host/draft.ts"],"mappings":";;KAEY,WAAW,QAAQ;EAAe;;KAElC;EACV;EACA,SAAS,IAAI;;cAGF,SAAU;cA6BV,mBAAoB,GAC/B,MAAM,WACN,OAAM,kBACL"}
@@ -0,0 +1,124 @@
1
+ //#region src/host/draft.ts
2
+ const frozen = (value) => {
3
+ if (value instanceof Date) return new Date(value.getTime());
4
+ if (Array.isArray(value)) return value.map((item) => frozen(item) ?? null);
5
+ if (typeof value === "object" && value !== null) {
6
+ const out = {};
7
+ for (const key of Object.keys(value)) {
8
+ const item = frozen(value[key]);
9
+ if (item !== void 0) out[key] = item;
10
+ }
11
+ return out;
12
+ }
13
+ return typeof value === "function" ? void 0 : value;
14
+ };
15
+ const lookup = (root, path) => {
16
+ let node = root;
17
+ for (const key of path) node = node[key];
18
+ return node;
19
+ };
20
+ const isIndex = (key) => /^(0|[1-9]\d*)$/.test(key);
21
+ const invalid = (path, message) => /* @__PURE__ */ new Error(`statewire: ${message} at path: ${path.join(".")}`);
22
+ const createStateDraft = (host, path = []) => {
23
+ const node = () => lookup(host.root(), path);
24
+ const assign = (container, key, value) => {
25
+ const old = Object.hasOwn(container, key) ? container[key] : void 0;
26
+ if (old === value) return;
27
+ if (typeof old === "string" && typeof value === "string" && value.startsWith(old)) {
28
+ host.record({
29
+ op: "append",
30
+ path: [...path, key],
31
+ value: value.slice(old.length)
32
+ });
33
+ return;
34
+ }
35
+ host.record({
36
+ op: "replace",
37
+ path: [...path, key],
38
+ value
39
+ });
40
+ };
41
+ return new Proxy(node(), {
42
+ get: (_target, prop) => {
43
+ const current = node();
44
+ if (typeof prop === "symbol") return current[prop];
45
+ const key = Array.isArray(current) && isIndex(prop) ? Number(prop) : prop;
46
+ const value = current[key];
47
+ if (typeof value === "object" && value !== null) return createStateDraft(host, [...path, key]);
48
+ return value;
49
+ },
50
+ set: (_target, prop, rawValue) => {
51
+ if (typeof prop === "symbol") return false;
52
+ const current = node();
53
+ const value = frozen(rawValue);
54
+ if (Array.isArray(current)) {
55
+ if (prop === "length") {
56
+ const next = Number(value);
57
+ if (!Number.isInteger(next) || next < 0 || next > current.length) throw invalid(path, `cannot set list length to ${String(value)}`);
58
+ for (let i = current.length - 1; i >= next; i--) host.record({
59
+ op: "remove",
60
+ path: [...path, i]
61
+ });
62
+ return true;
63
+ }
64
+ if (!isIndex(prop)) throw invalid(path, `cannot set key "${prop}" on a list`);
65
+ const index = Number(prop);
66
+ if (index > current.length) throw invalid(path, `list index ${index} out of range`);
67
+ if (index === current.length) {
68
+ host.record({
69
+ op: "add",
70
+ path: [...path, index],
71
+ value
72
+ });
73
+ return true;
74
+ }
75
+ assign(current, index, value);
76
+ return true;
77
+ }
78
+ assign(current, prop, value);
79
+ return true;
80
+ },
81
+ deleteProperty: (_target, prop) => {
82
+ if (typeof prop === "symbol") return false;
83
+ const current = node();
84
+ if (Array.isArray(current)) {
85
+ if (!isIndex(prop) || Number(prop) >= current.length) return true;
86
+ host.record({
87
+ op: "remove",
88
+ path: [...path, Number(prop)]
89
+ });
90
+ return true;
91
+ }
92
+ if (!Object.hasOwn(current, prop)) return true;
93
+ host.record({
94
+ op: "remove",
95
+ path: [...path, prop]
96
+ });
97
+ return true;
98
+ },
99
+ defineProperty: () => {
100
+ throw new Error("statewire: defineProperty is not supported on a state draft");
101
+ },
102
+ setPrototypeOf: () => {
103
+ throw new Error("statewire: setPrototypeOf is not supported on a state draft");
104
+ },
105
+ preventExtensions: () => {
106
+ throw new Error("statewire: preventExtensions is not supported on a state draft");
107
+ },
108
+ has: (_target, prop) => Reflect.has(node(), prop),
109
+ ownKeys: () => Reflect.ownKeys(node()),
110
+ getOwnPropertyDescriptor: (_target, prop) => {
111
+ const current = node();
112
+ const desc = Reflect.getOwnPropertyDescriptor(current, prop);
113
+ if (!desc) return void 0;
114
+ return {
115
+ ...desc,
116
+ configurable: !Array.isArray(current) || prop !== "length"
117
+ };
118
+ }
119
+ });
120
+ };
121
+ //#endregion
122
+ export { createStateDraft, frozen };
123
+
124
+ //# sourceMappingURL=draft.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft.js","names":["StatewireOp","StatewirePath","ServerOp","Exclude","op","DraftHost","root","record","frozen","value","Date","getTime","Array","isArray","map","item","out","Record","key","Object","keys","undefined","lookup","path","node","isIndex","test","invalid","message","Error","join","createStateDraft","host","T","assign","container","old","hasOwn","startsWith","slice","length","Proxy","get","_target","prop","current","Number","set","rawValue","next","isInteger","String","i","index","deleteProperty","defineProperty","setPrototypeOf","preventExtensions","has","Reflect","ownKeys","getOwnPropertyDescriptor","desc","configurable"],"sources":["../../src/host/draft.ts"],"sourcesContent":["import type { StatewireOp, StatewirePath } from \"../wire/ops\";\n\nexport type ServerOp = Exclude<StatewireOp, { op: \"event\" }>;\n\nexport type DraftHost = {\n root: () => unknown;\n record: (op: ServerOp) => void;\n};\n\nexport const frozen = (value: unknown): unknown => {\n if (value instanceof Date) return new Date(value.getTime());\n if (Array.isArray(value)) {\n return value.map((item) => frozen(item) ?? null);\n }\n if (typeof value === \"object\" && value !== null) {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n const item = frozen((value as Record<string, unknown>)[key]);\n if (item !== undefined) out[key] = item;\n }\n return out;\n }\n return typeof value === \"function\" ? undefined : value;\n};\n\nconst lookup = (root: unknown, path: StatewirePath): unknown => {\n let node = root;\n for (const key of path) {\n node = (node as Record<string | number, unknown>)[key];\n }\n return node;\n};\n\nconst isIndex = (key: string) => /^(0|[1-9]\\d*)$/.test(key);\n\nconst invalid = (path: StatewirePath, message: string) =>\n new Error(`statewire: ${message} at path: ${path.join(\".\")}`);\n\nexport const createStateDraft = <T>(\n host: DraftHost,\n path: StatewirePath = [],\n): T => {\n const node = () => lookup(host.root(), path);\n\n const assign = (\n container: Record<string | number, unknown>,\n key: string | number,\n value: unknown,\n ) => {\n const old = Object.hasOwn(container, key) ? container[key] : undefined;\n if (old === value) return;\n if (\n typeof old === \"string\" &&\n typeof value === \"string\" &&\n value.startsWith(old)\n ) {\n host.record({\n op: \"append\",\n path: [...path, key],\n value: value.slice(old.length),\n });\n return;\n }\n host.record({ op: \"replace\", path: [...path, key], value });\n };\n\n return new Proxy(node() as object, {\n get: (_target, prop) => {\n const current = node() as Record<string | number, unknown>;\n if (typeof prop === \"symbol\") {\n return (current as unknown as Record<symbol, unknown>)[prop];\n }\n const key = Array.isArray(current) && isIndex(prop) ? Number(prop) : prop;\n const value = current[key];\n if (typeof value === \"object\" && value !== null) {\n return createStateDraft(host, [...path, key]);\n }\n return value;\n },\n set: (_target, prop, rawValue) => {\n if (typeof prop === \"symbol\") return false;\n const current = node();\n const value = frozen(rawValue);\n if (Array.isArray(current)) {\n if (prop === \"length\") {\n const next = Number(value);\n if (!Number.isInteger(next) || next < 0 || next > current.length) {\n throw invalid(path, `cannot set list length to ${String(value)}`);\n }\n for (let i = current.length - 1; i >= next; i--) {\n host.record({ op: \"remove\", path: [...path, i] });\n }\n return true;\n }\n if (!isIndex(prop)) {\n throw invalid(path, `cannot set key \"${prop}\" on a list`);\n }\n const index = Number(prop);\n if (index > current.length) {\n throw invalid(path, `list index ${index} out of range`);\n }\n if (index === current.length) {\n host.record({ op: \"add\", path: [...path, index], value });\n return true;\n }\n assign(\n current as unknown as Record<string | number, unknown>,\n index,\n value,\n );\n return true;\n }\n assign(current as Record<string, unknown>, prop, value);\n return true;\n },\n deleteProperty: (_target, prop) => {\n if (typeof prop === \"symbol\") return false;\n const current = node();\n if (Array.isArray(current)) {\n if (!isIndex(prop) || Number(prop) >= current.length) return true;\n host.record({ op: \"remove\", path: [...path, Number(prop)] });\n return true;\n }\n if (!Object.hasOwn(current as object, prop)) return true;\n host.record({ op: \"remove\", path: [...path, prop] });\n return true;\n },\n defineProperty: () => {\n throw new Error(\n \"statewire: defineProperty is not supported on a state draft\",\n );\n },\n setPrototypeOf: () => {\n throw new Error(\n \"statewire: setPrototypeOf is not supported on a state draft\",\n );\n },\n preventExtensions: () => {\n throw new Error(\n \"statewire: preventExtensions is not supported on a state draft\",\n );\n },\n has: (_target, prop) => Reflect.has(node() as object, prop),\n ownKeys: () => Reflect.ownKeys(node() as object),\n getOwnPropertyDescriptor: (_target, prop) => {\n const current = node() as object;\n const desc = Reflect.getOwnPropertyDescriptor(current, prop);\n if (!desc) return undefined;\n return {\n ...desc,\n configurable: !Array.isArray(current) || prop !== \"length\",\n };\n },\n }) as T;\n};\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ //#region src/host/engine.d.ts
2
+ /**
3
+ * Definitive handler rejection: the command settles rejected and
4
+ * message/payload travel to the client's rejected promise.
5
+ */
6
+ declare class StatewireReject extends Error {
7
+ readonly payload?: unknown;
8
+ constructor(message: string, options?: {
9
+ payload?: unknown;
10
+ });
11
+ }
12
+ //#endregion
13
+ export { StatewireReject };
14
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","names":[],"sources":["../../src/host/engine.ts"],"mappings":";;;;;cAIa,wBAAwB;WAC1B;EAEG,YAAA,iBAAiB;IAAY"}
@@ -0,0 +1,17 @@
1
+ //#region src/host/engine.ts
2
+ /**
3
+ * Definitive handler rejection: the command settles rejected and
4
+ * message/payload travel to the client's rejected promise.
5
+ */
6
+ var StatewireReject = class extends Error {
7
+ payload;
8
+ constructor(message, options) {
9
+ super(message);
10
+ this.name = "StatewireReject";
11
+ if (options?.payload !== void 0) this.payload = options.payload;
12
+ }
13
+ };
14
+ //#endregion
15
+ export { StatewireReject };
16
+
17
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","names":["StatewireReject","Error","payload","constructor","message","options","name","undefined"],"sources":["../../src/host/engine.ts"],"sourcesContent":["/**\n * Definitive handler rejection: the command settles rejected and\n * message/payload travel to the client's rejected promise.\n */\nexport class StatewireReject extends Error {\n readonly payload?: unknown;\n\n constructor(message: string, options?: { payload?: unknown }) {\n super(message);\n this.name = \"StatewireReject\";\n if (options?.payload !== undefined) this.payload = options.payload;\n }\n}\n"],"mappings":";;;;;AAIA,IAAaA,kBAAb,cAAqCC,MAAM;CACzC;CAEAE,YAAYC,SAAiBC,SAAiC;EAC5D,MAAMD,OAAO;EACb,KAAKE,OAAO;EACZ,IAAID,SAASH,YAAYK,KAAAA,GAAW,KAAKL,UAAUG,QAAQH;CAC7D;AACF"}
@@ -0,0 +1,79 @@
1
+ import { StatewireOp } from "../wire/ops.js";
2
+ import { StatewireCommands, StatewireCommandsProxy, StatewireStateSource } from "../types.js";
3
+ import { ServerOp } from "./draft.js";
4
+ //#region src/host/host.d.ts
5
+ type StatewireStateCtl = {
6
+ /** Apply server-vocabulary ops (root replace = whole-state swap). */
7
+ apply: (ops: readonly StatewireOp[]) => void;
8
+ };
9
+ type StateHost = StatewireStateSource & {
10
+ /** Synchronous, per locally-recorded op; the host owns batching. */
11
+ setOnOp: (listener: ((op: ServerOp) => void) | null) => void;
12
+ };
13
+ declare const getStateHost: (state: object) => StateHost | undefined;
14
+ declare const useStatewireState: <TState>(init: () => TState) => readonly [TState, StatewireStateCtl];
15
+ declare const executionResult: unique symbol;
16
+ /**
17
+ * Handle a command handler returns to keep the command open past its own
18
+ * return: `ack()` releases the client's optimistic overlay / ack watermark,
19
+ * `resolve`/`reject` settle the command (and imply ack). `ack` is idempotent
20
+ * and a no-op after settle.
21
+ */
22
+ type CommandExecution<T = void> = {
23
+ readonly [executionResult]: (value: T) => void;
24
+ };
25
+ type CommandExecutionResolvers<T = void> = {
26
+ ack: () => void;
27
+ resolve: (value: T) => void;
28
+ reject: (error: unknown) => void;
29
+ };
30
+ /**
31
+ * `CommandExecution(executor)` runs the (possibly async) `executor({ ack })`
32
+ * immediately: its return value resolves the execution, a throw/rejection
33
+ * rejects it; `ack()` releases the client's ack watermark before the executor
34
+ * finishes. `CommandExecution.withResolvers()` returns `[execution,
35
+ * { ack, resolve, reject }]` instead — settle them from your own spawned work.
36
+ */
37
+ declare const CommandExecution: (<T = void>(executor: (resolvers: {
38
+ ack: () => void;
39
+ }) => T | void | PromiseLike<T | void>) => CommandExecution<T>) & {
40
+ withResolvers: <T = void>() => [CommandExecution<T>, CommandExecutionResolvers<T>];
41
+ };
42
+ type CommandsInvocation = {
43
+ readonly method: string;
44
+ readonly params: readonly unknown[];
45
+ readonly ts: number;
46
+ readonly seq: number;
47
+ readonly clientId?: string;
48
+ };
49
+ type CommandsOutcome = {
50
+ type: "accepted";
51
+ payload?: unknown;
52
+ } | {
53
+ type: "rejected";
54
+ error: unknown;
55
+ };
56
+ type CommandsListener = {
57
+ onStart: (inv: CommandsInvocation) => void;
58
+ onPosted?: (inv: CommandsInvocation) => void;
59
+ onAck: (inv: CommandsInvocation) => void;
60
+ /** Canonical state now covers the invocation's effect — drop any overlay. */
61
+ onCovered?: (inv: CommandsInvocation) => void;
62
+ onSettle: (inv: CommandsInvocation, outcome: CommandsOutcome) => void;
63
+ };
64
+ type CommandsHost = {
65
+ setListener: (listener: CommandsListener | null) => void;
66
+ };
67
+ declare const getCommandsHost: (commands: object) => CommandsHost | undefined;
68
+ declare const bindCommandsHost: (commands: object, host: CommandsHost) => void;
69
+ type UnwrapExecution<V> = V extends CommandExecution<infer T> ? T : V;
70
+ type StatewireHandledCommands<THandlers extends StatewireCommands> = { [K in keyof THandlers]: (...args: Parameters<THandlers[K]>) => UnwrapExecution<Awaited<ReturnType<THandlers[K]>>>; };
71
+ declare const useStatewireCommands: <THandlers extends StatewireCommands>(commands: THandlers | undefined | null | false) => StatewireCommandsProxy<StatewireHandledCommands<THandlers>>;
72
+ type EmitHost = {
73
+ setSink: (sink: ((event: unknown) => void) | null) => void;
74
+ };
75
+ declare const getEmitHost: (emit: object) => EmitHost | undefined;
76
+ declare const useStatewireEmit: <TEvent>() => ((event: TEvent) => void);
77
+ //#endregion
78
+ export { CommandExecution, CommandExecutionResolvers, CommandsHost, CommandsInvocation, CommandsListener, CommandsOutcome, EmitHost, StateHost, StatewireHandledCommands, StatewireStateCtl, bindCommandsHost, getCommandsHost, getEmitHost, getStateHost, useStatewireCommands, useStatewireEmit, useStatewireState };
79
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","names":[],"sources":["../../src/host/host.ts"],"mappings":";;;;KAkBY;;EAEV,QAAQ,cAAc;;KAGZ,YAAY;;EAEtB,UAAU,YAAY,IAAI;;cAKf,eAAgB,kBAAgB;cAchC,oBAAqB,QAChC,YAAY,qBACD,QAAQ;cAgFP;;;;;;;KAQF,iBAAiB;YACjB,mBAAmB,OAAO;;KAG1B,0BAA0B;EACpC;EACA,UAAU,OAAO;EACjB,SAAS;;;;;;;;;cAUE,oBACV,UAAC,WACW;EACT;MACI,WAAW,YAAY,cAC5B,iBAAiB;EAyBF,gBAAA,gBACd,iBAAiB,IACjB,0BAA0B;;KAkBpB;WACD;WACA;WACA;WACA;WACA;;KAGC;EACN;EAAkB;;EAClB;EAAkB;;KAEZ;EACV,UAAU,KAAK;EACf,YAAY,KAAK;EACjB,QAAQ,KAAK;;EAEb,aAAa,KAAK;EAClB,WAAW,KAAK,oBAAoB,SAAS;;KAGnC;EACV,cAAc,UAAU;;cAKb,kBAAmB,qBAAmB;cAGtC,mBAAoB,kBAAkB,MAAM;KAsIpD,gBAAgB,KAAK,UAAU,uBAAuB,KAAK,IAAI;KAExD,yBAAyB,kBAAkB,wBACpD,WAAW,gBACP,MAAM,WAAW,UAAU,QAC3B,gBAAgB,QAAQ,WAAW,UAAU;cAGvC,uBAAwB,kBAAkB,mBACrD,UAAU,yCACT,uBAAuB,yBAAyB;KA+EvC;EACV,UAAU,QAAQ;;cAKP,cAAe,iBAAe;cAG9B,mBAAoB,eAAa,OAAO"}
@@ -0,0 +1,303 @@
1
+ import { applyOp, applyOps } from "../wire/ops.js";
2
+ import { StatewireReject } from "./engine.js";
3
+ import { createStateDraft, frozen } from "./draft.js";
4
+ import { StatewireSendError } from "../types.js";
5
+ import { useEffect, useState } from "@assistant-ui/tap/react-shim";
6
+ //#region src/host/host.ts
7
+ const isDev = () => typeof process === "undefined" || process.env["NODE_ENV"] !== "production";
8
+ const stateHosts = /* @__PURE__ */ new WeakMap();
9
+ const getStateHost = (state) => stateHosts.get(state);
10
+ const useStatewireState = (init) => {
11
+ const [, setVersion] = useState(0);
12
+ const [cell] = useState(() => {
13
+ const c = {
14
+ current: frozen(init()),
15
+ draft: null,
16
+ changed: [[]],
17
+ onOp: null,
18
+ onChange: null,
19
+ bump: () => setVersion((v) => v + 1),
20
+ ctl: { apply: (ops) => {
21
+ const result = applyOps(c.current, ops);
22
+ if (result.events.length > 0) throw new Error("statewire: event ops do not apply to state — route them to emit");
23
+ c.current = result.state;
24
+ c.changed.push(...result.changedPaths);
25
+ c.bump();
26
+ c.onChange?.();
27
+ } },
28
+ host: {
29
+ root: () => c.current,
30
+ setOnOp: (listener) => {
31
+ c.onOp = listener;
32
+ },
33
+ setOnChange: (listener_0) => {
34
+ c.onChange = listener_0;
35
+ },
36
+ takeChanged: () => {
37
+ const changed = c.changed;
38
+ c.changed = [];
39
+ return changed;
40
+ }
41
+ }
42
+ };
43
+ return c;
44
+ });
45
+ let value = cell.current;
46
+ if (typeof value === "object" && value !== null) {
47
+ cell.draft ??= createStateDraft({
48
+ root: () => cell.current,
49
+ record: (op) => {
50
+ const applied = applyOp(cell.current, op);
51
+ cell.current = applied.state;
52
+ cell.changed.push(...applied.changedPaths);
53
+ cell.onOp?.(op);
54
+ cell.bump();
55
+ cell.onChange?.();
56
+ }
57
+ });
58
+ stateHosts.set(cell.draft, cell.host);
59
+ value = cell.draft;
60
+ }
61
+ return [value, cell.ctl];
62
+ };
63
+ const executionStates = /* @__PURE__ */ new WeakMap();
64
+ /**
65
+ * `CommandExecution(executor)` runs the (possibly async) `executor({ ack })`
66
+ * immediately: its return value resolves the execution, a throw/rejection
67
+ * rejects it; `ack()` releases the client's ack watermark before the executor
68
+ * finishes. `CommandExecution.withResolvers()` returns `[execution,
69
+ * { ack, resolve, reject }]` instead — settle them from your own spawned work.
70
+ */
71
+ const CommandExecution = Object.assign((executor) => {
72
+ const state = {
73
+ acked: false,
74
+ settled: null,
75
+ bind: null
76
+ };
77
+ const execution = Object.freeze({});
78
+ executionStates.set(execution, state);
79
+ const settle = (settled) => {
80
+ if (state.settled) return;
81
+ state.settled = settled;
82
+ state.acked = true;
83
+ state.bind?.onSettle(settled);
84
+ };
85
+ const ack = () => {
86
+ if (state.acked) return;
87
+ state.acked = true;
88
+ state.bind?.onAck();
89
+ };
90
+ (async () => {
91
+ try {
92
+ settle({
93
+ type: "resolved",
94
+ value: await executor({ ack })
95
+ });
96
+ } catch (error) {
97
+ settle({
98
+ type: "rejected",
99
+ error
100
+ });
101
+ }
102
+ })();
103
+ return execution;
104
+ }, { withResolvers: () => {
105
+ let resolve;
106
+ let reject;
107
+ const promise = new Promise((res, rej) => {
108
+ resolve = res;
109
+ reject = rej;
110
+ });
111
+ let ack;
112
+ return [CommandExecution(({ ack: a }) => {
113
+ ack = a;
114
+ return promise;
115
+ }), {
116
+ ack: () => ack(),
117
+ resolve,
118
+ reject
119
+ }];
120
+ } });
121
+ const commandsHosts = /* @__PURE__ */ new WeakMap();
122
+ const getCommandsHost = (commands) => commandsHosts.get(commands);
123
+ const bindCommandsHost = (commands, host) => {
124
+ commandsHosts.set(commands, host);
125
+ };
126
+ const STALL_WARN_MS = 5e3;
127
+ const toSendError = (error) => error instanceof StatewireSendError ? error : new StatewireSendError({
128
+ fate: "rejected",
129
+ cause: "server",
130
+ message: error instanceof Error ? error.message : String(error),
131
+ ...error instanceof StatewireReject && error.payload !== void 0 && { payload: error.payload }
132
+ });
133
+ const ackInvocation = (cell, inv) => {
134
+ if (inv.acked) return;
135
+ inv.acked = true;
136
+ cell.listener?.onAck(inv);
137
+ };
138
+ const settleInvocation = (cell, inv, call, settled) => {
139
+ ackInvocation(cell, inv);
140
+ if (settled.type === "resolved") {
141
+ const outcome = settled.value === void 0 ? { type: "accepted" } : {
142
+ type: "accepted",
143
+ payload: frozen(settled.value)
144
+ };
145
+ cell.listener?.onSettle(inv, outcome);
146
+ call.resolve(outcome.payload);
147
+ } else {
148
+ const error = toSendError(settled.error);
149
+ cell.listener?.onSettle(inv, {
150
+ type: "rejected",
151
+ error
152
+ });
153
+ call.reject(error);
154
+ }
155
+ };
156
+ const pump = (cell) => {
157
+ if (cell.running || !cell.handlers) {
158
+ watchStall(cell);
159
+ return;
160
+ }
161
+ const call = cell.queue.shift();
162
+ if (!call) return;
163
+ const handler = cell.handlers[call.method];
164
+ if (handler === void 0) {
165
+ call.reject(new StatewireSendError({
166
+ fate: "unknown-command",
167
+ cause: "server"
168
+ }));
169
+ pump(cell);
170
+ return;
171
+ }
172
+ const inv = {
173
+ method: call.method,
174
+ params: call.params,
175
+ ts: call.ts,
176
+ seq: ++cell.seq,
177
+ acked: false
178
+ };
179
+ cell.running = true;
180
+ cell.listener?.onStart(inv);
181
+ cell.listener?.onPosted?.(inv);
182
+ cell.listener?.onCovered?.(inv);
183
+ (async () => {
184
+ try {
185
+ const value = await handler(...call.params);
186
+ const execution = typeof value === "object" && value !== null ? executionStates.get(value) : void 0;
187
+ if (execution) {
188
+ if (execution.acked) ackInvocation(cell, inv);
189
+ if (execution.settled) settleInvocation(cell, inv, call, execution.settled);
190
+ else execution.bind = {
191
+ onAck: () => ackInvocation(cell, inv),
192
+ onSettle: (settled) => settleInvocation(cell, inv, call, settled)
193
+ };
194
+ } else settleInvocation(cell, inv, call, {
195
+ type: "resolved",
196
+ value
197
+ });
198
+ } catch (error) {
199
+ settleInvocation(cell, inv, call, {
200
+ type: "rejected",
201
+ error
202
+ });
203
+ } finally {
204
+ cell.running = false;
205
+ pump(cell);
206
+ }
207
+ })();
208
+ };
209
+ const watchStall = (cell) => {
210
+ if (!isDev() || cell.stallTimer !== null || cell.queue.length === 0) return;
211
+ if (cell.handlers) return;
212
+ cell.stallTimer = setTimeout(() => {
213
+ cell.stallTimer = null;
214
+ if (cell.handlers === null && cell.queue.length > 0 && !cell.unmounted) console.warn(`statewire: ${cell.queue.length} buffered command(s) waiting over ${STALL_WARN_MS}ms — did the host forget to arm useStatewireCommands?`);
215
+ }, STALL_WARN_MS);
216
+ };
217
+ const useStatewireCommands = (commands) => {
218
+ const [built] = useState(() => {
219
+ const cell = {
220
+ handlers: null,
221
+ queue: [],
222
+ running: false,
223
+ listener: null,
224
+ seq: 0,
225
+ unmounted: false,
226
+ stallTimer: null
227
+ };
228
+ const memo = /* @__PURE__ */ new Map();
229
+ const proxy = new Proxy({}, { get: (_target, method) => {
230
+ if (typeof method !== "string") return void 0;
231
+ let fn = memo.get(method);
232
+ if (fn === void 0) {
233
+ fn = (...params) => new Promise((resolve, reject) => {
234
+ if (cell.unmounted) {
235
+ reject(/* @__PURE__ */ new Error("statewire: commands called after unmount"));
236
+ return;
237
+ }
238
+ cell.queue.push({
239
+ method,
240
+ params,
241
+ ts: Date.now(),
242
+ resolve,
243
+ reject
244
+ });
245
+ pump(cell);
246
+ });
247
+ memo.set(method, fn);
248
+ }
249
+ return fn;
250
+ } });
251
+ commandsHosts.set(proxy, { setListener: (listener) => {
252
+ cell.listener = listener;
253
+ } });
254
+ return {
255
+ cell,
256
+ proxy
257
+ };
258
+ });
259
+ useEffect(() => {
260
+ const { cell: cell_0 } = built;
261
+ cell_0.unmounted = false;
262
+ return () => {
263
+ cell_0.unmounted = true;
264
+ cell_0.handlers = null;
265
+ if (cell_0.stallTimer !== null) {
266
+ clearTimeout(cell_0.stallTimer);
267
+ cell_0.stallTimer = null;
268
+ }
269
+ queueMicrotask(() => {
270
+ if (!cell_0.unmounted) return;
271
+ const queued = cell_0.queue;
272
+ cell_0.queue = [];
273
+ for (const call of queued) call.reject(/* @__PURE__ */ new Error("statewire: unmounted"));
274
+ });
275
+ };
276
+ }, [built]);
277
+ useEffect(() => {
278
+ built.cell.handlers = commands || null;
279
+ pump(built.cell);
280
+ });
281
+ return built.proxy;
282
+ };
283
+ const emitHosts = /* @__PURE__ */ new WeakMap();
284
+ const getEmitHost = (emit) => emitHosts.get(emit);
285
+ const useStatewireEmit = () => {
286
+ const [built] = useState(_temp);
287
+ return built;
288
+ };
289
+ function _temp() {
290
+ const cell = { sink: null };
291
+ const emit = (event) => {
292
+ if (!cell.sink) throw new Error("statewire: emit before a host bound the event sink");
293
+ cell.sink(frozen(event));
294
+ };
295
+ emitHosts.set(emit, { setSink: (sink) => {
296
+ cell.sink = sink;
297
+ } });
298
+ return emit;
299
+ }
300
+ //#endregion
301
+ export { CommandExecution, bindCommandsHost, getCommandsHost, getEmitHost, getStateHost, useStatewireCommands, useStatewireEmit, useStatewireState };
302
+
303
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","names":["useEffect","useState","applyOp","applyOps","StatewireOp","StatewirePath","StatewireReject","createStateDraft","frozen","ServerOp","StatewireSendError","StatewireCommands","StatewireCommandsProxy","StatewireStateSource","isDev","process","env","StatewireStateCtl","apply","ops","StateHost","setOnOp","listener","op","stateHosts","WeakMap","getStateHost","state","get","StateCell","current","draft","changed","onOp","onChange","ctl","host","bump","useStatewireState","init","TState","setVersion","cell","c","v","result","events","length","Error","push","changedPaths","root","setOnChange","takeChanged","value","record","applied","set","const","ExecutionSettled","type","error","ExecutionBind","onAck","onSettle","settled","ExecutionState","acked","bind","executionStates","executionResult","CommandExecution","T","CommandExecutionResolvers","ack","resolve","reject","Object","assign","executor","resolvers","PromiseLike","execution","freeze","settle","withResolvers","promise","Promise","res","rej","a","CommandsInvocation","method","params","ts","seq","clientId","CommandsOutcome","payload","CommandsListener","onStart","inv","onPosted","onCovered","outcome","CommandsHost","setListener","commandsHosts","getCommandsHost","commands","bindCommandsHost","QueuedCall","ActiveInvocation","CommandsCell","handlers","Record","args","queue","running","unmounted","stallTimer","ReturnType","setTimeout","STALL_WARN_MS","toSendError","fate","cause","message","String","undefined","ackInvocation","settleInvocation","call","pump","watchStall","shift","handler","console","warn","UnwrapExecution","V","StatewireHandledCommands","THandlers","Parameters","K","Awaited","useStatewireCommands","built","memo","Map","proxy","Proxy","_target","fn","Date","now","clearTimeout","queueMicrotask","queued","EmitHost","setSink","sink","event","emitHosts","getEmitHost","emit","useStatewireEmit","_temp"],"sources":["../../src/host/host.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { applyOp, applyOps } from \"../wire/ops\";\nimport type { StatewireOp, StatewirePath } from \"../wire/ops\";\nimport { StatewireReject } from \"./engine\";\nimport { createStateDraft, frozen } from \"./draft\";\nimport type { ServerOp } from \"./draft\";\nimport { StatewireSendError } from \"../types\";\nimport type {\n StatewireCommands,\n StatewireCommandsProxy,\n StatewireStateSource,\n} from \"../types\";\n\nconst isDev = () =>\n typeof process === \"undefined\" || process.env[\"NODE_ENV\"] !== \"production\";\n\n// ─── state ──────────────────────────────────────────────\n\nexport type StatewireStateCtl = {\n /** Apply server-vocabulary ops (root replace = whole-state swap). */\n apply: (ops: readonly StatewireOp[]) => void;\n};\n\nexport type StateHost = StatewireStateSource & {\n /** Synchronous, per locally-recorded op; the host owns batching. */\n setOnOp: (listener: ((op: ServerOp) => void) | null) => void;\n};\n\nconst stateHosts = new WeakMap<object, StateHost>();\n\nexport const getStateHost = (state: object): StateHost | undefined =>\n stateHosts.get(state);\n\ntype StateCell = {\n current: unknown;\n draft: object | null;\n changed: StatewirePath[];\n onOp: ((op: ServerOp) => void) | null;\n onChange: (() => void) | null;\n ctl: StatewireStateCtl;\n host: StateHost;\n bump: () => void;\n};\n\nexport const useStatewireState = <TState>(\n init: () => TState,\n): readonly [TState, StatewireStateCtl] => {\n const [, setVersion] = useState(0);\n const [cell] = useState((): StateCell => {\n const c: StateCell = {\n current: frozen(init()),\n draft: null,\n changed: [[]],\n onOp: null,\n onChange: null,\n bump: () => setVersion((v) => v + 1),\n ctl: {\n apply: (ops) => {\n const result = applyOps(c.current, ops);\n if (result.events.length > 0) {\n throw new Error(\n \"statewire: event ops do not apply to state — route them to emit\",\n );\n }\n c.current = result.state;\n c.changed.push(...result.changedPaths);\n c.bump();\n c.onChange?.();\n },\n },\n host: {\n root: () => c.current,\n setOnOp: (listener) => {\n c.onOp = listener;\n },\n setOnChange: (listener) => {\n c.onChange = listener;\n },\n takeChanged: () => {\n const changed = c.changed;\n c.changed = [];\n return changed;\n },\n },\n };\n return c;\n });\n\n let value = cell.current;\n if (typeof value === \"object\" && value !== null) {\n cell.draft ??= createStateDraft<object>({\n root: () => cell.current,\n record: (op) => {\n const applied = applyOp(cell.current, op);\n cell.current = applied.state;\n cell.changed.push(...applied.changedPaths);\n cell.onOp?.(op);\n cell.bump();\n cell.onChange?.();\n },\n });\n stateHosts.set(cell.draft, cell.host);\n value = cell.draft;\n }\n return [value as TState, cell.ctl] as const;\n};\n\n// ─── commands ───────────────────────────────────────────\n\ntype ExecutionSettled =\n | { type: \"resolved\"; value: unknown }\n | { type: \"rejected\"; error: unknown };\n\ntype ExecutionBind = {\n onAck: () => void;\n onSettle: (settled: ExecutionSettled) => void;\n};\n\ntype ExecutionState = {\n acked: boolean;\n settled: ExecutionSettled | null;\n bind: ExecutionBind | null;\n};\n\nconst executionStates = new WeakMap<object, ExecutionState>();\n\ndeclare const executionResult: unique symbol;\n\n/**\n * Handle a command handler returns to keep the command open past its own\n * return: `ack()` releases the client's optimistic overlay / ack watermark,\n * `resolve`/`reject` settle the command (and imply ack). `ack` is idempotent\n * and a no-op after settle.\n */\nexport type CommandExecution<T = void> = {\n readonly [executionResult]: (value: T) => void;\n};\n\nexport type CommandExecutionResolvers<T = void> = {\n ack: () => void;\n resolve: (value: T) => void;\n reject: (error: unknown) => void;\n};\n\n/**\n * `CommandExecution(executor)` runs the (possibly async) `executor({ ack })`\n * immediately: its return value resolves the execution, a throw/rejection\n * rejects it; `ack()` releases the client's ack watermark before the executor\n * finishes. `CommandExecution.withResolvers()` returns `[execution,\n * { ack, resolve, reject }]` instead — settle them from your own spawned work.\n */\nexport const CommandExecution = Object.assign(\n <T = void>(\n executor: (resolvers: {\n ack: () => void;\n }) => T | void | PromiseLike<T | void>,\n ): CommandExecution<T> => {\n const state: ExecutionState = { acked: false, settled: null, bind: null };\n const execution = Object.freeze({}) as unknown as CommandExecution<T>;\n executionStates.set(execution, state);\n const settle = (settled: ExecutionSettled) => {\n if (state.settled) return;\n state.settled = settled;\n state.acked = true;\n state.bind?.onSettle(settled);\n };\n const ack = () => {\n if (state.acked) return;\n state.acked = true;\n state.bind?.onAck();\n };\n void (async () => {\n try {\n settle({ type: \"resolved\", value: await executor({ ack }) });\n } catch (error) {\n settle({ type: \"rejected\", error });\n }\n })();\n return execution;\n },\n {\n withResolvers: <T = void>(): [\n CommandExecution<T>,\n CommandExecutionResolvers<T>,\n ] => {\n let resolve!: (value: T) => void;\n let reject!: (error: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n let ack!: () => void;\n const execution = CommandExecution<T>(({ ack: a }) => {\n ack = a;\n return promise;\n });\n return [execution, { ack: () => ack(), resolve, reject }];\n },\n },\n);\n\nexport type CommandsInvocation = {\n readonly method: string;\n readonly params: readonly unknown[];\n readonly ts: number;\n readonly seq: number;\n readonly clientId?: string;\n};\n\nexport type CommandsOutcome =\n | { type: \"accepted\"; payload?: unknown }\n | { type: \"rejected\"; error: unknown };\n\nexport type CommandsListener = {\n onStart: (inv: CommandsInvocation) => void;\n onPosted?: (inv: CommandsInvocation) => void;\n onAck: (inv: CommandsInvocation) => void;\n /** Canonical state now covers the invocation's effect — drop any overlay. */\n onCovered?: (inv: CommandsInvocation) => void;\n onSettle: (inv: CommandsInvocation, outcome: CommandsOutcome) => void;\n};\n\nexport type CommandsHost = {\n setListener: (listener: CommandsListener | null) => void;\n};\n\nconst commandsHosts = new WeakMap<object, CommandsHost>();\n\nexport const getCommandsHost = (commands: object): CommandsHost | undefined =>\n commandsHosts.get(commands);\n\nexport const bindCommandsHost = (commands: object, host: CommandsHost) => {\n commandsHosts.set(commands, host);\n};\n\ntype QueuedCall = {\n method: string;\n params: readonly unknown[];\n ts: number;\n resolve: (value: unknown) => void;\n reject: (error: unknown) => void;\n};\n\ntype ActiveInvocation = CommandsInvocation & { acked: boolean };\n\ntype CommandsCell = {\n handlers: Record<string, (...args: never[]) => unknown> | null;\n queue: QueuedCall[];\n running: boolean;\n listener: CommandsListener | null;\n seq: number;\n unmounted: boolean;\n stallTimer: ReturnType<typeof setTimeout> | null;\n};\n\nconst STALL_WARN_MS = 5000;\n\nconst toSendError = (error: unknown): StatewireSendError =>\n error instanceof StatewireSendError\n ? error\n : new StatewireSendError({\n fate: \"rejected\",\n cause: \"server\",\n message: error instanceof Error ? error.message : String(error),\n ...(error instanceof StatewireReject &&\n error.payload !== undefined && { payload: error.payload }),\n });\n\nconst ackInvocation = (cell: CommandsCell, inv: ActiveInvocation) => {\n if (inv.acked) return;\n inv.acked = true;\n cell.listener?.onAck(inv);\n};\n\nconst settleInvocation = (\n cell: CommandsCell,\n inv: ActiveInvocation,\n call: QueuedCall,\n settled: ExecutionSettled,\n) => {\n ackInvocation(cell, inv);\n if (settled.type === \"resolved\") {\n const outcome: CommandsOutcome =\n settled.value === undefined\n ? { type: \"accepted\" }\n : { type: \"accepted\", payload: frozen(settled.value) };\n cell.listener?.onSettle(inv, outcome);\n call.resolve(outcome.payload);\n } else {\n const error = toSendError(settled.error);\n cell.listener?.onSettle(inv, { type: \"rejected\", error });\n call.reject(error);\n }\n};\n\nconst pump = (cell: CommandsCell) => {\n if (cell.running || !cell.handlers) {\n watchStall(cell);\n return;\n }\n const call = cell.queue.shift();\n if (!call) return;\n const handler = cell.handlers[call.method];\n if (handler === undefined) {\n call.reject(\n new StatewireSendError({ fate: \"unknown-command\", cause: \"server\" }),\n );\n pump(cell);\n return;\n }\n const inv: ActiveInvocation = {\n method: call.method,\n params: call.params,\n ts: call.ts,\n seq: ++cell.seq,\n acked: false,\n };\n cell.running = true;\n cell.listener?.onStart(inv);\n cell.listener?.onPosted?.(inv);\n cell.listener?.onCovered?.(inv);\n void (async () => {\n try {\n const value = await (handler as (...args: readonly unknown[]) => unknown)(\n ...call.params,\n );\n const execution =\n typeof value === \"object\" && value !== null\n ? executionStates.get(value)\n : undefined;\n if (execution) {\n if (execution.acked) ackInvocation(cell, inv);\n if (execution.settled) {\n settleInvocation(cell, inv, call, execution.settled);\n } else {\n execution.bind = {\n onAck: () => ackInvocation(cell, inv),\n onSettle: (settled) => settleInvocation(cell, inv, call, settled),\n };\n }\n } else {\n settleInvocation(cell, inv, call, { type: \"resolved\", value });\n }\n } catch (error) {\n settleInvocation(cell, inv, call, { type: \"rejected\", error });\n } finally {\n cell.running = false;\n pump(cell);\n }\n })();\n};\n\nconst watchStall = (cell: CommandsCell) => {\n if (!isDev() || cell.stallTimer !== null || cell.queue.length === 0) return;\n if (cell.handlers) return;\n cell.stallTimer = setTimeout(() => {\n cell.stallTimer = null;\n if (cell.handlers === null && cell.queue.length > 0 && !cell.unmounted) {\n console.warn(\n `statewire: ${cell.queue.length} buffered command(s) waiting over ${STALL_WARN_MS}ms — did the host forget to arm useStatewireCommands?`,\n );\n }\n }, STALL_WARN_MS);\n};\n\ntype UnwrapExecution<V> = V extends CommandExecution<infer T> ? T : V;\n\nexport type StatewireHandledCommands<THandlers extends StatewireCommands> = {\n [K in keyof THandlers]: (\n ...args: Parameters<THandlers[K]>\n ) => UnwrapExecution<Awaited<ReturnType<THandlers[K]>>>;\n};\n\nexport const useStatewireCommands = <THandlers extends StatewireCommands>(\n commands: THandlers | undefined | null | false,\n): StatewireCommandsProxy<StatewireHandledCommands<THandlers>> => {\n const [built] = useState(() => {\n const cell: CommandsCell = {\n handlers: null,\n queue: [],\n running: false,\n listener: null,\n seq: 0,\n unmounted: false,\n stallTimer: null,\n };\n const memo = new Map<string, (...params: unknown[]) => Promise<unknown>>();\n const proxy = new Proxy(\n {} as StatewireCommandsProxy<StatewireHandledCommands<THandlers>>,\n {\n get: (_target, method) => {\n if (typeof method !== \"string\") return undefined;\n let fn = memo.get(method);\n if (fn === undefined) {\n fn = (...params: unknown[]) =>\n new Promise((resolve, reject) => {\n if (cell.unmounted) {\n reject(new Error(\"statewire: commands called after unmount\"));\n return;\n }\n cell.queue.push({\n method,\n params,\n ts: Date.now(),\n resolve,\n reject,\n });\n pump(cell);\n });\n memo.set(method, fn);\n }\n return fn;\n },\n },\n );\n commandsHosts.set(proxy, {\n setListener: (listener) => {\n cell.listener = listener;\n },\n });\n return { cell, proxy };\n });\n\n useEffect(() => {\n const { cell } = built;\n cell.unmounted = false;\n return () => {\n cell.unmounted = true;\n cell.handlers = null;\n if (cell.stallTimer !== null) {\n clearTimeout(cell.stallTimer);\n cell.stallTimer = null;\n }\n queueMicrotask(() => {\n if (!cell.unmounted) return;\n const queued = cell.queue;\n cell.queue = [];\n for (const call of queued) {\n call.reject(new Error(\"statewire: unmounted\"));\n }\n });\n };\n }, [built]);\n\n useEffect(() => {\n built.cell.handlers = commands || null;\n pump(built.cell);\n });\n\n return built.proxy;\n};\n\n// ─── emit ───────────────────────────────────────────────\n\nexport type EmitHost = {\n setSink: (sink: ((event: unknown) => void) | null) => void;\n};\n\nconst emitHosts = new WeakMap<object, EmitHost>();\n\nexport const getEmitHost = (emit: object): EmitHost | undefined =>\n emitHosts.get(emit);\n\nexport const useStatewireEmit = <TEvent>(): ((event: TEvent) => void) => {\n const [built] = useState(() => {\n const cell = { sink: null as ((event: unknown) => void) | null };\n const emit = (event: TEvent) => {\n if (!cell.sink) {\n throw new Error(\"statewire: emit before a host bound the event sink\");\n }\n cell.sink(frozen(event));\n };\n emitHosts.set(emit, {\n setSink: (sink) => {\n cell.sink = sink;\n },\n });\n return emit;\n });\n return built;\n};\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { StatewireOp, applyOps } from "./wire/ops.js";
2
+ import { StatewireConnection, StatewireSSE, StatewireSSEOptions } from "./transports/sse.js";
3
+ import { SendFailure, StatewireChanges, StatewireCommand, StatewireCommandUpdate, StatewireCommands, StatewireCommandsProxy, StatewireHelpers, StatewireOptimistic, StatewireOptimisticContext, StatewireOptions, StatewireSendError, StatewireStateSource, StatewireTransport } from "./types.js";
4
+ import { StatewireWS, StatewireWSOptions } from "./transports/ws.js";
5
+ import { Statewire, StatewireResource, useStatewire } from "./statewire.js";
6
+ //#region src/index.d.ts
7
+ declare namespace Statewire {
8
+ type Connection = StatewireConnection;
9
+ type ConnectionStatus = StatewireConnection["status"];
10
+ type Transport<TState = any, TCommands extends StatewireCommands = StatewireCommands, TEvent = any> = StatewireTransport<TState, TCommands, TEvent>;
11
+ type StateSource = StatewireStateSource;
12
+ type SSEOptions = StatewireSSEOptions;
13
+ type WSOptions = StatewireWSOptions;
14
+ type Options<TState, TCommands extends StatewireCommands = StatewireCommands, TEvent = any> = StatewireOptions<TState, TCommands, TEvent>;
15
+ type Helpers<TState, TCommands extends StatewireCommands = StatewireCommands> = StatewireHelpers<TState, TCommands>;
16
+ type Commands = StatewireCommands;
17
+ type Command<TCommands extends StatewireCommands = StatewireCommands> = StatewireCommand<TCommands>;
18
+ type CommandsProxy<TCommands extends StatewireCommands> = StatewireCommandsProxy<TCommands>;
19
+ type CommandUpdate<TCommands extends StatewireCommands = StatewireCommands> = StatewireCommandUpdate<TCommands>;
20
+ type Optimistic<TState, TCommands extends StatewireCommands = StatewireCommands> = StatewireOptimistic<TState, TCommands>;
21
+ type OptimisticContext = StatewireOptimisticContext;
22
+ type SendFailure = SendFailure;
23
+ type Changes = StatewireChanges;
24
+ type Op = StatewireOp;
25
+ }
26
+ //#endregion
27
+ export { Statewire, StatewireResource, StatewireSSE, StatewireSendError, StatewireWS, applyOps, useStatewire };
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;kBA4BiB;OACH,aAAa;OACb,mBAAmB;OACnB,UACV,cACA,kBAAkB,oBAAoB,mBACtC,gBACE,mBAAmB,QAAQ,WAAW;OAC9B,cAAc;OACd,aAAa;OACb,YAAY;OACZ,QACV,QACA,kBAAkB,oBAAoB,mBACtC,gBACE,iBAAiB,QAAQ,WAAW;OAC5B,QACV,QACA,kBAAkB,oBAAoB,qBACpC,iBAAiB,QAAQ;OACjB,WAAW;OACX,QAAQ,kBAAkB,oBAAoB,qBACxD,iBAAiB;OACP,cAAc,kBAAkB,qBAC1C,uBAAuB;OACb,cACV,kBAAkB,oBAAoB,qBACpC,uBAAuB;OACf,WACV,QACA,kBAAkB,oBAAoB,qBACpC,oBAAoB,QAAQ;OACpB,oBAAoB;OACpB,cAAc;OACd,UAAU;OACV,KAAK"}