@loomwork/ui-hydration 0.0.0-stage → 0.1.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 (179) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +398 -2
  4. package/dist/cache.d.ts +71 -0
  5. package/dist/cache.d.ts.map +1 -0
  6. package/dist/cache.js +157 -0
  7. package/dist/cache.js.map +1 -0
  8. package/dist/chatSource.d.ts +105 -0
  9. package/dist/chatSource.d.ts.map +1 -0
  10. package/dist/chatSource.js +259 -0
  11. package/dist/chatSource.js.map +1 -0
  12. package/dist/client.d.ts +17 -0
  13. package/dist/client.d.ts.map +1 -0
  14. package/dist/client.js +36 -0
  15. package/dist/client.js.map +1 -0
  16. package/dist/contentRefs.d.ts +78 -0
  17. package/dist/contentRefs.d.ts.map +1 -0
  18. package/dist/contentRefs.js +129 -0
  19. package/dist/contentRefs.js.map +1 -0
  20. package/dist/controller.d.ts +228 -0
  21. package/dist/controller.d.ts.map +1 -0
  22. package/dist/controller.js +454 -0
  23. package/dist/controller.js.map +1 -0
  24. package/dist/dataProvider.d.ts +53 -0
  25. package/dist/dataProvider.d.ts.map +1 -0
  26. package/dist/dataProvider.js +77 -0
  27. package/dist/dataProvider.js.map +1 -0
  28. package/dist/esm/cache.js +151 -0
  29. package/dist/esm/cache.js.map +1 -0
  30. package/dist/esm/chatSource.js +254 -0
  31. package/dist/esm/chatSource.js.map +1 -0
  32. package/dist/esm/client.js +15 -0
  33. package/dist/esm/client.js.map +1 -0
  34. package/dist/esm/contentRefs.js +119 -0
  35. package/dist/esm/contentRefs.js.map +1 -0
  36. package/dist/esm/controller.js +449 -0
  37. package/dist/esm/controller.js.map +1 -0
  38. package/dist/esm/dataProvider.js +72 -0
  39. package/dist/esm/dataProvider.js.map +1 -0
  40. package/dist/esm/index.js +15 -0
  41. package/dist/esm/index.js.map +1 -0
  42. package/dist/esm/invoker.js +2 -0
  43. package/dist/esm/invoker.js.map +1 -0
  44. package/dist/esm/invokers.js +310 -0
  45. package/dist/esm/invokers.js.map +1 -0
  46. package/dist/esm/loomEffectProvider.js +96 -0
  47. package/dist/esm/loomEffectProvider.js.map +1 -0
  48. package/dist/esm/params.js +207 -0
  49. package/dist/esm/params.js.map +1 -0
  50. package/dist/esm/path.js +24 -0
  51. package/dist/esm/path.js.map +1 -0
  52. package/dist/esm/plan.js +190 -0
  53. package/dist/esm/plan.js.map +1 -0
  54. package/dist/esm/projection.js +230 -0
  55. package/dist/esm/projection.js.map +1 -0
  56. package/dist/esm/provider.js +416 -0
  57. package/dist/esm/provider.js.map +1 -0
  58. package/dist/esm/repair.js +53 -0
  59. package/dist/esm/repair.js.map +1 -0
  60. package/dist/esm/reshape.js +156 -0
  61. package/dist/esm/reshape.js.map +1 -0
  62. package/dist/esm/restricted.js +54 -0
  63. package/dist/esm/restricted.js.map +1 -0
  64. package/dist/esm/scheduler.js +247 -0
  65. package/dist/esm/scheduler.js.map +1 -0
  66. package/dist/esm/select.js +18 -0
  67. package/dist/esm/select.js.map +1 -0
  68. package/dist/esm/shape.js +34 -0
  69. package/dist/esm/shape.js.map +1 -0
  70. package/dist/esm/split/client.js +309 -0
  71. package/dist/esm/split/client.js.map +1 -0
  72. package/dist/esm/split/index.js +3 -0
  73. package/dist/esm/split/index.js.map +1 -0
  74. package/dist/esm/split/server.js +488 -0
  75. package/dist/esm/split/server.js.map +1 -0
  76. package/dist/esm/split/shared.js +13 -0
  77. package/dist/esm/split/shared.js.map +1 -0
  78. package/dist/index.d.ts +29 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +63 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/invoker.d.ts +10 -0
  83. package/dist/invoker.d.ts.map +1 -0
  84. package/dist/invoker.js +3 -0
  85. package/dist/invoker.js.map +1 -0
  86. package/dist/invokers.d.ts +36 -0
  87. package/dist/invokers.d.ts.map +1 -0
  88. package/dist/invokers.js +315 -0
  89. package/dist/invokers.js.map +1 -0
  90. package/dist/loomEffectProvider.d.ts +67 -0
  91. package/dist/loomEffectProvider.d.ts.map +1 -0
  92. package/dist/loomEffectProvider.js +101 -0
  93. package/dist/loomEffectProvider.js.map +1 -0
  94. package/dist/params.d.ts +103 -0
  95. package/dist/params.d.ts.map +1 -0
  96. package/dist/params.js +221 -0
  97. package/dist/params.js.map +1 -0
  98. package/dist/path.d.ts +12 -0
  99. package/dist/path.d.ts.map +1 -0
  100. package/dist/path.js +28 -0
  101. package/dist/path.js.map +1 -0
  102. package/dist/plan.d.ts +56 -0
  103. package/dist/plan.d.ts.map +1 -0
  104. package/dist/plan.js +199 -0
  105. package/dist/plan.js.map +1 -0
  106. package/dist/projection.d.ts +122 -0
  107. package/dist/projection.d.ts.map +1 -0
  108. package/dist/projection.js +238 -0
  109. package/dist/projection.js.map +1 -0
  110. package/dist/provider.d.ts +152 -0
  111. package/dist/provider.d.ts.map +1 -0
  112. package/dist/provider.js +421 -0
  113. package/dist/provider.js.map +1 -0
  114. package/dist/repair.d.ts +18 -0
  115. package/dist/repair.d.ts.map +1 -0
  116. package/dist/repair.js +57 -0
  117. package/dist/repair.js.map +1 -0
  118. package/dist/reshape.d.ts +32 -0
  119. package/dist/reshape.d.ts.map +1 -0
  120. package/dist/reshape.js +164 -0
  121. package/dist/reshape.js.map +1 -0
  122. package/dist/restricted.d.ts +21 -0
  123. package/dist/restricted.d.ts.map +1 -0
  124. package/dist/restricted.js +61 -0
  125. package/dist/restricted.js.map +1 -0
  126. package/dist/scheduler.d.ts +82 -0
  127. package/dist/scheduler.d.ts.map +1 -0
  128. package/dist/scheduler.js +254 -0
  129. package/dist/scheduler.js.map +1 -0
  130. package/dist/select.d.ts +34 -0
  131. package/dist/select.d.ts.map +1 -0
  132. package/dist/select.js +21 -0
  133. package/dist/select.js.map +1 -0
  134. package/dist/shape.d.ts +3 -0
  135. package/dist/shape.d.ts.map +1 -0
  136. package/dist/shape.js +37 -0
  137. package/dist/shape.js.map +1 -0
  138. package/dist/split/client.d.ts +132 -0
  139. package/dist/split/client.d.ts.map +1 -0
  140. package/dist/split/client.js +313 -0
  141. package/dist/split/client.js.map +1 -0
  142. package/dist/split/index.d.ts +5 -0
  143. package/dist/split/index.d.ts.map +1 -0
  144. package/dist/split/index.js +14 -0
  145. package/dist/split/index.js.map +1 -0
  146. package/dist/split/server.d.ts +160 -0
  147. package/dist/split/server.d.ts.map +1 -0
  148. package/dist/split/server.js +496 -0
  149. package/dist/split/server.js.map +1 -0
  150. package/dist/split/shared.d.ts +6 -0
  151. package/dist/split/shared.d.ts.map +1 -0
  152. package/dist/split/shared.js +19 -0
  153. package/dist/split/shared.js.map +1 -0
  154. package/package.json +77 -3
  155. package/src/cache.ts +211 -0
  156. package/src/chatSource.ts +374 -0
  157. package/src/client.ts +46 -0
  158. package/src/contentRefs.ts +195 -0
  159. package/src/controller.ts +708 -0
  160. package/src/dataProvider.ts +141 -0
  161. package/src/index.ts +86 -0
  162. package/src/invoker.ts +14 -0
  163. package/src/invokers.ts +348 -0
  164. package/src/loomEffectProvider.ts +136 -0
  165. package/src/params.ts +314 -0
  166. package/src/path.ts +26 -0
  167. package/src/plan.ts +197 -0
  168. package/src/projection.ts +297 -0
  169. package/src/provider.ts +657 -0
  170. package/src/repair.ts +70 -0
  171. package/src/reshape.ts +193 -0
  172. package/src/restricted.ts +69 -0
  173. package/src/scheduler.ts +284 -0
  174. package/src/select.ts +59 -0
  175. package/src/shape.ts +39 -0
  176. package/src/split/client.ts +449 -0
  177. package/src/split/index.ts +18 -0
  178. package/src/split/server.ts +746 -0
  179. package/src/split/shared.ts +18 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reshape.js","sourceRoot":"","sources":["../../src/reshape.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { effectiveViewer, isBroadcast, mayView, } from "@loomwork/ui-core";
2
+ // ── Viewer enforcement at the data boundary ───────────────────────────────────
3
+ // Hydration is where data actually flows, so it is the second place a binding's `sensitivity`
4
+ // is enforced (the first is `compile`, which redacts the node). A handle whose strictest class the
5
+ // viewer may not see is never planned, never invoked, never cached, never served: its provider
6
+ // is not called at all. FAIL-CLOSED: no viewer is a viewer with no clearance; unclassified handles
7
+ // are unaffected either way. See `@loomwork/ui-core`'s `viewer.ts`.
8
+ /**
9
+ * What the store (and so the viewer) is told about a refused handle. A fixed text: it names no
10
+ * handle, class, tool or argument, so refusing leaks nothing beyond "this is restricted".
11
+ */
12
+ export const restrictedFinding = () => ({
13
+ code: "restricted",
14
+ severity: "error",
15
+ message: "this data is restricted for the current viewer",
16
+ });
17
+ /** The advisory for classified handles with no viewer supplied (they are all refused). */
18
+ export const viewerNotSuppliedFinding = () => ({
19
+ code: "viewer-not-supplied",
20
+ severity: "warn",
21
+ message: "the experience binds classified handles and no viewer was supplied: they are refused (no viewer is the most restrictive viewer)",
22
+ });
23
+ /** Split an inventory into the handles a viewer may load and the ones it may not. */
24
+ export function partitionByViewer(uses, viewer) {
25
+ const allowed = [];
26
+ const restricted = [];
27
+ for (const use of uses)
28
+ (mayView(viewer, use.sensitivity) ? allowed : restricted).push(use);
29
+ const classified = uses.some((u) => u.sensitivity !== undefined);
30
+ return {
31
+ allowed,
32
+ restricted,
33
+ advisory: classified && viewer === undefined ? [viewerNotSuppliedFinding()] : [],
34
+ };
35
+ }
36
+ /**
37
+ * A copy of the viewer holding only a clearance read once; a throwing getter reads as none. For a
38
+ * broadcast `audience` the result is the audience's viewer (no clearance, whoever asked: the
39
+ * viewer is not even read), so a handle compile withheld for the audience is refused here too.
40
+ */
41
+ export function snapshotViewer(viewer, audience) {
42
+ if (isBroadcast(audience))
43
+ return effectiveViewer(undefined, audience);
44
+ if (viewer === undefined)
45
+ return undefined;
46
+ try {
47
+ const clearance = viewer.clearance;
48
+ return clearance === undefined ? {} : { clearance };
49
+ }
50
+ catch {
51
+ return {};
52
+ }
53
+ }
54
+ //# sourceMappingURL=restricted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restricted.js","sourceRoot":"","sources":["../../src/restricted.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,eAAe,EACf,WAAW,EACX,OAAO,GACR,MAAM,mBAAmB,CAAC;AAE3B,iFAAiF;AACjF,8FAA8F;AAC9F,mGAAmG;AACnG,+FAA+F;AAC/F,mGAAmG;AACnG,oEAAoE;AAEpE;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAY,EAAE,CAAC,CAAC;IAC/C,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,gDAAgD;CAC1D,CAAC,CAAC;AAEH,0FAA0F;AAC1F,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAY,EAAE,CAAC,CAAC;IACtD,IAAI,EAAE,qBAAqB;IAC3B,QAAQ,EAAE,MAAM;IAChB,OAAO,EACL,iIAAiI;CACpI,CAAC,CAAC;AAEH,qFAAqF;AACrF,MAAM,UAAU,iBAAiB,CAC/B,IAA0B,EAC1B,MAA0B;IAE1B,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,IAAI;QAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5F,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC;IACjE,OAAO;QACL,OAAO;QACP,UAAU;QACV,QAAQ,EAAE,UAAU,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,wBAAwB,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;KACjF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,MAA0B,EAC1B,QAAmB;IAEnB,IAAI,WAAW,CAAC,QAAQ,CAAC;QAAE,OAAO,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACvE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QACnC,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,247 @@
1
+ export const defaultTimer = (fn, ms) => {
2
+ const t = setTimeout(fn, ms);
3
+ return () => clearTimeout(t);
4
+ };
5
+ /** NUL: cannot occur in a handle or a hash, so joined fingerprints never collide. */
6
+ export const KEY_SEP = String.fromCharCode(0);
7
+ export const disposedFinding = (what) => ({
8
+ code: "disposed",
9
+ severity: "error",
10
+ message: `the hydration controller is disposed; ${what} does nothing`,
11
+ });
12
+ export const tooDeep = (experienceId, max) => ({
13
+ code: "tree-too-deep",
14
+ severity: "error",
15
+ message: `experience "${experienceId}" exceeds MAX_TREE_DEPTH (${max})`,
16
+ });
17
+ export class HandleScheduler {
18
+ store;
19
+ hooks;
20
+ setTimer;
21
+ batchWindowMs;
22
+ inflight = new Map();
23
+ /**
24
+ * P1 jobs waiting for the batch timer, ONE per handle: a question changed inside the window
25
+ * replaces the queued one (the old one would otherwise start first and wedge the new one).
26
+ */
27
+ pending = new Map();
28
+ cancelBatch;
29
+ lazy = new Map();
30
+ /** handle → fingerprint of the job it was last STARTED with. Pruned with the handle. */
31
+ loaded = new Map();
32
+ disposed = false;
33
+ constructor(store, hooks, setTimer = defaultTimer, batchWindowMs = 50) {
34
+ this.store = store;
35
+ this.hooks = hooks;
36
+ this.setTimer = setTimer;
37
+ this.batchWindowMs = batchWindowMs;
38
+ }
39
+ get isDisposed() {
40
+ return this.disposed;
41
+ }
42
+ /** Schedule by priority; a job whose question is already answered (or being answered) is skipped. */
43
+ schedule(jobs) {
44
+ if (this.disposed)
45
+ return;
46
+ // One group for every job this call starts now (a P1 batch and a markVisible get their own).
47
+ const now = this.lazyGroup();
48
+ for (const job of jobs)
49
+ this.scheduleOne(job, now);
50
+ }
51
+ /** Keep only these handles: abort, dequeue, forget and unpublish every other one. */
52
+ retain(keep) {
53
+ const drop = new Set();
54
+ for (const handle of [
55
+ ...this.inflight.keys(),
56
+ ...this.lazy.keys(),
57
+ ...this.pending.keys(),
58
+ ...this.store.handles(),
59
+ ])
60
+ if (!keep.has(handle))
61
+ drop.add(handle);
62
+ if (drop.size === 0)
63
+ return;
64
+ for (const handle of drop) {
65
+ this.inflight.get(handle)?.abort();
66
+ this.inflight.delete(handle);
67
+ this.lazy.delete(handle);
68
+ this.pending.delete(handle);
69
+ this.loaded.delete(handle);
70
+ if (this.store.status(handle) !== undefined)
71
+ this.store.remove(handle);
72
+ }
73
+ }
74
+ /**
75
+ * Ask again even if already asked: each in-flight load is superseded and a fresh one starts at
76
+ * once (one group). A lazy job stays lazy — its status untouched, its last value on screen.
77
+ */
78
+ reload(jobs) {
79
+ if (this.disposed)
80
+ return;
81
+ const group = this.lazyGroup();
82
+ for (const job of jobs) {
83
+ this.inflight.get(job.handle)?.abort();
84
+ this.inflight.delete(job.handle);
85
+ this.pending.delete(job.handle); // started below (or re-queued lazy): not a second time
86
+ if (job.priority === "P2") {
87
+ this.lazy.set(job.handle, job);
88
+ continue;
89
+ }
90
+ this.start(job, group()).catch(() => { });
91
+ }
92
+ }
93
+ /** The surface reports a lazy (P2) widget entered the viewport. */
94
+ markVisible(handle) {
95
+ if (this.disposed)
96
+ return;
97
+ const job = this.lazy.get(handle);
98
+ if (!job)
99
+ return;
100
+ this.lazy.delete(handle);
101
+ this.start(job, this.hooks.newGroup()).catch(() => { });
102
+ }
103
+ inFlight() {
104
+ return [...this.inflight.keys()].sort();
105
+ }
106
+ /** Terminal: every in-flight or queued load ends on an error status, and nothing schedules again. */
107
+ dispose() {
108
+ if (this.disposed)
109
+ return;
110
+ this.disposed = true;
111
+ for (const [handle, ac] of this.inflight) {
112
+ ac.abort();
113
+ // The widget must not sit on a spinner forever because its controller went away.
114
+ this.store.setStatus(handle, {
115
+ state: "error",
116
+ finding: {
117
+ code: "disposed",
118
+ severity: "error",
119
+ message: `hydration for "${handle}" was disposed while in flight`,
120
+ },
121
+ });
122
+ }
123
+ this.inflight.clear();
124
+ this.cancelBatch?.();
125
+ this.cancelBatch = undefined;
126
+ for (const job of this.pending.values()) {
127
+ // Already published `pending`; leaving it there would spin the widget forever waiting on a
128
+ // batch timer that just got cancelled. Lazy jobs were never published: nothing to terminate.
129
+ this.store.setStatus(job.handle, {
130
+ state: "error",
131
+ finding: {
132
+ code: "disposed",
133
+ severity: "error",
134
+ message: `hydration for "${job.handle}" was disposed while queued`,
135
+ },
136
+ });
137
+ }
138
+ this.pending.clear();
139
+ this.lazy.clear();
140
+ this.loaded.clear();
141
+ }
142
+ /** A group made on first use, then shared: a call that starts nothing makes none. */
143
+ lazyGroup() {
144
+ let made;
145
+ return () => {
146
+ if (made === undefined)
147
+ made = { group: this.hooks.newGroup() };
148
+ return made.group;
149
+ };
150
+ }
151
+ scheduleOne(job, group) {
152
+ const st = this.store.status(job.handle)?.state;
153
+ if (this.loaded.get(job.handle) === job.fingerprint) {
154
+ // Same question, already asked: loading, loaded (an `empty` answer is an answer), or
155
+ // drifted-and-awaiting-repair.
156
+ if (st === "ready" || st === "pending" || st === "stale" || st === "empty")
157
+ return;
158
+ }
159
+ else {
160
+ // A different question for this handle: whatever is in flight answers the OLD one.
161
+ this.inflight.get(job.handle)?.abort();
162
+ this.inflight.delete(job.handle);
163
+ }
164
+ // A job queued for the batch answers the old question (or the old priority): this one owns it.
165
+ this.pending.delete(job.handle);
166
+ if (job.priority === "P2") {
167
+ this.lazy.set(job.handle, job);
168
+ return;
169
+ }
170
+ this.lazy.delete(job.handle); // promoted out of P2: the lazy entry has a new owner
171
+ if (job.priority === "P0") {
172
+ this.start(job, group()).catch(() => { });
173
+ return;
174
+ }
175
+ this.store.setStatus(job.handle, { state: "pending" });
176
+ // Keyed by handle: a changed question REPLACES the queued one rather than queueing behind it.
177
+ this.pending.set(job.handle, job);
178
+ this.cancelBatch ??= this.setTimer(() => {
179
+ this.cancelBatch = undefined;
180
+ const batch = [...this.pending.values()];
181
+ this.pending.clear();
182
+ if (batch.length === 0)
183
+ return;
184
+ const g = this.hooks.newGroup();
185
+ for (const j of batch)
186
+ this.start(j, g).catch(() => { });
187
+ }, this.batchWindowMs);
188
+ }
189
+ async start(job, group) {
190
+ const { handle } = job;
191
+ if (this.disposed)
192
+ return;
193
+ this.loaded.set(handle, job.fingerprint);
194
+ const cached = this.hooks.cached?.(job);
195
+ if (cached) {
196
+ this.inflight.delete(handle);
197
+ this.store.setValue(handle, cached.value, { state: "ready" });
198
+ return;
199
+ }
200
+ if (this.inflight.has(handle))
201
+ return;
202
+ const ac = new AbortController();
203
+ this.inflight.set(handle, ac);
204
+ try {
205
+ this.store.setStatus(handle, { state: "pending" });
206
+ const result = await this.hooks.run(job, ac.signal, group);
207
+ if (this.inflight.get(handle) !== ac || ac.signal.aborted)
208
+ return; // superseded or aborted
209
+ this.inflight.delete(handle);
210
+ this.hooks.commit?.(job, result);
211
+ if (result.state === "ready")
212
+ this.store.setValue(handle, result.value, {
213
+ state: "ready",
214
+ ...(result.finding && { finding: result.finding }),
215
+ });
216
+ else
217
+ this.store.setStatus(handle, { state: result.state, finding: result.finding });
218
+ this.hooks.published?.(job, result);
219
+ }
220
+ catch (e) {
221
+ // `run` is total by construction — but a loader or invoker that rejects with a value whose
222
+ // message getter throws, a store subscriber that throws synchronously on ANY publish here
223
+ // (including the first `pending`), or any future defect must land on the widget as an error
224
+ // status, never as an unhandled rejection that takes the host process down.
225
+ if (this.inflight.get(handle) !== ac || ac.signal.aborted)
226
+ return;
227
+ this.inflight.delete(handle);
228
+ try {
229
+ // The publish below can re-trigger the very subscriber whose throw got us here. A second
230
+ // throw must not escape: `inflight` is already cleaned up, which is the invariant
231
+ // `dispose`/`retain`/`inFlight` depend on.
232
+ this.store.setStatus(handle, {
233
+ state: "error",
234
+ finding: {
235
+ code: "hydration-internal",
236
+ severity: "error",
237
+ message: e instanceof Error ? e.message : String(e),
238
+ },
239
+ });
240
+ }
241
+ catch {
242
+ // Ignored — see comment above.
243
+ }
244
+ }
245
+ }
246
+ }
247
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { resolvePath } from "./plan";
2
+ export function jsonPathSelect(value, path) {
3
+ if (path === "" || path === "$")
4
+ return { ok: true, value };
5
+ const out = resolvePath(value, path);
6
+ if (out === undefined)
7
+ return {
8
+ ok: false,
9
+ failureKind: "selects-nothing",
10
+ finding: {
11
+ code: "reshape-failed",
12
+ severity: "error",
13
+ message: `JSONPath "${path}" selects nothing from the tool output`,
14
+ },
15
+ };
16
+ return { ok: true, value: out };
17
+ }
18
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/select.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AA2CrC,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,IAAY;IACzD,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC5D,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACrC,IAAI,GAAG,KAAK,SAAS;QACnB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,WAAW,EAAE,iBAAiB;YAC9B,OAAO,EAAE;gBACP,IAAI,EAAE,gBAAgB;gBACtB,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,aAAa,IAAI,wCAAwC;aACnE;SACF,CAAC;IACJ,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAClC,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { jsonSchemaHash } from "@loomwork/core";
2
+ const MAX_SHAPE_DEPTH = 1024;
3
+ function shapeAt(value, depth) {
4
+ if (value === null)
5
+ return "null";
6
+ const t = typeof value;
7
+ if (t === "string" || t === "number" || t === "boolean")
8
+ return t;
9
+ if (depth >= MAX_SHAPE_DEPTH) {
10
+ throw new Error(`shapeOf: depth limit exceeded (${MAX_SHAPE_DEPTH})`);
11
+ }
12
+ if (Array.isArray(value)) {
13
+ const shapes = new Map();
14
+ for (const v of value) {
15
+ const s = shapeAt(v, depth + 1);
16
+ shapes.set(JSON.stringify(s), s);
17
+ }
18
+ return [...shapes.entries()].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)).map(([, s]) => s);
19
+ }
20
+ if (t === "object") {
21
+ const out = {};
22
+ for (const [k, v] of Object.entries(value)) {
23
+ if (v !== undefined)
24
+ out[k] = shapeAt(v, depth + 1);
25
+ }
26
+ return out;
27
+ }
28
+ return t;
29
+ }
30
+ /** The output-shape fingerprint. The planner pins `ProviderSpec.outputShapeHash` with THIS function. */
31
+ export function outputShapeHashOf(value) {
32
+ return jsonSchemaHash(shapeAt(value, 0));
33
+ }
34
+ //# sourceMappingURL=shape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape.js","sourceRoot":"","sources":["../../src/shape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAQhD,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,SAAS,OAAO,CAAC,KAAc,EAAE,KAAa;IAC5C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,MAAM,CAAC,GAAG,OAAO,KAAK,CAAC;IACvB,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IAClE,IAAI,KAAK,IAAI,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,kCAAkC,eAAe,GAAG,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAClG,CAAC;IACD,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnB,MAAM,GAAG,GAA6B,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACtE,IAAI,CAAC,KAAK,SAAS;gBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC"}