iterate 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/README.md +164 -82
  2. package/dist/{next/api.d.ts → api.d.ts} +197 -33
  3. package/dist/{next/app-server.d.ts → app-server.d.ts} +7 -0
  4. package/dist/{next/app-server.mjs → app-server.mjs} +17 -15
  5. package/dist/app-server.mjs.map +1 -0
  6. package/dist/{next/app-session.mjs → app-session.mjs} +12 -15
  7. package/dist/app-session.mjs.map +1 -0
  8. package/dist/{next/app.mjs → app.mjs} +53 -14
  9. package/dist/app.mjs.map +1 -0
  10. package/dist/{next/client → client}/live-state.d.ts +11 -11
  11. package/dist/client/oauth.d.ts +17 -0
  12. package/dist/{next/client → client}/react.d.ts +10 -42
  13. package/dist/{next/client → client}/socket.d.ts +1 -0
  14. package/dist/client.mjs +156 -4
  15. package/dist/client.mjs.map +1 -0
  16. package/dist/{next/expression.d.ts → expression.d.ts} +11 -69
  17. package/dist/{next/expression.mjs → expression.mjs} +11 -109
  18. package/dist/expression.mjs.map +1 -0
  19. package/dist/lib-BWr-5mFO.mjs +36 -0
  20. package/dist/lib-BWr-5mFO.mjs.map +1 -0
  21. package/dist/{next/lib.d.ts → lib.d.ts} +16 -2
  22. package/dist/{next/lib.mjs → lib.mjs} +32 -3
  23. package/dist/lib.mjs.map +1 -0
  24. package/dist/node.d.ts +15 -3
  25. package/dist/node.mjs +36 -174
  26. package/dist/node.mjs.map +1 -1
  27. package/dist/{next/oauth-scopes.mjs → oauth-scopes.mjs} +1 -1
  28. package/dist/oauth-scopes.mjs.map +1 -0
  29. package/dist/{next/oauth.mjs → oauth.mjs} +14 -2
  30. package/dist/oauth.mjs.map +1 -0
  31. package/dist/principal.d.ts +8 -0
  32. package/dist/principal.mjs +8 -0
  33. package/dist/principal.mjs.map +1 -0
  34. package/dist/project-ingress.d.ts +58 -0
  35. package/dist/project-ingress.mjs +104 -0
  36. package/dist/project-ingress.mjs.map +1 -0
  37. package/dist/{next/react.mjs → react.mjs} +12 -12
  38. package/dist/react.mjs.map +1 -0
  39. package/dist/sdk/auth.d.ts +25 -0
  40. package/dist/sdk/index.d.ts +155 -0
  41. package/dist/sdk/record-pipelined-steps.d.ts +19 -0
  42. package/dist/sdk.mjs +245 -2
  43. package/dist/sdk.mjs.map +1 -0
  44. package/dist/{next/stream → stream}/processor.d.ts +28 -23
  45. package/dist/{next/stream → stream}/processor.mjs +48 -25
  46. package/dist/stream/processor.mjs.map +1 -0
  47. package/dist/{next/stream → stream}/run.d.ts +9 -6
  48. package/dist/{next/stream → stream}/run.mjs +13 -8
  49. package/dist/stream/run.mjs.map +1 -0
  50. package/dist/stream/test-support.d.ts +45 -0
  51. package/dist/stream/test-support.mjs +196 -0
  52. package/dist/stream/test-support.mjs.map +1 -0
  53. package/package.json +65 -219
  54. package/THIRD_PARTY_NOTICES.md +0 -55
  55. package/bin/iterate.js +0 -94
  56. package/dist/api-url-B6404M82.mjs +0 -17
  57. package/dist/api-url-B6404M82.mjs.map +0 -1
  58. package/dist/app-ref-BipL0feU.mjs +0 -35
  59. package/dist/app-ref-BipL0feU.mjs.map +0 -1
  60. package/dist/app-ref-C1CrgXqX.mjs +0 -7
  61. package/dist/app-ref-C1CrgXqX.mjs.map +0 -1
  62. package/dist/app-ref-DYai_om1.mjs +0 -7
  63. package/dist/app-ref-DYai_om1.mjs.map +0 -1
  64. package/dist/cli-D0c-pDL_.mjs +0 -1010
  65. package/dist/cli-D0c-pDL_.mjs.map +0 -1
  66. package/dist/client.d.ts +0 -3
  67. package/dist/cloudflare-BTm90gQ4.mjs +0 -951
  68. package/dist/cloudflare-BTm90gQ4.mjs.map +0 -1
  69. package/dist/contract-s4FW4eES.mjs +0 -309
  70. package/dist/contract-s4FW4eES.mjs.map +0 -1
  71. package/dist/document-review/index.d.ts +0 -5
  72. package/dist/document-review/types.d.ts +0 -107
  73. package/dist/document-review.mjs +0 -7015
  74. package/dist/document-review.mjs.map +0 -1
  75. package/dist/durable-object-processor-durability-CNsTjAJS.mjs +0 -205
  76. package/dist/durable-object-processor-durability-CNsTjAJS.mjs.map +0 -1
  77. package/dist/idempotency-DleloJNt.mjs +0 -28
  78. package/dist/idempotency-DleloJNt.mjs.map +0 -1
  79. package/dist/index.d.mts +0 -5
  80. package/dist/index.mjs +0 -8
  81. package/dist/index.mjs.map +0 -1
  82. package/dist/itx/api-url.d.ts +0 -6
  83. package/dist/itx/itx-node-client.d.ts +0 -65
  84. package/dist/itx/itx-session.d.ts +0 -215
  85. package/dist/itx/owned-rpc-session.d.ts +0 -14
  86. package/dist/itx/query-client.d.ts +0 -10
  87. package/dist/itx-api.generated.d.ts +0 -6195
  88. package/dist/itx-session-sjud8GiT.mjs +0 -534
  89. package/dist/itx-session-sjud8GiT.mjs.map +0 -1
  90. package/dist/live-state-BJNqOwFw.mjs +0 -299
  91. package/dist/live-state-BJNqOwFw.mjs.map +0 -1
  92. package/dist/next/app-server.mjs.map +0 -1
  93. package/dist/next/app-session.mjs.map +0 -1
  94. package/dist/next/app.mjs.map +0 -1
  95. package/dist/next/client/oauth.d.ts +0 -12
  96. package/dist/next/client.mjs +0 -156
  97. package/dist/next/client.mjs.map +0 -1
  98. package/dist/next/expression.mjs.map +0 -1
  99. package/dist/next/lib.mjs.map +0 -1
  100. package/dist/next/oauth-scopes.mjs.map +0 -1
  101. package/dist/next/oauth.mjs.map +0 -1
  102. package/dist/next/principal.d.ts +0 -64
  103. package/dist/next/principal.mjs +0 -98
  104. package/dist/next/principal.mjs.map +0 -1
  105. package/dist/next/project-ingress.d.ts +0 -37
  106. package/dist/next/project-ingress.mjs +0 -75
  107. package/dist/next/project-ingress.mjs.map +0 -1
  108. package/dist/next/react.mjs.map +0 -1
  109. package/dist/next/sdk/auth.d.ts +0 -5
  110. package/dist/next/sdk/index.d.ts +0 -112
  111. package/dist/next/sdk.mjs +0 -139
  112. package/dist/next/sdk.mjs.map +0 -1
  113. package/dist/next/stream/processor.mjs.map +0 -1
  114. package/dist/next/stream/run.mjs.map +0 -1
  115. package/dist/next-node.d.ts +0 -15
  116. package/dist/next-node.mjs +0 -51
  117. package/dist/next-node.mjs.map +0 -1
  118. package/dist/processor-host-capabilities-BMFH3KTM.mjs +0 -56
  119. package/dist/processor-host-capabilities-BMFH3KTM.mjs.map +0 -1
  120. package/dist/processors/cloudflare.d.ts +0 -3
  121. package/dist/processors/durable-object-processor-durability.d.ts +0 -79
  122. package/dist/processors/event-consumption-metrics.d.ts +0 -82
  123. package/dist/processors/idempotency.d.ts +0 -13
  124. package/dist/processors/index.d.ts +0 -12
  125. package/dist/processors/processor-contracts.d.ts +0 -342
  126. package/dist/processors/processor-facet.d.ts +0 -186
  127. package/dist/processors/processor-host-capabilities.d.ts +0 -60
  128. package/dist/processors/prompt-sections.d.ts +0 -17
  129. package/dist/processors/rpc-types.d.ts +0 -515
  130. package/dist/processors/schemas.d.ts +0 -102
  131. package/dist/processors/stream-handle.d.ts +0 -45
  132. package/dist/processors/stream-processor-keepalive.d.ts +0 -95
  133. package/dist/processors/stream-processor-registry.d.ts +0 -233
  134. package/dist/processors/stream-processor-runner.d.ts +0 -289
  135. package/dist/processors/stream-processor.d.ts +0 -339
  136. package/dist/processors/stream-runtime-metrics.d.ts +0 -107
  137. package/dist/processors/testing.d.ts +0 -302
  138. package/dist/processors-BoNyeBfQ.mjs +0 -10
  139. package/dist/processors-BoNyeBfQ.mjs.map +0 -1
  140. package/dist/processors-cloudflare.mjs +0 -3
  141. package/dist/processors-testing.mjs +0 -435
  142. package/dist/processors-testing.mjs.map +0 -1
  143. package/dist/processors.mjs +0 -52
  144. package/dist/processors.mjs.map +0 -1
  145. package/dist/protocol-DnK_f2m6.mjs +0 -251
  146. package/dist/protocol-DnK_f2m6.mjs.map +0 -1
  147. package/dist/sdk/capnweb/index.d.ts +0 -2
  148. package/dist/sdk/capnweb/live-state/compact.d.ts +0 -5
  149. package/dist/sdk/capnweb/live-state/diff.d.ts +0 -41
  150. package/dist/sdk/capnweb/live-state/engine.d.ts +0 -44
  151. package/dist/sdk/capnweb/live-state/index.d.ts +0 -41
  152. package/dist/sdk/capnweb/live-state/protocol.d.ts +0 -87
  153. package/dist/sdk/capnweb/live-state/retain.d.ts +0 -23
  154. package/dist/sdk/capnweb/live-state/store.d.ts +0 -20
  155. package/dist/sdk/capnweb/live-state/types.d.ts +0 -11
  156. package/dist/sdk/capnweb/react.d.ts +0 -45
  157. package/dist/sdk/capnweb/react.mjs +0 -316
  158. package/dist/sdk/capnweb/react.mjs.map +0 -1
  159. package/dist/sdk/capnweb.mjs +0 -4
  160. package/dist/sdk/itx/react.d.ts +0 -191
  161. package/dist/sdk/itx/react.mjs +0 -383
  162. package/dist/sdk/itx/react.mjs.map +0 -1
  163. package/dist/sdk-DMB-IM11.mjs +0 -933
  164. package/dist/sdk-DMB-IM11.mjs.map +0 -1
  165. package/dist/sdk.d.ts +0 -339
  166. package/dist/serve-itx.d.ts +0 -46
  167. package/dist/starter-apps/flake-dashboard/app-ref.d.ts +0 -31
  168. package/dist/starter-apps/flake-dashboard/configured-worker.mjs +0 -1055
  169. package/dist/starter-apps/flake-dashboard/configured-worker.mjs.map +0 -1
  170. package/dist/starter-apps/flake-dashboard/contract.d.ts +0 -4839
  171. package/dist/starter-apps/flake-dashboard/contract.mjs +0 -2
  172. package/dist/starter-apps/flake-dashboard/index.d.ts +0 -17
  173. package/dist/starter-apps/flake-dashboard/index.mjs +0 -56
  174. package/dist/starter-apps/flake-dashboard/index.mjs.map +0 -1
  175. package/dist/starter-apps/flake-dashboard/worker.d.ts +0 -4607
  176. package/dist/starter-apps/github-ai-linter/ai-linter.d.ts +0 -8914
  177. package/dist/starter-apps/github-ai-linter/configured-worker.mjs +0 -17987
  178. package/dist/starter-apps/github-ai-linter/configured-worker.mjs.map +0 -1
  179. package/dist/starter-apps/github-ai-linter/contract.d.ts +0 -9193
  180. package/dist/starter-apps/github-ai-linter/index.d.ts +0 -10
  181. package/dist/starter-apps/github-ai-linter/index.mjs +0 -36
  182. package/dist/starter-apps/github-ai-linter/index.mjs.map +0 -1
  183. package/dist/starter-apps/github-ai-linter/prompt.d.ts +0 -13
  184. package/dist/starter-apps/github-ai-linter/review-bot.d.ts +0 -808
  185. package/dist/starter-apps/github-ai-linter/rules.d.ts +0 -34
  186. package/dist/starter-apps/github-ai-linter/worker-ref.d.ts +0 -19
  187. package/dist/starter-apps/github-ai-linter/worker.d.ts +0 -19
  188. package/dist/starter-apps/github-ai-linter/worker.mjs +0 -947
  189. package/dist/starter-apps/github-ai-linter/worker.mjs.map +0 -1
  190. package/dist/starter-apps/guestbook/app-ref.d.ts +0 -27
  191. package/dist/starter-apps/guestbook/client.d.ts +0 -7
  192. package/dist/starter-apps/guestbook/client.mjs +0 -59
  193. package/dist/starter-apps/guestbook/configured-worker.mjs +0 -205
  194. package/dist/starter-apps/guestbook/configured-worker.mjs.map +0 -1
  195. package/dist/starter-apps/guestbook/index.d.ts +0 -9
  196. package/dist/starter-apps/guestbook/index.mjs +0 -31
  197. package/dist/starter-apps/guestbook/index.mjs.map +0 -1
  198. package/dist/starter-apps/guestbook/processor.d.ts +0 -2267
  199. package/dist/starter-apps/guestbook/worker.d.ts +0 -26
  200. package/dist/starter-apps/guestbook/worker.mjs +0 -191
  201. package/dist/starter-apps/guestbook/worker.mjs.map +0 -1
  202. package/dist/starter-apps/media/configured-worker.mjs +0 -577
  203. package/dist/starter-apps/media/configured-worker.mjs.map +0 -1
  204. package/dist/starter-apps/media/index.mjs +0 -36
  205. package/dist/starter-apps/media/index.mjs.map +0 -1
  206. package/dist/starter-apps/media/ref.mjs +0 -20
  207. package/dist/starter-apps/media/ref.mjs.map +0 -1
  208. package/dist/starter-apps/media/worker.mjs +0 -579
  209. package/dist/starter-apps/media/worker.mjs.map +0 -1
  210. package/dist/starter-apps/notes/configured-worker.mjs +0 -6134
  211. package/dist/starter-apps/notes/configured-worker.mjs.map +0 -1
  212. package/dist/starter-apps/notes/index.mjs +0 -23
  213. package/dist/starter-apps/notes/index.mjs.map +0 -1
  214. package/dist/starter-apps/notes/ref.mjs +0 -21
  215. package/dist/starter-apps/notes/ref.mjs.map +0 -1
  216. package/dist/starter-apps/notes/worker.mjs +0 -427
  217. package/dist/starter-apps/notes/worker.mjs.map +0 -1
  218. package/dist/starter-apps/todo/client.mjs +0 -59
  219. package/dist/starter-apps/todo/configured-worker.mjs +0 -2864
  220. package/dist/starter-apps/todo/configured-worker.mjs.map +0 -1
  221. package/dist/starter-apps/todo/index.d.ts +0 -8
  222. package/dist/starter-apps/todo/index.mjs +0 -29
  223. package/dist/starter-apps/todo/index.mjs.map +0 -1
  224. package/dist/stream-processor-keepalive-DAQTP6m3.mjs +0 -2082
  225. package/dist/stream-processor-keepalive-DAQTP6m3.mjs.map +0 -1
  226. package/dist/usingCtx-mZx5nsAW.mjs +0 -11800
  227. package/dist/usingCtx-mZx5nsAW.mjs.map +0 -1
  228. package/dist/worker-ref-DZxPDmb_.mjs +0 -390
  229. package/dist/worker-ref-DZxPDmb_.mjs.map +0 -1
  230. package/dist/worker.d.mts +0 -33
  231. package/dist/worker.mjs +0 -18
  232. package/dist/worker.mjs.map +0 -1
  233. package/menubar/Iterate.entitlements +0 -12
  234. package/menubar/Iterate.swift +0 -914
  235. package/menubar/IterateIcon.swift +0 -145
  236. package/menubar/README.md +0 -28
  237. package/menubar/build-menubar-app.sh +0 -59
  238. /package/dist/{next/api.mjs → api.mjs} +0 -0
  239. /package/dist/{next/app-session.d.ts → app-session.d.ts} +0 -0
  240. /package/dist/{next/app.d.ts → app.d.ts} +0 -0
  241. /package/dist/{next/oauth-scopes.d.ts → oauth-scopes.d.ts} +0 -0
@@ -1,251 +0,0 @@
1
- //#region src/sdk/capnweb/live-state/diff.ts
2
- /**
3
- * Structural diff between two JSON values, producing the minimal `LiveStatePatch`
4
- * — or `undefined` when nothing changed.
5
- *
6
- * The diff is REFERENCE-FIRST: identical references short-circuit immediately
7
- * (`Object.is`), so the cost is O(changed), not O(size) — *as long as callers
8
- * update state immutably* (unchanged sub-objects keep their identity). That one
9
- * discipline is the whole performance story: a single touched row in a
10
- * thousand-entry index yields one tiny patch instead of a full rescan.
11
- *
12
- * PLAIN objects (prototype `Object.prototype` or `null`) are treated as keyed
13
- * maps and diffed per key. Dense arrays are diffed by position. Everything
14
- * else — primitives, `null`, sparse arrays, and
15
- * non-plain instances like `Date`/`Map`/`Set` — is a leaf, replaced wholesale.
16
- * Descending into an instance would diff its own enumerable keys, which for a
17
- * `Date` is NONE — two different Dates would read as "unchanged" and the
18
- * subscriber would stay stale forever. Keyed objects remain preferable for
19
- * collections whose entries frequently move; positional patches do not infer moves.
20
- */
21
- function diff(prev, next, options = {}) {
22
- if (Object.is(prev, next)) return void 0;
23
- if (Array.isArray(prev) && Array.isArray(next) && options.arrays !== false) {
24
- const items = [];
25
- for (let index = 0; index < next.length; index++) {
26
- if (!Object.hasOwn(next, index) || index < prev.length && !Object.hasOwn(prev, index)) return { set: next };
27
- const patch = index < prev.length ? diff(prev[index], next[index], options) : { set: next[index] };
28
- if (patch) items.push([index, patch]);
29
- }
30
- return items.length > 0 || prev.length !== next.length ? { array: {
31
- length: next.length,
32
- items
33
- } } : void 0;
34
- }
35
- if (!isPlainObject(prev) || !isPlainObject(next)) return { set: next };
36
- const fields = [];
37
- const drop = [];
38
- for (const key of Object.keys(next)) {
39
- if (next[key] === void 0) {
40
- if (Object.hasOwn(prev, key)) drop.push(key);
41
- continue;
42
- }
43
- const childPatch = diff(Object.hasOwn(prev, key) ? prev[key] : void 0, next[key], options);
44
- if (childPatch !== void 0) fields.push([key, childPatch]);
45
- }
46
- for (const key of Object.keys(prev)) if (!Object.hasOwn(next, key)) drop.push(key);
47
- if (fields.length === 0 && drop.length === 0) return void 0;
48
- const patch = {};
49
- if (fields.length > 0) patch.fields = Object.fromEntries(fields);
50
- if (drop.length > 0) patch.drop = drop;
51
- return patch;
52
- }
53
- /**
54
- * Apply a `LiveStatePatch` to a previous value, returning the next value.
55
- *
56
- * Like `diff`, this preserves structural sharing: a fresh object is built only
57
- * along changed paths, so untouched branches keep their previous reference.
58
- * That's what lets a client selector (`s => s.streamsIndex`) skip re-rendering
59
- * when an unrelated slice changed — the slice it reads stays `Object.is`-equal
60
- * across applies.
61
- */
62
- function applyPatch(prev, patch) {
63
- if ("set" in patch) return patch.set;
64
- if ("array" in patch) {
65
- if (!Array.isArray(prev)) throw new Error("Live-state array patch requires an array baseline");
66
- const next = prev.slice(0, patch.array.length);
67
- next.length = patch.array.length;
68
- for (const [index, child] of patch.array.items) {
69
- if (!Number.isSafeInteger(index) || index < 0 || index >= next.length) throw new Error("Live-state array patch index is outside its resulting length");
70
- next[index] = applyPatch(prev[index], child);
71
- }
72
- return next;
73
- }
74
- const base = isPlainObject(prev) ? prev : {};
75
- const next = { ...base };
76
- if (patch.fields) for (const [key, childPatch] of Object.entries(patch.fields)) Object.defineProperty(next, key, {
77
- value: applyPatch(Object.hasOwn(base, key) ? base[key] : void 0, childPatch),
78
- enumerable: true,
79
- writable: true,
80
- configurable: true
81
- });
82
- if (patch.drop) for (const key of patch.drop) delete next[key];
83
- return next;
84
- }
85
- /**
86
- * A PLAIN object — prototype `Object.prototype` or `null` — the only thing
87
- * `diff` descends into and `applyPatch` merges over. Arrays and class instances
88
- * (`Date`, `Map`, `Set`, …) fail this on purpose: they carry state outside
89
- * their own enumerable keys, so per-key diffing would misread them (see the
90
- * `diff` docstring) — they are leaves, replaced wholesale.
91
- */
92
- function isPlainObject(value) {
93
- if (typeof value !== "object" || value === null) return false;
94
- const proto = Object.getPrototypeOf(value);
95
- return proto === Object.prototype || proto === null;
96
- }
97
- //#endregion
98
- //#region src/sdk/capnweb/live-state/compact.ts
99
- const fieldAddresses = /* @__PURE__ */ new WeakMap();
100
- function addresses(value) {
101
- let cached = fieldAddresses.get(value);
102
- if (!cached) {
103
- const keys = Object.keys(value).filter((key) => value[key] !== void 0).sort();
104
- cached = {
105
- keys,
106
- indices: new Map(keys.map((key, index) => [key, index]))
107
- };
108
- fieldAddresses.set(value, cached);
109
- }
110
- return cached;
111
- }
112
- /** Encode only the changed paths of an existing structural diff. */
113
- function compactPatch(previous, patch) {
114
- if ("set" in patch) {
115
- const next = patch.set;
116
- if (typeof previous === "string" && typeof next === "string" && previous.length >= 16 && previous.length <= 4096 && next.length > previous.length && next.startsWith(previous)) return [previous.length, next.slice(previous.length)];
117
- if (next === null || typeof next === "string" || typeof next === "number" || typeof next === "boolean") return next;
118
- return [next];
119
- }
120
- if ("array" in patch) {
121
- if (!Array.isArray(previous)) throw new Error("Live-state array patch requires an array baseline");
122
- const result = {};
123
- if (patch.array.length !== previous.length) result["#"] = patch.array.length;
124
- for (const [index, child] of patch.array.items) result[index] = compactPatch(previous[index], child);
125
- return result;
126
- }
127
- if (!isPlainObject(previous)) throw new Error("Live-state object patch requires an object baseline");
128
- const { indices } = addresses(previous);
129
- const fields = [];
130
- for (const [key, child] of Object.entries(patch.fields || {})) {
131
- const index = indices.get(key);
132
- fields.push([index === void 0 ? `+${key}` : String(index), compactPatch(index === void 0 ? void 0 : previous[key], child)]);
133
- }
134
- for (const key of patch.drop || []) {
135
- const index = indices.get(key);
136
- if (index !== void 0) fields.push([String(index), []]);
137
- }
138
- return Object.fromEntries(fields);
139
- }
140
- /** Apply a version 3 patch, retaining every untouched object's identity. */
141
- function applyCompactPatch(previous, patch) {
142
- return applyCompactValue(previous, patch);
143
- }
144
- function applyCompactValue(previous, patch) {
145
- if (patch === null || typeof patch !== "object") return patch;
146
- if (Array.isArray(patch)) {
147
- if (patch.length === 1) return patch[0];
148
- if (patch.length !== 2 || typeof previous !== "string" || previous.length !== patch[0]) throw new Error("Live-state append does not match its string baseline");
149
- return previous + patch[1];
150
- }
151
- if (Array.isArray(previous)) {
152
- const length = Object.hasOwn(patch, "#") ? patch["#"] : previous.length;
153
- if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > 4294967295) throw new Error("Live-state array patch has an invalid length");
154
- const next = previous.slice(0, length);
155
- next.length = length;
156
- for (const [address, child] of Object.entries(patch)) {
157
- if (address === "#") continue;
158
- const index = position(address, length);
159
- next[index] = applyCompactValue(previous[index], child);
160
- }
161
- return next;
162
- }
163
- if (!isPlainObject(previous)) throw new Error("Live-state object patch requires an object baseline");
164
- const { keys } = addresses(previous);
165
- const next = { ...previous };
166
- for (const [address, child] of Object.entries(patch)) {
167
- const added = address.startsWith("+");
168
- const key = added ? address.slice(1) : keys[position(address, keys.length)];
169
- if (added && Object.hasOwn(previous, key) && previous[key] !== void 0) throw new Error("Live-state new field already exists in its baseline");
170
- if (Array.isArray(child) && child.length === 0) {
171
- if (added) throw new Error("Live-state cannot delete a new field");
172
- delete next[key];
173
- } else Object.defineProperty(next, key, {
174
- value: applyCompactValue(added ? void 0 : previous[key], child),
175
- enumerable: true,
176
- writable: true,
177
- configurable: true
178
- });
179
- }
180
- return next;
181
- }
182
- function position(address, length) {
183
- const index = Number(address);
184
- if (!Number.isSafeInteger(index) || index < 0 || index >= length || String(index) !== address) throw new Error("Live-state field address is outside its baseline");
185
- return index;
186
- }
187
- //#endregion
188
- //#region src/sdk/capnweb/live-state/store.ts
189
- function createLiveStateStore() {
190
- let held = {
191
- revision: -1,
192
- state: void 0
193
- };
194
- const listeners = /* @__PURE__ */ new Set();
195
- const notify = () => listeners.forEach((listener) => listener());
196
- return {
197
- getState: () => held.state,
198
- subscribe: (listener) => {
199
- listeners.add(listener);
200
- return () => void listeners.delete(listener);
201
- },
202
- reset: () => {
203
- held = {
204
- revision: -1,
205
- state: void 0
206
- };
207
- notify();
208
- },
209
- apply: (update, resync) => {
210
- if ("s" in update) held = {
211
- revision: update.s[0],
212
- state: update.s[1]
213
- };
214
- else if ("p" in update) {
215
- if (update.p[0] !== held.revision) {
216
- resync();
217
- return;
218
- }
219
- held = {
220
- revision: update.p[1],
221
- state: applyCompactPatch(held.state, update.p[2])
222
- };
223
- } else if (update.type === "snapshot") held = {
224
- revision: update.revision,
225
- state: update.state
226
- };
227
- else if (update.from !== held.revision) {
228
- resync();
229
- return;
230
- } else held = {
231
- revision: update.to,
232
- state: applyPatch(held.state, update.patch)
233
- };
234
- notify();
235
- }
236
- };
237
- }
238
- //#endregion
239
- //#region src/sdk/capnweb/live-state/protocol.ts
240
- function isLiveStateSnapshot(update) {
241
- return "s" in update || "type" in update && update.type === "snapshot";
242
- }
243
- function liveStateRevision(update) {
244
- if ("s" in update) return update.s[0];
245
- if ("p" in update) return update.p[1];
246
- return update.type === "snapshot" ? update.revision : update.to;
247
- }
248
- //#endregion
249
- export { compactPatch as a, applyCompactPatch as i, liveStateRevision as n, applyPatch as o, createLiveStateStore as r, diff as s, isLiveStateSnapshot as t };
250
-
251
- //# sourceMappingURL=protocol-DnK_f2m6.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol-DnK_f2m6.mjs","names":[],"sources":["../src/sdk/capnweb/live-state/diff.ts","../src/sdk/capnweb/live-state/compact.ts","../src/sdk/capnweb/live-state/store.ts","../src/sdk/capnweb/live-state/protocol.ts"],"sourcesContent":["import type { LiveStatePatch } from \"./protocol.ts\";\n\n/**\n * Structural diff between two JSON values, producing the minimal `LiveStatePatch`\n * — or `undefined` when nothing changed.\n *\n * The diff is REFERENCE-FIRST: identical references short-circuit immediately\n * (`Object.is`), so the cost is O(changed), not O(size) — *as long as callers\n * update state immutably* (unchanged sub-objects keep their identity). That one\n * discipline is the whole performance story: a single touched row in a\n * thousand-entry index yields one tiny patch instead of a full rescan.\n *\n * PLAIN objects (prototype `Object.prototype` or `null`) are treated as keyed\n * maps and diffed per key. Dense arrays are diffed by position. Everything\n * else — primitives, `null`, sparse arrays, and\n * non-plain instances like `Date`/`Map`/`Set` — is a leaf, replaced wholesale.\n * Descending into an instance would diff its own enumerable keys, which for a\n * `Date` is NONE — two different Dates would read as \"unchanged\" and the\n * subscriber would stay stale forever. Keyed objects remain preferable for\n * collections whose entries frequently move; positional patches do not infer moves.\n */\nexport function diff(\n prev: unknown,\n next: unknown,\n options: { arrays?: boolean } = {},\n): LiveStatePatch | undefined {\n if (Object.is(prev, next)) return undefined;\n if (Array.isArray(prev) && Array.isArray(next) && options.arrays !== false) {\n const items: [number, LiveStatePatch][] = [];\n for (let index = 0; index < next.length; index++) {\n // Sparse arrays retain the replacement semantics of their wire value.\n if (!Object.hasOwn(next, index) || (index < prev.length && !Object.hasOwn(prev, index))) {\n return { set: next };\n }\n const patch =\n index < prev.length ? diff(prev[index], next[index], options) : { set: next[index] };\n if (patch) items.push([index, patch]);\n }\n return items.length > 0 || prev.length !== next.length\n ? { array: { length: next.length, items } }\n : undefined;\n }\n if (!isPlainObject(prev) || !isPlainObject(next)) return { set: next };\n\n // Entries + fromEntries, not `bag[key] = …`: assignment with key \"__proto__\"\n // would SET THE BAG'S PROTOTYPE instead of recording the field — the change\n // would silently vanish from the patch. `Object.fromEntries` DEFINES own\n // properties (safe for any key) and yields an ordinary Object.prototype\n // object — which matters, because patches cross capnweb, whose serializer\n // accepts exactly Object.prototype (a null-proto bag reads as unsupported\n // and kills the push). (applyPatch has the mirror-image write guard.)\n // Own-property checks throughout (`Object.hasOwn`, not `in` / bare reads):\n // `\"__proto__\" in x` is true for EVERY object via inheritance, so `in` would\n // misread that key's presence in both directions.\n const fields: [string, LiveStatePatch][] = [];\n const drop: string[] = [];\n for (const key of Object.keys(next)) {\n if (next[key] === undefined) {\n if (Object.hasOwn(prev, key)) drop.push(key); // a key set to `undefined` reads as removed\n continue;\n }\n const childPatch = diff(Object.hasOwn(prev, key) ? prev[key] : undefined, next[key], options);\n if (childPatch !== undefined) fields.push([key, childPatch]);\n }\n for (const key of Object.keys(prev)) {\n if (!Object.hasOwn(next, key)) drop.push(key);\n }\n\n if (fields.length === 0 && drop.length === 0) return undefined;\n const patch: { fields?: Record<string, LiveStatePatch>; drop?: string[] } = {};\n if (fields.length > 0) patch.fields = Object.fromEntries(fields);\n if (drop.length > 0) patch.drop = drop;\n return patch;\n}\n\n/**\n * Apply a `LiveStatePatch` to a previous value, returning the next value.\n *\n * Like `diff`, this preserves structural sharing: a fresh object is built only\n * along changed paths, so untouched branches keep their previous reference.\n * That's what lets a client selector (`s => s.streamsIndex`) skip re-rendering\n * when an unrelated slice changed — the slice it reads stays `Object.is`-equal\n * across applies.\n */\nexport function applyPatch<State>(prev: State, patch: LiveStatePatch): State {\n if (\"set\" in patch) return patch.set as State;\n if (\"array\" in patch) {\n if (!Array.isArray(prev)) throw new Error(\"Live-state array patch requires an array baseline\");\n const next = prev.slice(0, patch.array.length);\n next.length = patch.array.length;\n for (const [index, child] of patch.array.items) {\n if (!Number.isSafeInteger(index) || index < 0 || index >= next.length) {\n throw new Error(\"Live-state array patch index is outside its resulting length\");\n }\n next[index] = applyPatch(prev[index], child);\n }\n // The array operation preserves State's shape; only the generic parameter\n // prevents TypeScript from expressing the Array.isArray narrowing on return.\n return next as State;\n }\n const base: Record<string, unknown> = isPlainObject(prev) ? prev : {};\n const next: Record<string, unknown> = { ...base };\n if (patch.fields) {\n for (const [key, childPatch] of Object.entries(patch.fields)) {\n // Define, don't assign: `next[key] =` with key \"__proto__\" would SET THE\n // PROTOTYPE instead of creating an own property — dropping the field and\n // letting a hostile patch inject one. (The spread above is already safe:\n // spread uses define semantics.) `Object.hasOwn` guards the read the same\n // way — a bare `base[\"__proto__\"]` reads the prototype, not a field.\n Object.defineProperty(next, key, {\n value: applyPatch(Object.hasOwn(base, key) ? base[key] : undefined, childPatch),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n }\n if (patch.drop) {\n for (const key of patch.drop) delete next[key];\n }\n return next as State;\n}\n\n/**\n * A PLAIN object — prototype `Object.prototype` or `null` — the only thing\n * `diff` descends into and `applyPatch` merges over. Arrays and class instances\n * (`Date`, `Map`, `Set`, …) fail this on purpose: they carry state outside\n * their own enumerable keys, so per-key diffing would misread them (see the\n * `diff` docstring) — they are leaves, replaced wholesale.\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n","import { isPlainObject } from \"./diff.ts\";\nimport type { CompactLiveStatePatch, LiveStatePatch } from \"./protocol.ts\";\n\nconst fieldAddresses = new WeakMap<object, { keys: string[]; indices: Map<string, number> }>();\n\nfunction addresses(value: Record<string, unknown>) {\n let cached = fieldAddresses.get(value);\n if (!cached) {\n // Undefined object fields are absent after a JSON transport. They must not\n // shift addresses on either side of the next update.\n const keys = Object.keys(value)\n .filter((key) => value[key] !== undefined)\n .sort();\n cached = { keys, indices: new Map(keys.map((key, index) => [key, index])) };\n fieldAddresses.set(value, cached);\n }\n return cached;\n}\n\n/** Encode only the changed paths of an existing structural diff. */\nexport function compactPatch(previous: unknown, patch: LiveStatePatch): CompactLiveStatePatch {\n if (\"set\" in patch) {\n const next = patch.set;\n if (\n typeof previous === \"string\" &&\n typeof next === \"string\" &&\n previous.length >= 16 &&\n // Bound prefix checks even for a multi-megabyte string. Immutable text\n // blocks are ~1 KiB; larger ordinary strings retain replacement semantics.\n previous.length <= 4096 &&\n next.length > previous.length &&\n next.startsWith(previous)\n )\n return [previous.length, next.slice(previous.length)];\n if (\n next === null ||\n typeof next === \"string\" ||\n typeof next === \"number\" ||\n typeof next === \"boolean\"\n )\n return next;\n return [next];\n }\n if (\"array\" in patch) {\n if (!Array.isArray(previous))\n throw new Error(\"Live-state array patch requires an array baseline\");\n const result: Record<string, CompactLiveStatePatch> = {};\n if (patch.array.length !== previous.length) result[\"#\"] = patch.array.length;\n for (const [index, child] of patch.array.items)\n result[index] = compactPatch(previous[index], child);\n return result;\n }\n if (!isPlainObject(previous))\n throw new Error(\"Live-state object patch requires an object baseline\");\n const { indices } = addresses(previous);\n const fields: [string, CompactLiveStatePatch][] = [];\n for (const [key, child] of Object.entries(patch.fields || {})) {\n const index = indices.get(key);\n fields.push([\n index === undefined ? `+${key}` : String(index),\n compactPatch(index === undefined ? undefined : previous[key], child),\n ]);\n }\n for (const key of patch.drop || []) {\n const index = indices.get(key);\n // An undefined field was already absent on the wire.\n if (index !== undefined) fields.push([String(index), []]);\n }\n return Object.fromEntries(fields);\n}\n\n/** Apply a version 3 patch, retaining every untouched object's identity. */\nexport function applyCompactPatch<State>(previous: State, patch: CompactLiveStatePatch): State {\n // Like applyPatch, the wire operation preserves the caller's State contract;\n // TypeScript cannot infer that contract from a recursive, generic JSON codec.\n return applyCompactValue(previous, patch) as State;\n}\n\nfunction applyCompactValue(previous: unknown, patch: CompactLiveStatePatch): unknown {\n if (patch === null || typeof patch !== \"object\") return patch;\n if (Array.isArray(patch)) {\n if (patch.length === 1) return patch[0];\n if (patch.length !== 2 || typeof previous !== \"string\" || previous.length !== patch[0]) {\n throw new Error(\"Live-state append does not match its string baseline\");\n }\n return previous + patch[1];\n }\n if (Array.isArray(previous)) {\n const length = Object.hasOwn(patch, \"#\") ? patch[\"#\"] : previous.length;\n if (\n typeof length !== \"number\" ||\n !Number.isSafeInteger(length) ||\n length < 0 ||\n length > 0xffffffff\n ) {\n throw new Error(\"Live-state array patch has an invalid length\");\n }\n const next = previous.slice(0, length);\n next.length = length;\n for (const [address, child] of Object.entries(patch)) {\n if (address === \"#\") continue;\n const index = position(address, length);\n next[index] = applyCompactValue(previous[index], child);\n }\n return next;\n }\n if (!isPlainObject(previous))\n throw new Error(\"Live-state object patch requires an object baseline\");\n const { keys } = addresses(previous);\n const next = { ...previous };\n for (const [address, child] of Object.entries(patch)) {\n const added = address.startsWith(\"+\");\n const key = added ? address.slice(1) : keys[position(address, keys.length)]!;\n if (added && Object.hasOwn(previous, key) && previous[key] !== undefined) {\n throw new Error(\"Live-state new field already exists in its baseline\");\n }\n if (Array.isArray(child) && child.length === 0) {\n if (added) throw new Error(\"Live-state cannot delete a new field\");\n delete next[key];\n } else {\n // Define own properties, including __proto__, without mutating prototypes.\n Object.defineProperty(next, key, {\n value: applyCompactValue(added ? undefined : previous[key], child),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n }\n return next;\n}\n\nfunction position(address: string, length: number): number {\n const index = Number(address);\n if (!Number.isSafeInteger(index) || index < 0 || index >= length || String(index) !== address) {\n throw new Error(\"Live-state field address is outside its baseline\");\n }\n return index;\n}\n","import { applyPatch } from \"./diff.ts\";\nimport { applyCompactPatch } from \"./compact.ts\";\nimport type { LiveUpdate } from \"./protocol.ts\";\n\n/**\n * The client half of the live-state channel: a tiny external store that folds\n * wire updates (one snapshot, then patches) back into the live value. The\n * server's `LiveState` engine is the producing half; `useLiveState` renders\n * this store via `useSyncExternalStore`.\n *\n * Revision discipline: a patch only applies when its `from` matches the held\n * revision. A mismatch means a message was missed (or arrived from a stale\n * subscription's revision line) — the store calls `resync` and holds its value\n * until the fresh snapshot lands, so a gap can never silently corrupt state.\n */\nexport type LiveStateStore<State> = {\n getState: () => State | undefined;\n subscribe: (listener: () => void) => () => void;\n reset: () => void;\n /** Fold one wire update into the held value; a revision gap means a missed patch — resync. */\n apply: (update: LiveUpdate<State>, resync: () => void) => void;\n};\n\nexport function createLiveStateStore<State>(): LiveStateStore<State> {\n let held: { revision: number; state: State | undefined } = { revision: -1, state: undefined };\n const listeners = new Set<() => void>();\n const notify = () => listeners.forEach((listener) => listener());\n return {\n getState: () => held.state,\n subscribe: (listener: () => void) => {\n listeners.add(listener);\n return () => void listeners.delete(listener);\n },\n reset: () => {\n held = { revision: -1, state: undefined };\n notify();\n },\n apply: (update: LiveUpdate<State>, resync: () => void) => {\n if (\"s\" in update) {\n held = { revision: update.s[0], state: update.s[1] };\n } else if (\"p\" in update) {\n if (update.p[0] !== held.revision) {\n resync();\n return;\n }\n held = { revision: update.p[1], state: applyCompactPatch(held.state, update.p[2]) };\n } else if (update.type === \"snapshot\") {\n held = { revision: update.revision, state: update.state };\n } else if (update.from !== held.revision) {\n resync();\n return;\n } else {\n held = { revision: update.to, state: applyPatch(held.state, update.patch) };\n }\n notify();\n },\n };\n}\n","/**\n * Wire types for the live-state channel: what a server engine pushes down a\n * subscription. A subscription always delivers one `snapshot` first (the full\n * current state), then a stream of `patch`es — each the minimal structural diff\n * since the previous revision. `useLiveState` reassembles these into the live\n * value, so feature code never touches these types directly.\n *\n * See `diff.ts` for how patches are produced (`diff`) and applied (`applyPatch`).\n */\n\n/**\n * A structural patch turning a previous JSON value into the next one. Three\n * shapes, discriminated by `set`, `array`, or an object patch:\n * - `{ set }` — replace this position wholesale. Used for primitives,\n * `null`, type changes,\n * and newly-added object keys.\n * - `{ fields?, drop? }` — descend into a plain object: `fields` maps each\n * changed key to its own patch; `drop` lists keys that disappeared. At least\n * one is present (an empty descend never gets emitted).\n * - `{ array }` — patch changed positions and set the resulting length. Kept\n * elements retain their identity, including immutable text blocks inside a\n * changed step. This form is sent only to subscribers requesting version 2.\n */\nexport type LiveStatePatch =\n | { set: unknown }\n | { array: { length: number; items: [number, LiveStatePatch][] } }\n | { fields?: Record<string, LiveStatePatch>; drop?: string[] };\n\n/** Explicit codec negotiation keeps already-open clients valid across deploys. */\nexport type LiveStateSubscriptionOptions = { patchVersion?: 2 | 3 };\n\n/**\n * Version 3 addresses existing object fields by their sorted baseline position;\n * new fields use `+name`. Arrays use indices and an optional `#` length.\n * Primitives replace directly, `[value]` replaces other values, `[length, text]`\n * appends to a string, and `[]` deletes an object field. No dictionary survives\n * an update: every address refers to the acknowledged baseline of that patch.\n */\nexport type CompactLiveStatePatch =\n | string\n | number\n | boolean\n | null\n | []\n | [unknown]\n | [number, string]\n | { [address: string]: CompactLiveStatePatch };\n\n/** A transient reader's position; a new engine incarnation always has a new epoch. */\nexport type LiveStateCursor = { epoch: string; revision: number };\n\n/** A pull transports one delta, a fresh snapshot, or no change. No callback is retained. */\nexport type LiveStateRead<State> = { epoch: string; update: LiveUpdate<State> | null };\n\n/**\n * One message pushed down a live-state subscription. The first is always a\n * `snapshot` (a resync sends a fresh one); every message after carries only the\n * diff from revision `from` to `to`. Revisions are monotonic for the life of one\n * subscription, so a gap (`from` ≠ the client's revision) means a message was\n * missed and the client should resubscribe.\n *\n * `State` is asserted by the caller of `useLiveState` — the wire itself is\n * structure-agnostic.\n */\nexport type LiveUpdate<State = unknown> =\n | { type: \"snapshot\"; revision: number; state: State }\n | { type: \"patch\"; from: number; to: number; patch: LiveStatePatch }\n | { s: [revision: number, state: State] }\n | { p: [from: number, to: number, patch: CompactLiveStatePatch] };\n\nexport function isLiveStateSnapshot<State>(\n update: LiveUpdate<State>,\n): update is Extract<LiveUpdate<State>, { type: \"snapshot\" } | { s: unknown }> {\n return \"s\" in update || (\"type\" in update && update.type === \"snapshot\");\n}\n\nexport function liveStateRevision(update: LiveUpdate): number {\n if (\"s\" in update) return update.s[0];\n if (\"p\" in update) return update.p[1];\n return update.type === \"snapshot\" ? update.revision : update.to;\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export * from "@iterate-com/capnweb";
2
- export * from "./live-state/index.ts";
@@ -1,5 +0,0 @@
1
- import type { CompactLiveStatePatch, LiveStatePatch } from "./protocol.ts";
2
- /** Encode only the changed paths of an existing structural diff. */
3
- export declare function compactPatch(previous: unknown, patch: LiveStatePatch): CompactLiveStatePatch;
4
- /** Apply a version 3 patch, retaining every untouched object's identity. */
5
- export declare function applyCompactPatch<State>(previous: State, patch: CompactLiveStatePatch): State;
@@ -1,41 +0,0 @@
1
- import type { LiveStatePatch } from "./protocol.ts";
2
- /**
3
- * Structural diff between two JSON values, producing the minimal `LiveStatePatch`
4
- * — or `undefined` when nothing changed.
5
- *
6
- * The diff is REFERENCE-FIRST: identical references short-circuit immediately
7
- * (`Object.is`), so the cost is O(changed), not O(size) — *as long as callers
8
- * update state immutably* (unchanged sub-objects keep their identity). That one
9
- * discipline is the whole performance story: a single touched row in a
10
- * thousand-entry index yields one tiny patch instead of a full rescan.
11
- *
12
- * PLAIN objects (prototype `Object.prototype` or `null`) are treated as keyed
13
- * maps and diffed per key. Dense arrays are diffed by position. Everything
14
- * else — primitives, `null`, sparse arrays, and
15
- * non-plain instances like `Date`/`Map`/`Set` — is a leaf, replaced wholesale.
16
- * Descending into an instance would diff its own enumerable keys, which for a
17
- * `Date` is NONE — two different Dates would read as "unchanged" and the
18
- * subscriber would stay stale forever. Keyed objects remain preferable for
19
- * collections whose entries frequently move; positional patches do not infer moves.
20
- */
21
- export declare function diff(prev: unknown, next: unknown, options?: {
22
- arrays?: boolean;
23
- }): LiveStatePatch | undefined;
24
- /**
25
- * Apply a `LiveStatePatch` to a previous value, returning the next value.
26
- *
27
- * Like `diff`, this preserves structural sharing: a fresh object is built only
28
- * along changed paths, so untouched branches keep their previous reference.
29
- * That's what lets a client selector (`s => s.streamsIndex`) skip re-rendering
30
- * when an unrelated slice changed — the slice it reads stays `Object.is`-equal
31
- * across applies.
32
- */
33
- export declare function applyPatch<State>(prev: State, patch: LiveStatePatch): State;
34
- /**
35
- * A PLAIN object — prototype `Object.prototype` or `null` — the only thing
36
- * `diff` descends into and `applyPatch` merges over. Arrays and class instances
37
- * (`Date`, `Map`, `Set`, …) fail this on purpose: they carry state outside
38
- * their own enumerable keys, so per-key diffing would misread them (see the
39
- * `diff` docstring) — they are leaves, replaced wholesale.
40
- */
41
- export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
@@ -1,44 +0,0 @@
1
- import type { LiveStateCursor, LiveStateRead, LiveStateSubscriptionOptions, LiveUpdate } from "./protocol.ts";
2
- /** Handle returned by `LiveState.subscribe` — the ownership + liveness surface for one subscriber. */
3
- export type LiveStateSubscription = {
4
- /** Still registered on a live engine? A dead DO incarnation also makes the call reject. */
5
- ping(): boolean;
6
- unsubscribe(): void;
7
- [Symbol.dispose](): void;
8
- };
9
- /**
10
- * A source-agnostic live store: hold a state value, and when it changes push the
11
- * minimal diff to every subscriber. It does not know or care where the state
12
- * comes from — a Durable Object folds events into it, a stateless RpcTarget polls
13
- * a third-party API into it — so ANY RpcTarget can expose live state by holding
14
- * one and returning a read-only wrapper from a `.live` getter.
15
- *
16
- * Two rules make it cheap and correct:
17
- * - Updates are IMMUTABLE (`setState`/`assign` build a new value, never mutate),
18
- * so the diff short-circuits unchanged branches by identity — O(changed), not
19
- * O(size). See `diff.ts`.
20
- * - Push work runs only while a subscriber exists. Transient readers call
21
- * `readSince` explicitly; a dormant engine schedules nothing.
22
- *
23
- * All subscribers share one revision line. Fast subscribers share a patch;
24
- * slow subscribers receive a coalesced patch from their acknowledged state.
25
- * A revision mismatch makes the client resync instead of applying stale data.
26
- */
27
- export declare class LiveState<State extends object> {
28
- #private;
29
- constructor(initial: State, options?: {
30
- debounceMs?: number;
31
- });
32
- /** The current state — reflects every `setState`/`assign`, even while dormant. */
33
- getState(): State;
34
- /** One retained delta bounds history while a single parent can pull incrementally.
35
- * A late reader or a new incarnation receives an explicit snapshot instead. */
36
- readSince(cursor?: LiveStateCursor, options?: LiveStateSubscriptionOptions): LiveStateRead<State>;
37
- /** True while at least one live subscriber makes projection work observable. */
38
- get observed(): boolean;
39
- /** Replace the state. Build a NEW value (don't mutate) so the diff stays cheap. */
40
- setState(next: State | ((prev: State) => State)): void;
41
- /** Shallow-merge a partial into the state — sugar for `setState(p => ({ ...p, ...partial }))`. */
42
- assign(partial: Partial<State>): void;
43
- subscribe(sink: (update: LiveUpdate<State>) => unknown, options?: LiveStateSubscriptionOptions): LiveStateSubscription;
44
- }
@@ -1,41 +0,0 @@
1
- import { RpcTarget } from "@iterate-com/capnweb";
2
- import type { LiveState as LiveStateEngine, LiveStateSubscription } from "./engine.ts";
3
- import type { LiveStateSubscriptionOptions, LiveUpdate } from "./protocol.ts";
4
- import type { LiveStateRpc, LiveStateSubscriptionHandle } from "./types.ts";
5
- type LiveStateSource<State extends object> = Pick<LiveStateEngine<State>, "getState" | "subscribe">;
6
- type RefreshingLiveStateSource<State extends object> = {
7
- readonly live: LiveStateSource<State>;
8
- loadAndRefreshLive(): void | PromiseLike<void>;
9
- };
10
- export { createLiveStateStore, type LiveStateStore } from "./store.ts";
11
- export { applyPatch, diff } from "./diff.ts";
12
- export { compactPatch, applyCompactPatch } from "./compact.ts";
13
- export { isLiveStateSnapshot, liveStateRevision } from "./protocol.ts";
14
- export type { CompactLiveStatePatch, LiveStateCursor, LiveStateRead, LiveStatePatch, LiveStateSubscriptionOptions, LiveUpdate, } from "./protocol.ts";
15
- export { LiveState, type LiveStateSubscription } from "./engine.ts";
16
- export type { LiveStateRpc, LiveStateSubscriptionHandle } from "./types.ts";
17
- export { disposeIgnoredRpcResult, isThenable, retainCallback, type RetainedCallback, } from "./retain.ts";
18
- /**
19
- * Expose mutable server state as a read-only Cap'n Web capability.
20
- * Pass an in-memory `LiveState`, or a stream-processor registry whose engine
21
- * must hydrate before its first snapshot.
22
- */
23
- export declare class LiveStateRpcTarget<State extends object> extends RpcTarget implements LiveStateRpc<State> {
24
- #private;
25
- constructor(source: LiveStateSource<State> | RefreshingLiveStateSource<State>);
26
- get(): Promise<State>;
27
- subscribe(onUpdate: (update: LiveUpdate<State>) => unknown, options?: LiveStateSubscriptionOptions): Promise<LiveStateSubscriptionRpcTarget>;
28
- }
29
- /**
30
- * The wire handle for one subscription — `ping`/`unsubscribe` over RPC.
31
- * Exported for relays that build their subscription OUTSIDE a `LiveState`
32
- * engine (the worker-local liveState-socket relay) but must hand back the
33
- * same handle shape `LiveStateRpcTarget.subscribe` does.
34
- */
35
- export declare class LiveStateSubscriptionRpcTarget extends RpcTarget implements LiveStateSubscriptionHandle {
36
- #private;
37
- constructor(subscription: LiveStateSubscription);
38
- ping(): boolean;
39
- unsubscribe(): void;
40
- [Symbol.dispose](): void;
41
- }
@@ -1,87 +0,0 @@
1
- /**
2
- * Wire types for the live-state channel: what a server engine pushes down a
3
- * subscription. A subscription always delivers one `snapshot` first (the full
4
- * current state), then a stream of `patch`es — each the minimal structural diff
5
- * since the previous revision. `useLiveState` reassembles these into the live
6
- * value, so feature code never touches these types directly.
7
- *
8
- * See `diff.ts` for how patches are produced (`diff`) and applied (`applyPatch`).
9
- */
10
- /**
11
- * A structural patch turning a previous JSON value into the next one. Three
12
- * shapes, discriminated by `set`, `array`, or an object patch:
13
- * - `{ set }` — replace this position wholesale. Used for primitives,
14
- * `null`, type changes,
15
- * and newly-added object keys.
16
- * - `{ fields?, drop? }` — descend into a plain object: `fields` maps each
17
- * changed key to its own patch; `drop` lists keys that disappeared. At least
18
- * one is present (an empty descend never gets emitted).
19
- * - `{ array }` — patch changed positions and set the resulting length. Kept
20
- * elements retain their identity, including immutable text blocks inside a
21
- * changed step. This form is sent only to subscribers requesting version 2.
22
- */
23
- export type LiveStatePatch = {
24
- set: unknown;
25
- } | {
26
- array: {
27
- length: number;
28
- items: [number, LiveStatePatch][];
29
- };
30
- } | {
31
- fields?: Record<string, LiveStatePatch>;
32
- drop?: string[];
33
- };
34
- /** Explicit codec negotiation keeps already-open clients valid across deploys. */
35
- export type LiveStateSubscriptionOptions = {
36
- patchVersion?: 2 | 3;
37
- };
38
- /**
39
- * Version 3 addresses existing object fields by their sorted baseline position;
40
- * new fields use `+name`. Arrays use indices and an optional `#` length.
41
- * Primitives replace directly, `[value]` replaces other values, `[length, text]`
42
- * appends to a string, and `[]` deletes an object field. No dictionary survives
43
- * an update: every address refers to the acknowledged baseline of that patch.
44
- */
45
- export type CompactLiveStatePatch = string | number | boolean | null | [] | [unknown] | [number, string] | {
46
- [address: string]: CompactLiveStatePatch;
47
- };
48
- /** A transient reader's position; a new engine incarnation always has a new epoch. */
49
- export type LiveStateCursor = {
50
- epoch: string;
51
- revision: number;
52
- };
53
- /** A pull transports one delta, a fresh snapshot, or no change. No callback is retained. */
54
- export type LiveStateRead<State> = {
55
- epoch: string;
56
- update: LiveUpdate<State> | null;
57
- };
58
- /**
59
- * One message pushed down a live-state subscription. The first is always a
60
- * `snapshot` (a resync sends a fresh one); every message after carries only the
61
- * diff from revision `from` to `to`. Revisions are monotonic for the life of one
62
- * subscription, so a gap (`from` ≠ the client's revision) means a message was
63
- * missed and the client should resubscribe.
64
- *
65
- * `State` is asserted by the caller of `useLiveState` — the wire itself is
66
- * structure-agnostic.
67
- */
68
- export type LiveUpdate<State = unknown> = {
69
- type: "snapshot";
70
- revision: number;
71
- state: State;
72
- } | {
73
- type: "patch";
74
- from: number;
75
- to: number;
76
- patch: LiveStatePatch;
77
- } | {
78
- s: [revision: number, state: State];
79
- } | {
80
- p: [from: number, to: number, patch: CompactLiveStatePatch];
81
- };
82
- export declare function isLiveStateSnapshot<State>(update: LiveUpdate<State>): update is Extract<LiveUpdate<State>, {
83
- type: "snapshot";
84
- } | {
85
- s: unknown;
86
- }>;
87
- export declare function liveStateRevision(update: LiveUpdate): number;
@@ -1,23 +0,0 @@
1
- /** An RPC callback after retention: still callable, plus disposable and (best-effort) broken-transport aware. */
2
- export type RetainedCallback<Arg> = ((arg: Arg) => unknown) & Disposable & {
3
- onRpcBroken?(handler: (error: unknown) => void): void;
4
- };
5
- /**
6
- * Retain a single-argument RPC callback so it survives past the call that
7
- * carried it. `dup()` duplicates the underlying remote stub (that dup is what
8
- * `[Symbol.dispose]` releases); `onRpcBroken` is forwarded defensively — Cap'n
9
- * Web stubs expose no own property descriptors and a Workers RPC property access
10
- * can fabricate a pipelined method that rejects at call time, so we wire whatever
11
- * the stub claims and swallow registration failures. `onRpcBroken` is only a
12
- * prompt hint; callers that need a terminal verdict must model one explicitly
13
- * (for example, the durable wake lane's independent settlement capability).
14
- */
15
- export declare function retainCallback<Arg>(callback: (arg: Arg) => unknown): RetainedCallback<Arg>;
16
- /** Thenable probe: RPC stubs and their call results are thenable-shaped. */
17
- export declare function isThenable(value: unknown): value is PromiseLike<unknown>;
18
- /**
19
- * Dispose the result of an RPC call whose value the caller ignores. Reading a
20
- * Cap'n Web / Workers RPC method yields a disposable stub even when unused, and
21
- * dropping it without disposal leaks the remote reference.
22
- */
23
- export declare function disposeIgnoredRpcResult(result: unknown): void;
@@ -1,20 +0,0 @@
1
- import type { LiveUpdate } from "./protocol.ts";
2
- /**
3
- * The client half of the live-state channel: a tiny external store that folds
4
- * wire updates (one snapshot, then patches) back into the live value. The
5
- * server's `LiveState` engine is the producing half; `useLiveState` renders
6
- * this store via `useSyncExternalStore`.
7
- *
8
- * Revision discipline: a patch only applies when its `from` matches the held
9
- * revision. A mismatch means a message was missed (or arrived from a stale
10
- * subscription's revision line) — the store calls `resync` and holds its value
11
- * until the fresh snapshot lands, so a gap can never silently corrupt state.
12
- */
13
- export type LiveStateStore<State> = {
14
- getState: () => State | undefined;
15
- subscribe: (listener: () => void) => () => void;
16
- reset: () => void;
17
- /** Fold one wire update into the held value; a revision gap means a missed patch — resync. */
18
- apply: (update: LiveUpdate<State>, resync: () => void) => void;
19
- };
20
- export declare function createLiveStateStore<State>(): LiveStateStore<State>;
@@ -1,11 +0,0 @@
1
- import type { LiveStateSubscriptionOptions, LiveUpdate } from "./protocol.ts";
2
- /** Owned handle for one live-state subscription. */
3
- export type LiveStateSubscriptionHandle = Disposable & {
4
- ping(): boolean | Promise<boolean>;
5
- unsubscribe(): void;
6
- };
7
- /** Read-only live value exposed across a Cap'n Web capability boundary. */
8
- export interface LiveStateRpc<State = unknown> {
9
- get(): Promise<State>;
10
- subscribe(onUpdate: (update: LiveUpdate<State>) => unknown, options?: LiveStateSubscriptionOptions): Promise<LiveStateSubscriptionHandle>;
11
- }
@@ -1,45 +0,0 @@
1
- import { type ReactNode } from "react";
2
- import type { LiveStateRpc } from "./live-state/types.ts";
3
- export type CapnWebRoot = object & Partial<Disposable> & {
4
- onRpcBroken?(callback: (error?: unknown) => void): void;
5
- };
6
- export type MakeCapnWebConnection<Root extends CapnWebRoot> = () => Root | PromiseLike<Root>;
7
- export type LiveStateStatus = "connecting" | "live" | "error";
8
- type ConnectionSnapshot = {
9
- error?: string;
10
- generation: number;
11
- reconnect: () => void;
12
- root?: CapnWebRoot;
13
- /** Stable for one connection factory, across all of that factory's reconnects. */
14
- scope: object | undefined;
15
- status: "connecting" | "connected" | "error";
16
- };
17
- /**
18
- * Own one reconnectable Cap'n Web root for a React subtree. The factory is the
19
- * only transport policy: it can dial a WebSocket directly or duplicate a root
20
- * from a lower-level shared connection keeper. Broken roots are disposed and
21
- * replaced with bounded exponential backoff.
22
- */
23
- export declare function CapnWebProvider<Root extends CapnWebRoot>({ children, makeConnection, }: {
24
- children?: ReactNode;
25
- makeConnection: MakeCapnWebConnection<Root>;
26
- }): import("react").FunctionComponentElement<import("react").ProviderProps<ConnectionSnapshot | undefined>>;
27
- /** The current provider root, undefined while its connection is being replaced. */
28
- export declare function useCapnWebRoot<Root extends CapnWebRoot>(): Root | undefined;
29
- type LiveStateOptions<Root extends CapnWebRoot> = {
30
- enabled?: boolean;
31
- makeConnection?: MakeCapnWebConnection<Root>;
32
- root?: Root | null;
33
- };
34
- /**
35
- * Render a selected slice of any LiveStateRpc reachable from the provider root.
36
- * Pass `{ root }` to borrow an explicit root instead; borrowed roots are never
37
- * disposed or reconnected by this hook.
38
- */
39
- export declare function useLiveState<Root extends CapnWebRoot, State, Selected = State>(live: (root: Root) => LiveStateRpc<State>, selector?: (state: State) => Selected, deps?: unknown[], options?: LiveStateOptions<Root>): {
40
- error?: string;
41
- refresh: () => void;
42
- status: LiveStateStatus;
43
- value: Selected | undefined;
44
- };
45
- export {};