@milaboratories/pl-tree 1.7.5 → 1.7.7

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 (45) hide show
  1. package/dist/accessors.cjs +297 -0
  2. package/dist/accessors.cjs.map +1 -0
  3. package/dist/accessors.d.ts +6 -6
  4. package/dist/accessors.js +288 -0
  5. package/dist/accessors.js.map +1 -0
  6. package/dist/dump.cjs +86 -0
  7. package/dist/dump.cjs.map +1 -0
  8. package/dist/dump.d.ts +1 -1
  9. package/dist/dump.js +84 -0
  10. package/dist/dump.js.map +1 -0
  11. package/dist/index.cjs +36 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.js +7 -10
  14. package/dist/index.js.map +1 -1
  15. package/dist/snapshot.cjs +88 -0
  16. package/dist/snapshot.cjs.map +1 -0
  17. package/dist/snapshot.d.ts +6 -5
  18. package/dist/snapshot.js +83 -0
  19. package/dist/snapshot.js.map +1 -0
  20. package/dist/state.cjs +631 -0
  21. package/dist/state.cjs.map +1 -0
  22. package/dist/state.d.ts +7 -5
  23. package/dist/state.js +627 -0
  24. package/dist/state.js.map +1 -0
  25. package/dist/sync.cjs +156 -0
  26. package/dist/sync.cjs.map +1 -0
  27. package/dist/sync.d.ts +2 -2
  28. package/dist/sync.js +151 -0
  29. package/dist/sync.js.map +1 -0
  30. package/dist/synchronized_tree.cjs +235 -0
  31. package/dist/synchronized_tree.cjs.map +1 -0
  32. package/dist/synchronized_tree.d.ts +4 -4
  33. package/dist/synchronized_tree.js +214 -0
  34. package/dist/synchronized_tree.js.map +1 -0
  35. package/dist/test_utils.d.ts +2 -2
  36. package/dist/traversal_ops.d.ts +1 -1
  37. package/dist/value_and_error.cjs +20 -0
  38. package/dist/value_and_error.cjs.map +1 -0
  39. package/dist/value_and_error.js +17 -0
  40. package/dist/value_and_error.js.map +1 -0
  41. package/package.json +16 -14
  42. package/src/snapshot.test.ts +4 -3
  43. package/src/state.test.ts +6 -4
  44. package/dist/index.mjs +0 -904
  45. package/dist/index.mjs.map +0 -1
package/dist/index.mjs DELETED
@@ -1,904 +0,0 @@
1
- var M = Object.defineProperty;
2
- var U = (o, e, t) => e in o ? M(o, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[e] = t;
3
- var u = (o, e, t) => U(o, typeof e != "symbol" ? e + "" : e, t);
4
- import { resourceIdToString as g, resourceTypesEqual as _, resourceTypeToString as J, isNotNullResourceId as y, NullResourceId as D, isNullResourceId as O, stringifyWithResourceId as F, isTimeoutOrCancelError as q } from "@milaboratories/pl-client";
5
- import { ChangeSource as C, KeyedChangeSource as z, PollingComputableHooks as H } from "@milaboratories/computable";
6
- import { parsePlError as V } from "@milaboratories/pl-errors";
7
- import { notEmpty as p, cachedDecode as A, cachedDeserialize as b, msToHumanReadable as j } from "@milaboratories/ts-helpers";
8
- import Y from "denque";
9
- import * as G from "node:timers/promises";
10
- function oe(o, e) {
11
- if (o !== void 0)
12
- return K(o, e);
13
- }
14
- function K(o, e) {
15
- const t = {};
16
- return o.value !== void 0 && (t.value = e(o.value)), o.error !== void 0 && (t.error = e(o.error)), t;
17
- }
18
- class de extends Error {
19
- constructor(e) {
20
- super(e);
21
- }
22
- }
23
- function ue(o) {
24
- return typeof o == "object" && o !== null && o.__pl_tree_type_marker__ === "PlTreeEntry";
25
- }
26
- function ce(o) {
27
- return typeof o == "object" && o !== null && o.__pl_tree_type_marker__ === "PlTreeEntryAccessor";
28
- }
29
- function he(o) {
30
- return typeof o == "object" && o !== null && o.__pl_tree_type_marker__ === "PlTreeNodeAccessor";
31
- }
32
- class R {
33
- constructor(e, t) {
34
- u(this, "__pl_tree_type_marker__", "PlTreeEntry");
35
- this.accessorData = e, this.rid = t;
36
- }
37
- createAccessor(e, t) {
38
- return new T(this.accessorData, this.accessorData.treeProvider(), this.rid, {
39
- ctx: e,
40
- guard: t
41
- });
42
- }
43
- toJSON() {
44
- return this.toString();
45
- }
46
- toString() {
47
- return `[ENTRY:${g(this.rid)}]`;
48
- }
49
- }
50
- function N(o, e, t, i, n) {
51
- const d = new Q(
52
- o,
53
- e,
54
- e.get(t.ctx.watcher, i),
55
- t
56
- );
57
- if (!n.ignoreError) {
58
- const a = d.getError();
59
- if (a !== void 0)
60
- throw V(p(a.getDataAsString()), d.id, d.resourceType);
61
- }
62
- if (n.assertResourceType !== void 0 && (Array.isArray(n.assertResourceType) ? n.assertResourceType.findIndex((a) => _(a, d.resourceType)) === -1 : !_(n.assertResourceType, d.resourceType)))
63
- throw new Error(
64
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
65
- `wrong resource type ${J(d.resourceType)} but expected ${n.assertResourceType}`
66
- );
67
- return d;
68
- }
69
- class T {
70
- constructor(e, t, i, n) {
71
- u(this, "__pl_tree_type_marker__", "PlTreeEntryAccessor");
72
- this.accessorData = e, this.tree = t, this.rid = i, this.instanceData = n;
73
- }
74
- node(e = {}) {
75
- return this.instanceData.guard(), this.accessorData.hooks !== void 0 && this.instanceData.ctx.attacheHooks(this.accessorData.hooks), N(this.accessorData, this.tree, this.instanceData, this.rid, e);
76
- }
77
- }
78
- function le(o, e) {
79
- return o instanceof R ? e.accessor(o).node().resourceInfo : o;
80
- }
81
- class Q {
82
- constructor(e, t, i, n) {
83
- u(this, "__pl_tree_type_marker__", "PlTreeNodeAccessor");
84
- u(this, "onUnstableLambda", (e) => {
85
- this.instanceData.ctx.markUnstable(e);
86
- });
87
- this.accessorData = e, this.tree = t, this.resource = i, this.instanceData = n;
88
- }
89
- get id() {
90
- return this.instanceData.guard(), this.resource.id;
91
- }
92
- get originalId() {
93
- return this.instanceData.guard(), this.resource.originalResourceId;
94
- }
95
- get resourceType() {
96
- return this.instanceData.guard(), this.resource.type;
97
- }
98
- get resourceInfo() {
99
- return { id: this.id, type: this.resourceType };
100
- }
101
- getResourceFromTree(e, t) {
102
- return N(this.accessorData, this.tree, this.instanceData, e, t);
103
- }
104
- traverse(...e) {
105
- return this.traverseWithCommon({}, ...e);
106
- }
107
- traverseOrError(...e) {
108
- return this.traverseOrErrorWithCommon({}, ...e);
109
- }
110
- traverseWithCommon(e, ...t) {
111
- const i = this.traverseOrErrorWithCommon(e, ...t);
112
- if (i !== void 0) {
113
- if (!i.ok) throw i.error;
114
- return i.value;
115
- }
116
- }
117
- traverseOrErrorWithCommon(e, ...t) {
118
- let i = this;
119
- for (const n of t) {
120
- const d = typeof n == "string" ? {
121
- ...e,
122
- field: n
123
- } : { ...e, ...n }, a = i.getField(n);
124
- if (a === void 0 || d.pureFieldErrorToUndefined && a.value === void 0 && a.error !== void 0)
125
- return;
126
- if ((!d.ignoreError || a.value === void 0) && a.error !== void 0)
127
- return {
128
- ok: !1,
129
- // FIXME: in next tickets we'll allow Errors to be thrown.
130
- error: V(
131
- p(a.error.getDataAsString()),
132
- i.id,
133
- i.resourceType,
134
- d.field
135
- )
136
- };
137
- if (a.value === void 0) {
138
- if (d.errorIfFieldNotSet)
139
- return {
140
- ok: !1,
141
- error: new Error(`field have no assigned value ${d.field} of ${g(i.id)}`)
142
- };
143
- this.onUnstableLambda("unpopulated_field:" + d.field);
144
- return;
145
- }
146
- i = a.value;
147
- }
148
- return { ok: !0, value: i };
149
- }
150
- getField(e) {
151
- this.instanceData.guard();
152
- const t = typeof e == "string" ? { field: e } : e, i = this.resource.getField(this.instanceData.ctx.watcher, t, this.onUnstableLambda);
153
- if (i !== void 0)
154
- return K(i, (n) => this.getResourceFromTree(n, { ignoreError: !0 }));
155
- }
156
- getInputsLocked() {
157
- this.instanceData.guard();
158
- const e = this.resource.getInputsLocked(this.instanceData.ctx.watcher);
159
- return e || this.instanceData.ctx.markUnstable("inputs_unlocked:" + this.resourceType.name), e;
160
- }
161
- getOutputsLocked() {
162
- this.instanceData.guard();
163
- const e = this.resource.getOutputsLocked(this.instanceData.ctx.watcher);
164
- return e || this.instanceData.ctx.markUnstable("outputs_unlocked:" + this.resourceType.name), e;
165
- }
166
- getIsReadyOrError() {
167
- this.instanceData.guard();
168
- const e = this.resource.getIsReadyOrError(this.instanceData.ctx.watcher);
169
- return e || this.instanceData.ctx.markUnstable("not_ready:" + this.resourceType.name), e;
170
- }
171
- getIsFinal() {
172
- return this.instanceData.guard(), this.resource.getIsFinal(this.instanceData.ctx.watcher);
173
- }
174
- getError() {
175
- this.instanceData.guard();
176
- const e = this.resource.getError(this.instanceData.ctx.watcher);
177
- if (e !== void 0)
178
- return this.getResourceFromTree(e, {});
179
- }
180
- getData() {
181
- return this.resource.data;
182
- }
183
- getDataAsString() {
184
- return this.resource.getDataAsString();
185
- }
186
- getDataAsJson() {
187
- return this.resource.getDataAsJson();
188
- }
189
- listInputFields() {
190
- return this.instanceData.guard(), this.getInputsLocked(), this.resource.listInputFields(this.instanceData.ctx.watcher);
191
- }
192
- listOutputFields() {
193
- return this.instanceData.guard(), this.getOutputsLocked(), this.resource.listOutputFields(this.instanceData.ctx.watcher);
194
- }
195
- listDynamicFields() {
196
- return this.instanceData.guard(), this.resource.listDynamicFields(this.instanceData.ctx.watcher);
197
- }
198
- getKeyValue(e, t = !1) {
199
- this.instanceData.guard();
200
- const i = this.resource.getKeyValue(this.instanceData.ctx.watcher, e);
201
- return i === void 0 && t && this.instanceData.ctx.markUnstable("key_not_found_b:" + e), i;
202
- }
203
- /** @deprecated */
204
- getKeyValueString(e) {
205
- return this.getKeyValueAsString(e);
206
- }
207
- getKeyValueAsString(e, t = !1) {
208
- this.instanceData.guard();
209
- const i = this.resource.getKeyValueString(this.instanceData.ctx.watcher, e);
210
- return i === void 0 && t && this.instanceData.ctx.markUnstable("key_not_found_s:" + e), i;
211
- }
212
- getKeyValueAsJson(e, t = !1) {
213
- const i = this.resource.getKeyValueAsJson(this.instanceData.ctx.watcher, e);
214
- if (i === void 0) {
215
- t && this.instanceData.ctx.markUnstable("key_not_found_j:" + e);
216
- return;
217
- }
218
- return i;
219
- }
220
- /**
221
- * Can be used to pass a higher level accessor that will wrap the resource and throw its
222
- * errors on node resolution.
223
- * */
224
- toEntryAccessor() {
225
- return new T(this.accessorData, this.tree, this.id, this.instanceData);
226
- }
227
- /** Can be passed to nested computable. */
228
- persist() {
229
- return new R(this.accessorData, this.resource.id);
230
- }
231
- }
232
- class S extends Error {
233
- constructor(e) {
234
- super(e);
235
- }
236
- }
237
- class x {
238
- constructor(e, t, i, n, d, a, r) {
239
- u(this, "change", new C());
240
- this.name = e, this.type = t, this.value = i, this.error = n, this.status = d, this.valueIsFinal = a, this.resourceVersion = r;
241
- }
242
- get state() {
243
- return {
244
- name: this.name,
245
- type: this.type,
246
- status: this.status,
247
- value: this.value,
248
- error: this.error,
249
- valueIsFinal: this.valueIsFinal
250
- };
251
- }
252
- }
253
- const L = 0;
254
- class X {
255
- constructor(e, t) {
256
- /** Tracks number of other resources referencing this resource. Used to perform garbage collection in tree patching procedure */
257
- u(this, "refCount", 0);
258
- /** Increments each time resource is checked for difference with new state */
259
- u(this, "version", L);
260
- /** Set to resource version when resource state, or it's fields have changed */
261
- u(this, "dataVersion", L);
262
- u(this, "fieldsMap", /* @__PURE__ */ new Map());
263
- u(this, "kv", /* @__PURE__ */ new Map());
264
- u(this, "resourceRemoved", new C());
265
- // following change source are removed when resource is marked as final
266
- u(this, "finalChanged", new C());
267
- u(this, "resourceStateChange", new C());
268
- u(this, "lockedChange", new C());
269
- u(this, "inputAndServiceFieldListChanged", new C());
270
- u(this, "outputFieldListChanged", new C());
271
- u(this, "dynamicFieldListChanged", new C());
272
- // kvChangedGlobal? = new ChangeSource();
273
- u(this, "kvChangedPerKey", new z());
274
- u(this, "id");
275
- u(this, "originalResourceId");
276
- u(this, "kind");
277
- u(this, "type");
278
- u(this, "data");
279
- u(this, "dataAsString");
280
- u(this, "dataAsJson");
281
- u(this, "error");
282
- u(this, "inputsLocked");
283
- u(this, "outputsLocked");
284
- u(this, "resourceReady");
285
- u(this, "finalFlag");
286
- /** Set externally by the tree, using {@link FinalResourceDataPredicate} */
287
- u(this, "_finalState", !1);
288
- u(this, "logger");
289
- this.id = e.id, this.originalResourceId = e.originalResourceId, this.kind = e.kind, this.type = e.type, this.data = e.data, this.error = e.error, this.inputsLocked = e.inputsLocked, this.outputsLocked = e.outputsLocked, this.resourceReady = e.resourceReady, this.finalFlag = e.final, this.logger = t;
290
- }
291
- // TODO add logging
292
- info(e) {
293
- this.logger !== void 0 && this.logger.info(e);
294
- }
295
- warn(e) {
296
- this.logger !== void 0 && this.logger.warn(e);
297
- }
298
- get final() {
299
- return this.finalFlag;
300
- }
301
- get finalState() {
302
- return this._finalState;
303
- }
304
- get fields() {
305
- return [...this.fieldsMap.values()];
306
- }
307
- getField(e, t, i = () => {
308
- }) {
309
- var a, r, f;
310
- const n = typeof t == "string" ? { field: t } : t, d = this.fieldsMap.get(n.field);
311
- if (d === void 0) {
312
- if (n.errorIfFieldNotFound || n.errorIfFieldNotSet)
313
- throw new Error(
314
- `Field "${n.field}" not found in resource ${g(this.id)}`
315
- );
316
- if (!this.inputsLocked) (a = this.inputAndServiceFieldListChanged) == null || a.attachWatcher(e);
317
- else if (n.assertFieldType === "Service" || n.assertFieldType === "Input") {
318
- if (n.allowPermanentAbsence)
319
- return;
320
- throw new Error(`Service or input field not found ${n.field}.`);
321
- }
322
- if (!this.outputsLocked) (r = this.outputFieldListChanged) == null || r.attachWatcher(e);
323
- else if (n.assertFieldType === "Output") {
324
- if (n.allowPermanentAbsence)
325
- return;
326
- throw new Error(`Output field not found ${n.field}.`);
327
- }
328
- (f = this.dynamicFieldListChanged) == null || f.attachWatcher(e), !this._finalState && !n.stableIfNotFound && i("field_not_found:" + n.field);
329
- return;
330
- } else {
331
- if (n.assertFieldType !== void 0 && d.type !== n.assertFieldType)
332
- throw new Error(
333
- `Unexpected field type: expected ${n.assertFieldType} but got ${d.type} for the field name ${n.field}`
334
- );
335
- const l = {};
336
- return y(d.value) && (l.value = d.value), y(d.error) && (l.error = d.error), l.value === void 0 && l.error === void 0 && i("field_not_resolved:" + n.field), d.change.attachWatcher(e), l;
337
- }
338
- }
339
- getInputsLocked(e) {
340
- var t;
341
- return this.inputsLocked || (t = this.resourceStateChange) == null || t.attachWatcher(e), this.inputsLocked;
342
- }
343
- getOutputsLocked(e) {
344
- var t;
345
- return this.outputsLocked || (t = this.resourceStateChange) == null || t.attachWatcher(e), this.outputsLocked;
346
- }
347
- get isReadyOrError() {
348
- return this.error !== D || this.resourceReady || this.originalResourceId !== D;
349
- }
350
- getIsFinal(e) {
351
- var t;
352
- return (t = this.finalChanged) == null || t.attachWatcher(e), this._finalState;
353
- }
354
- getIsReadyOrError(e) {
355
- var t;
356
- return this.isReadyOrError || (t = this.resourceStateChange) == null || t.attachWatcher(e), this.isReadyOrError;
357
- }
358
- getError(e) {
359
- var t;
360
- if (O(this.error)) {
361
- (t = this.resourceStateChange) == null || t.attachWatcher(e);
362
- return;
363
- } else
364
- return this.error;
365
- }
366
- listInputFields(e) {
367
- var i;
368
- const t = [];
369
- return this.fieldsMap.forEach((n, d) => {
370
- (n.type === "Input" || n.type === "Service") && t.push(d);
371
- }), this.inputsLocked || (i = this.inputAndServiceFieldListChanged) == null || i.attachWatcher(e), t;
372
- }
373
- listOutputFields(e) {
374
- var i;
375
- const t = [];
376
- return this.fieldsMap.forEach((n, d) => {
377
- n.type === "Output" && t.push(d);
378
- }), this.outputsLocked || (i = this.outputFieldListChanged) == null || i.attachWatcher(e), t;
379
- }
380
- listDynamicFields(e) {
381
- var i;
382
- const t = [];
383
- return this.fieldsMap.forEach((n, d) => {
384
- n.type !== "Input" && n.type !== "Output" && t.push(d);
385
- }), (i = this.dynamicFieldListChanged) == null || i.attachWatcher(e), t;
386
- }
387
- getKeyValue(e, t) {
388
- var i;
389
- return (i = this.kvChangedPerKey) == null || i.attachWatcher(t, e), this.kv.get(t);
390
- }
391
- getKeyValueString(e, t) {
392
- const i = this.getKeyValue(e, t);
393
- if (i !== void 0)
394
- return A(i);
395
- }
396
- getKeyValueAsJson(e, t) {
397
- const i = this.getKeyValue(e, t);
398
- if (i !== void 0)
399
- return b(i);
400
- }
401
- getDataAsString() {
402
- if (this.data !== void 0)
403
- return this.dataAsString === void 0 && (this.dataAsString = A(this.data)), this.dataAsString;
404
- }
405
- getDataAsJson() {
406
- if (this.data !== void 0)
407
- return this.dataAsJson === void 0 && (this.dataAsJson = b(this.data)), this.dataAsJson;
408
- }
409
- verifyReadyState() {
410
- if (this.resourceReady && !this.inputsLocked)
411
- throw new Error(`ready without input or output lock: ${F(this.basicState)}`);
412
- }
413
- get basicState() {
414
- return {
415
- id: this.id,
416
- kind: this.kind,
417
- type: this.type,
418
- data: this.data,
419
- resourceReady: this.resourceReady,
420
- inputsLocked: this.inputsLocked,
421
- outputsLocked: this.outputsLocked,
422
- error: this.error,
423
- originalResourceId: this.originalResourceId,
424
- final: this.finalFlag
425
- };
426
- }
427
- get extendedState() {
428
- return {
429
- ...this.basicState,
430
- fields: this.fields,
431
- kv: Array.from(this.kv.entries()).map(([e, t]) => ({ key: e, value: t }))
432
- };
433
- }
434
- /** Called when {@link FinalResourceDataPredicate} returns true for the state. */
435
- markFinal() {
436
- this._finalState || (this._finalState = !0, p(this.finalChanged).markChanged("marked final"), this.finalChanged = void 0, this.resourceStateChange = void 0, this.dynamicFieldListChanged = void 0, this.inputAndServiceFieldListChanged = void 0, this.outputFieldListChanged = void 0, this.lockedChange = void 0, this.kvChangedPerKey = void 0);
437
- }
438
- /** Used for invalidation */
439
- markAllChanged() {
440
- var e, t, i, n, d, a, r;
441
- this.fieldsMap.forEach((f) => f.change.markChanged("marked all changed")), (e = this.finalChanged) == null || e.markChanged("marked all changed"), (t = this.resourceStateChange) == null || t.markChanged("marked all changed"), (i = this.lockedChange) == null || i.markChanged("marked all changed"), (n = this.inputAndServiceFieldListChanged) == null || n.markChanged("marked all changed"), (d = this.outputFieldListChanged) == null || d.markChanged("marked all changed"), (a = this.dynamicFieldListChanged) == null || a.markChanged("marked all changed"), (r = this.kvChangedPerKey) == null || r.markAllChanged("marked all changed"), this.resourceRemoved.markChanged("marked all changed");
442
- }
443
- }
444
- class P {
445
- constructor(e, t) {
446
- /** resource heap */
447
- u(this, "resources", /* @__PURE__ */ new Map());
448
- u(this, "resourcesAdded", new C());
449
- /** Resets to false if any invalid state transitions are registered,
450
- * after that tree will produce errors for any read or write operations */
451
- u(this, "_isValid", !0);
452
- u(this, "invalidationMessage");
453
- this.root = e, this.isFinalPredicate = t;
454
- }
455
- forEachResource(e) {
456
- this.resources.forEach((t) => e(t));
457
- }
458
- checkValid() {
459
- if (!this._isValid) throw new Error(this.invalidationMessage ?? "tree is in invalid state");
460
- }
461
- get(e, t) {
462
- this.checkValid();
463
- const i = this.resources.get(t);
464
- if (i === void 0)
465
- throw this.resourcesAdded.attachWatcher(e), new Error(`resource ${g(t)} not found in the tree`);
466
- return i.resourceRemoved.attachWatcher(e), i;
467
- }
468
- updateFromResourceData(e, t = !1) {
469
- this.checkValid();
470
- const i = [], n = [];
471
- for (const a of e) {
472
- let r = this.resources.get(a.id);
473
- const f = r == null ? void 0 : r.basicState, l = (h) => {
474
- const { fields: s, ...c } = a;
475
- throw this.invalidateTree(), new S(
476
- `Unexpected resource state transition (${h}): ${F(
477
- c
478
- )} -> ${F(f)}`
479
- );
480
- };
481
- if (r !== void 0) {
482
- r.finalState && l("resource state can be updated after it is marked as final");
483
- let h = !1;
484
- r.version += 1, r.originalResourceId !== a.originalResourceId && (r.originalResourceId !== D && l("originalResourceId can't change after it is set"), r.originalResourceId = a.originalResourceId, p(r.resourceStateChange).markChanged(`originalResourceId changed for ${g(r.id)}`), h = !0), r.error !== a.error && (y(r.error) && l("resource can't change attached error after it is set"), r.error = a.error, i.push(r.error), p(r.resourceStateChange).markChanged(`error changed for ${g(r.id)}`), h = !0);
485
- for (const s of a.fields) {
486
- let c = r.fieldsMap.get(s.name);
487
- c ? (c.type !== s.type && (c.type !== "Dynamic" && l(`field changed type ${c.type} -> ${s.type}`), p(r.dynamicFieldListChanged).markChanged(`field ${s.name} changed type from Dynamic to ${s.type} in ${g(r.id)}`), (c.type === "Input" || c.type === "Service") && (r.inputsLocked && l(
488
- `adding input field "${s.name}", while corresponding list is locked`
489
- ), p(r.inputAndServiceFieldListChanged).markChanged(`field ${s.name} changed to type ${s.type} in ${g(r.id)}`)), c.type === "Output" && (r.outputsLocked && l(
490
- `adding output field "${s.name}", while corresponding list is locked`
491
- ), p(r.outputFieldListChanged).markChanged(`field ${s.name} changed to type ${s.type} in ${g(r.id)}`)), c.type = s.type, c.change.markChanged(`field ${s.name} type changed to ${s.type} in ${g(r.id)}`), h = !0), c.value !== s.value && (y(c.value) && n.push(c.value), c.value = s.value, y(s.value) && i.push(s.value), c.change.markChanged(`field ${s.name} value changed in ${g(r.id)}`), h = !0), c.error !== s.error && (y(c.error) && n.push(c.error), c.error = s.error, y(s.error) && i.push(s.error), c.change.markChanged(`field ${s.name} error changed in ${g(r.id)}`), h = !0), c.status !== s.status && (c.status = s.status, c.change.markChanged(`field ${s.name} status changed to ${s.status} in ${g(r.id)}`), h = !0), c.valueIsFinal !== s.valueIsFinal && (c.valueIsFinal = s.valueIsFinal, c.change.markChanged(`field ${s.name} valueIsFinal changed to ${s.valueIsFinal} in ${g(r.id)}`), h = !0), c.resourceVersion = r.version) : (c = new x(
492
- s.name,
493
- s.type,
494
- s.value,
495
- s.error,
496
- s.status,
497
- s.valueIsFinal,
498
- r.version
499
- ), y(s.value) && i.push(s.value), y(s.error) && i.push(s.error), s.type === "Input" || s.type === "Service" ? (r.inputsLocked && l(
500
- `adding ${s.type} (${s.name}) field while inputs locked`
501
- ), p(r.inputAndServiceFieldListChanged).markChanged(`new ${s.type} field ${s.name} added to ${g(r.id)}`)) : s.type === "Output" ? (r.outputsLocked && l(
502
- `adding ${s.type} (${s.name}) field while outputs locked`
503
- ), p(r.outputFieldListChanged).markChanged(`new ${s.type} field ${s.name} added to ${g(r.id)}`)) : p(r.dynamicFieldListChanged).markChanged(`new ${s.type} field ${s.name} added to ${g(r.id)}`), r.fieldsMap.set(s.name, c), h = !0);
504
- }
505
- if (r.fieldsMap.forEach((s, c, m) => {
506
- s.resourceVersion !== r.version && ((s.type === "Input" || s.type === "Service" || s.type === "Output") && l(`removal of ${s.type} field ${c}`), s.change.markChanged(`dynamic field ${c} removed from ${g(r.id)}`), m.delete(c), y(s.value) && n.push(s.value), y(s.error) && n.push(s.error), p(r.dynamicFieldListChanged).markChanged(`dynamic field ${c} removed from ${g(r.id)}`));
507
- }), r.inputsLocked !== a.inputsLocked && (r.inputsLocked && l("inputs unlocking is not permitted"), r.inputsLocked = a.inputsLocked, p(r.lockedChange).markChanged(`inputs locked for ${g(r.id)}`), h = !0), r.outputsLocked !== a.outputsLocked && (r.outputsLocked && l("outputs unlocking is not permitted"), r.outputsLocked = a.outputsLocked, p(r.lockedChange).markChanged(`outputs locked for ${g(r.id)}`), h = !0), r.resourceReady !== a.resourceReady) {
508
- const s = r.resourceReady;
509
- r.resourceReady = a.resourceReady, r.verifyReadyState(), r.isReadyOrError || l(
510
- `resource can't lose it's ready or error state (ready state before ${s})`
511
- ), p(r.resourceStateChange).markChanged(`ready flag changed to ${a.resourceReady} for ${g(r.id)}`), h = !0;
512
- }
513
- for (const s of a.kv) {
514
- const c = r.kv.get(s.key);
515
- c === void 0 ? (r.kv.set(s.key, s.value), p(r.kvChangedPerKey).markChanged(s.key, `kv added for ${g(r.id)}: ${s.key}`)) : Buffer.compare(c, s.value) !== 0 && (r.kv.set(s.key, s.value), p(r.kvChangedPerKey).markChanged(s.key, `kv changed for ${g(r.id)}: ${s.key}`));
516
- }
517
- if (r.kv.size > a.kv.length) {
518
- const s = new Set(a.kv.map((c) => c.key));
519
- r.kv.forEach((c, m, k) => {
520
- s.has(m) || (k.delete(m), p(r.kvChangedPerKey).markChanged(m, `kv deleted for ${g(r.id)}: ${m}`));
521
- });
522
- }
523
- h && (r.dataVersion = r.version, this.isFinalPredicate(r) && r.markFinal());
524
- } else {
525
- r = new X(a), r.verifyReadyState(), y(r.error) && i.push(r.error);
526
- for (const h of a.fields) {
527
- const s = new x(
528
- h.name,
529
- h.type,
530
- h.value,
531
- h.error,
532
- h.status,
533
- h.valueIsFinal,
534
- L
535
- );
536
- y(h.value) && i.push(h.value), y(h.error) && i.push(h.error), r.fieldsMap.set(h.name, s);
537
- }
538
- for (const h of a.kv) r.kv.set(h.key, h.value);
539
- this.isFinalPredicate(r) && r.markFinal(), this.resources.set(r.id, r), this.resourcesAdded.markChanged(`new resource ${g(r.id)} added`);
540
- }
541
- }
542
- for (const a of i) {
543
- const r = this.resources.get(a);
544
- if (!r)
545
- throw this.invalidateTree(), new S(`orphan resource ${a}`);
546
- r.refCount++;
547
- }
548
- let d = n;
549
- for (; d.length > 0; ) {
550
- const a = [];
551
- for (const r of d) {
552
- const f = this.resources.get(r);
553
- if (!f)
554
- throw this.invalidateTree(), new S(`orphan resource ${r}`);
555
- f.refCount--, f.refCount === 0 && f.id !== this.root && (f.fieldsMap.forEach((l) => {
556
- y(l.value) && a.push(l.value), y(l.error) && a.push(l.error), l.change.markChanged(`field ${l.name} removed during garbage collection of ${g(f.id)}`);
557
- }), y(f.error) && a.push(f.error), f.resourceRemoved.markChanged(`resource removed during garbage collection: ${g(f.id)}`), this.resources.delete(r));
558
- }
559
- d = a;
560
- }
561
- if (!t) {
562
- for (const a of e)
563
- if (!this.resources.has(a.id))
564
- throw this.invalidateTree(), new S(`orphan input resource ${a.id}`);
565
- }
566
- }
567
- /** @deprecated use "entry" instead */
568
- accessor(e = this.root) {
569
- return this.checkValid(), this.entry(e);
570
- }
571
- entry(e = this.root) {
572
- return this.checkValid(), new R({ treeProvider: () => this }, e);
573
- }
574
- invalidateTree(e) {
575
- this._isValid = !1, this.invalidationMessage = e, this.resources.forEach((t) => {
576
- t.markAllChanged();
577
- });
578
- }
579
- dumpState() {
580
- return Array.from(this.resources.values()).map((e) => e.extendedState);
581
- }
582
- }
583
- function Z(o, e) {
584
- const t = [], i = /* @__PURE__ */ new Set();
585
- return o.forEachResource((n) => {
586
- n.finalState ? i.add(n.id) : t.push(n.id);
587
- }), t.length === 0 && i.size === 0 && t.push(o.root), { seedResources: t, finalResources: i, pruningFunction: e };
588
- }
589
- function $() {
590
- return {
591
- requests: 0,
592
- roundTrips: 0,
593
- retrievedResources: 0,
594
- retrievedFields: 0,
595
- retrievedKeyValues: 0,
596
- retrievedResourceDataBytes: 0,
597
- retrievedKeyValueBytes: 0,
598
- prunedFields: 0,
599
- finalResourcesSkipped: 0,
600
- millisSpent: 0
601
- };
602
- }
603
- function fe(o) {
604
- let e = `Requests: ${o.requests}
605
- `;
606
- return e += `Total time: ${j(o.millisSpent)}
607
- `, e += `Round-trips: ${o.roundTrips}
608
- `, e += `Resources: ${o.retrievedResources}
609
- `, e += `Fields: ${o.retrievedFields}
610
- `, e += `KV: ${o.retrievedKeyValues}
611
- `, e += `Data Bytes: ${o.retrievedResourceDataBytes}
612
- `, e += `KV Bytes: ${o.retrievedKeyValueBytes}
613
- `, e += `Pruned fields: ${o.prunedFields}
614
- `, e += `Final resources skipped: ${o.finalResourcesSkipped}`, e;
615
- }
616
- async function ee(o, e, t) {
617
- var m;
618
- const i = Date.now();
619
- t && t.requests++;
620
- const { seedResources: n, finalResources: d, pruningFunction: a } = e, r = new Y();
621
- let f = !0, l = 0;
622
- const h = /* @__PURE__ */ new Set(), s = (k) => {
623
- if (O(k) || h.has(k)) return;
624
- if (d.has(k)) {
625
- t && t.finalResourcesSkipped++;
626
- return;
627
- }
628
- h.add(k);
629
- const v = o.getResourceDataIfExists(k, !0), w = o.listKeyValuesIfResourceExists(k), W = f;
630
- f && (f = !1), r.push(
631
- (async () => {
632
- const [I, E] = await Promise.all([v, w]);
633
- if (W && (l++, f = !0), I !== void 0) {
634
- if (E === void 0) throw new Error("Inconsistent replies");
635
- return { ...I, kv: E };
636
- }
637
- })()
638
- );
639
- };
640
- n.forEach((k) => s(k));
641
- const c = [];
642
- for (; ; ) {
643
- const k = r.shift();
644
- if (k === void 0)
645
- break;
646
- let v = await k;
647
- if (v !== void 0) {
648
- if (a !== void 0) {
649
- const w = a(v);
650
- t && (t.prunedFields += v.fields.length - w.length), v = { ...v, fields: w };
651
- }
652
- s(v.error);
653
- for (const w of v.fields)
654
- s(w.value), s(w.error);
655
- if (t) {
656
- t.retrievedResources++, t.retrievedFields += v.fields.length, t.retrievedKeyValues += v.kv.length, t.retrievedResourceDataBytes += ((m = v.data) == null ? void 0 : m.length) ?? 0;
657
- for (const w of v.kv) t.retrievedKeyValueBytes += w.value.length;
658
- }
659
- c.push(v);
660
- }
661
- }
662
- return t && (t.millisSpent += Date.now() - i, t.roundTrips += l), c;
663
- }
664
- function ge(o) {
665
- return o;
666
- }
667
- function pe(o, e, t) {
668
- var a;
669
- const i = o instanceof R ? p(t).accessor(o).node() : o instanceof T ? o.node() : o, d = { ...i.resourceInfo };
670
- if (e.data !== void 0 && (e.data === "raw" ? d.data = i.getData() : d.data = e.data.parse(i.getDataAsJson())), e.fields !== void 0) {
671
- const r = {};
672
- for (const [f, l] of Object.entries(e.fields))
673
- r[f] = (a = i.traverse({
674
- field: f,
675
- errorIfFieldNotSet: l,
676
- stableIfNotFound: !l
677
- })) == null ? void 0 : a.id;
678
- d.fields = r;
679
- }
680
- if (e.kv !== void 0) {
681
- const r = {};
682
- for (const [f, l] of Object.entries(e.kv)) {
683
- const h = i.getKeyValue(f);
684
- if (h === void 0)
685
- throw new Error(`Key not found ${f}`);
686
- l === "raw" ? r[f] = h : r[f] = l.parse(JSON.parse(Buffer.from(h).toString("utf-8")));
687
- }
688
- d.kv = r;
689
- }
690
- return d;
691
- }
692
- function ye(o, e, t) {
693
- if (o instanceof R) {
694
- const i = t.accessor(o).node(), n = i.resourceInfo, d = e.map((a) => {
695
- var r, f;
696
- return [
697
- a,
698
- (f = (r = i.getField(a)) == null ? void 0 : r.value) == null ? void 0 : f.id
699
- ];
700
- });
701
- return {
702
- ...n,
703
- fields: new Map(d),
704
- data: i.getData() ?? new Uint8Array()
705
- };
706
- }
707
- return o;
708
- }
709
- function ve(o, e, t) {
710
- if (!(o instanceof R)) return o;
711
- const i = t.accessor(o).node(), n = i.resourceInfo, d = e.map((a) => [a, i.getKeyValue(a)]);
712
- return {
713
- ...n,
714
- metadata: Object.fromEntries(d)
715
- };
716
- }
717
- class B {
718
- constructor(e, t, i, n) {
719
- u(this, "finalPredicate");
720
- u(this, "state");
721
- u(this, "pollingInterval");
722
- u(this, "pruning");
723
- u(this, "logStat");
724
- u(this, "hooks");
725
- u(this, "abortController", new AbortController());
726
- u(this, "currentLoopDelayInterrupt");
727
- u(this, "scheduledOnNextState", []);
728
- /** If true, main loop will continue polling pl state. */
729
- u(this, "keepRunning", !1);
730
- /** Actual state of main loop. */
731
- u(this, "currentLoop");
732
- /** If true this tree state is permanently terminaed. */
733
- u(this, "terminated", !1);
734
- this.pl = e, this.root = t, this.logger = n;
735
- const { finalPredicateOverride: d, pruning: a, pollingInterval: r, stopPollingDelay: f, logStat: l } = i;
736
- this.pruning = a, this.pollingInterval = r, this.finalPredicate = d ?? e.finalPredicate, this.logStat = l, this.state = new P(t, this.finalPredicate), this.hooks = new H(
737
- () => this.startUpdating(),
738
- () => this.stopUpdating(),
739
- { stopDebounce: f },
740
- (h, s) => this.scheduleOnNextState(h, s)
741
- );
742
- }
743
- /** @deprecated use "entry" instead */
744
- accessor(e = this.root) {
745
- if (this.terminated) throw new Error("tree synchronization is terminated");
746
- return this.entry(e);
747
- }
748
- entry(e = this.root) {
749
- if (this.terminated) throw new Error("tree synchronization is terminated");
750
- return new R({ treeProvider: () => this.state, hooks: this.hooks }, e);
751
- }
752
- /** Can be used to externally kick off the synchronization polling loop, and
753
- * await for the first synchronization to happen. */
754
- async refreshState() {
755
- if (this.terminated) throw new Error("tree synchronization is terminated");
756
- await this.hooks.refreshState();
757
- }
758
- /** Called from computable hooks when external observer asks for state refresh */
759
- scheduleOnNextState(e, t) {
760
- this.terminated ? t(new Error("tree synchronization is terminated")) : (this.scheduledOnNextState.push({ resolve: e, reject: t }), this.currentLoopDelayInterrupt && (this.currentLoopDelayInterrupt.abort(), this.currentLoopDelayInterrupt = void 0));
761
- }
762
- /** Called from observer */
763
- startUpdating() {
764
- this.terminated || (this.keepRunning = !0, this.currentLoop === void 0 && (this.currentLoop = this.mainLoop()));
765
- }
766
- /** Called from observer */
767
- stopUpdating() {
768
- this.keepRunning = !1;
769
- }
770
- /** Executed from the main loop, and initialization procedure. */
771
- async refresh(e, t) {
772
- if (this.terminated) throw new Error("tree synchronization is terminated");
773
- const i = Z(this.state, this.pruning), n = await this.pl.withReadTx("ReadingTree", async (d) => await ee(d, i, e), t);
774
- this.state.updateFromResourceData(n, !0);
775
- }
776
- async mainLoop() {
777
- var i, n;
778
- let e = this.logStat ? $() : void 0, t = Date.now();
779
- for (; !(!this.keepRunning || this.terminated); ) {
780
- let d;
781
- this.scheduledOnNextState.length > 0 && (d = this.scheduledOnNextState, this.scheduledOnNextState = []);
782
- try {
783
- if (this.logStat === "per-request" && (e = $()), await this.refresh(e), e && this.logger && this.logger.info(`Tree stat (success, after ${Date.now() - t}ms): ${JSON.stringify(e)}`), t = Date.now(), d !== void 0) for (const a of d) a.resolve();
784
- } catch (a) {
785
- if (e && this.logger && this.logger.info(`Tree stat (error, after ${Date.now() - t}ms): ${JSON.stringify(e)}`), t = Date.now(), d !== void 0) for (const r of d) r.reject(a);
786
- if (a instanceof S) {
787
- (i = this.logger) == null || i.error(a), this.state.invalidateTree("stat update error"), this.state = new P(this.root, this.finalPredicate);
788
- continue;
789
- } else (n = this.logger) == null || n.warn(a);
790
- }
791
- if (!this.keepRunning || this.terminated) break;
792
- if (this.scheduledOnNextState.length === 0)
793
- try {
794
- this.currentLoopDelayInterrupt = new AbortController(), await G.setTimeout(
795
- this.pollingInterval,
796
- AbortSignal.any([this.abortController.signal, this.currentLoopDelayInterrupt.signal])
797
- );
798
- } catch (a) {
799
- if (!q(a)) throw new Error("Unexpected error", { cause: a });
800
- break;
801
- } finally {
802
- this.currentLoopDelayInterrupt = void 0;
803
- }
804
- }
805
- this.currentLoop = void 0;
806
- }
807
- /**
808
- * Dumps the current state of the tree.
809
- * @returns An array of ExtendedResourceData objects representing the current state of the tree.
810
- */
811
- dumpState() {
812
- return this.state.dumpState();
813
- }
814
- /**
815
- * Terminates the internal loop, and permanently destoys all internal state, so
816
- * all computables using this state will resolve to errors.
817
- * */
818
- async terminate() {
819
- this.keepRunning = !1, this.terminated = !0, this.abortController.abort(), this.currentLoop !== void 0 && (await this.currentLoop, this.state.invalidateTree("synchronization terminated for the tree"));
820
- }
821
- /** @deprecated */
822
- async awaitSyncLoopTermination() {
823
- this.currentLoop !== void 0 && await this.currentLoop;
824
- }
825
- static async init(e, t, i, n) {
826
- const d = new B(e, t, i, n), a = i.logStat ? $() : void 0;
827
- let r = !1;
828
- try {
829
- await d.refresh(a, {
830
- timeout: i.initialTreeLoadingTimeout
831
- }), r = !0;
832
- } finally {
833
- a && n && n.info(
834
- `Tree stat (initial load, ${r ? "success" : "failure"}): ${JSON.stringify(a)}`
835
- );
836
- }
837
- return d;
838
- }
839
- }
840
- function ke(o) {
841
- var t;
842
- const e = {
843
- total: {
844
- count: 0,
845
- fieldNameBytes: 0,
846
- fieldsCount: 0,
847
- dataBytes: 0,
848
- kvCount: 0,
849
- kvBytes: 0
850
- },
851
- byResourceType: {}
852
- };
853
- for (const i of o) {
854
- const n = `${i.type.name}/${i.type.version}`;
855
- e.byResourceType[n] || (e.byResourceType[n] = {
856
- count: 0,
857
- fieldNameBytes: 0,
858
- fieldsCount: 0,
859
- dataBytes: 0,
860
- kvCount: 0,
861
- kvBytes: 0
862
- });
863
- const d = e.byResourceType[n];
864
- d.count++, e.total.count++;
865
- for (const a of i.fields)
866
- d.fieldNameBytes += a.name.length, d.fieldsCount++, e.total.fieldNameBytes += a.name.length, e.total.fieldsCount++;
867
- if (i.data) {
868
- const a = ((t = i.data) == null ? void 0 : t.length) ?? 0;
869
- d.dataBytes += a, e.total.dataBytes += a;
870
- }
871
- d.kvCount += i.kv.length, e.total.kvCount += i.kv.length;
872
- for (const a of i.kv) {
873
- const r = a.key.length + a.value.length;
874
- d.kvBytes += r, e.total.kvBytes += r;
875
- }
876
- }
877
- return e;
878
- }
879
- export {
880
- de as PlError,
881
- R as PlTreeEntry,
882
- T as PlTreeEntryAccessor,
883
- Q as PlTreeNodeAccessor,
884
- X as PlTreeResource,
885
- P as PlTreeState,
886
- B as SynchronizedTreeState,
887
- S as TreeStateUpdateError,
888
- Z as constructTreeLoadingRequest,
889
- fe as formatTreeLoadingStat,
890
- $ as initialTreeLoadingStat,
891
- ue as isPlTreeEntry,
892
- ce as isPlTreeEntryAccessor,
893
- he as isPlTreeNodeAccessor,
894
- ee as loadTreeState,
895
- pe as makeResourceSnapshot,
896
- K as mapValueAndError,
897
- oe as mapValueAndErrorIfDefined,
898
- ge as rsSchema,
899
- ke as treeDumpStats,
900
- le as treeEntryToResourceInfo,
901
- ye as treeEntryToResourceWithData,
902
- ve as treeEntryToResourceWithMetadata
903
- };
904
- //# sourceMappingURL=index.mjs.map