zocket 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bun.js CHANGED
@@ -1,3112 +1,13 @@
1
1
  // @bun
2
- // ../orbz/src/utils/runtime.js
3
- var _baseAnchor;
4
- var hasSetDefault = false;
5
- var MEM = {
6
- get BASE_ANCHOR() {
7
- return _baseAnchor;
8
- },
9
- set BASE_ANCHOR(anchor) {
10
- if (hasSetDefault) {
11
- throw new Error("cannot update base anchor");
12
- }
13
- _baseAnchor = anchor;
14
- hasSetDefault = true;
15
- },
16
- LAST_ANCHOR_ID: 1,
17
- ORB_META: new WeakMap,
18
- ORB_STATE: new WeakMap,
19
- ORB_PLAN: new WeakMap,
20
- ORB_GETTER_CACHE: new WeakMap,
21
- FACTORY_PLAN: new WeakMap,
22
- MOUNTS: new WeakMap,
23
- MOUNT_FACTORIES: new WeakMap,
24
- SHAPE_NAMES: new Set,
25
- LINKS_BY_SOURCE: new Map,
26
- INSPECTORS: new Set
27
- };
28
- var VOCAB = {
29
- SHAPE: {
30
- NAME: Symbol.for("orbz.Shape.name"),
31
- INIT: Symbol.for("orbz.Shape.init"),
32
- KEYS: Symbol.for("orbz.Shape.keys"),
33
- EDGE: Symbol.for("orbz.Shape.edge"),
34
- SAVE: Symbol.for("orbz.Shape.save"),
35
- LOAD: Symbol.for("orbz.Shape.load"),
36
- MOUNTS: Symbol.for("orbz.Shape.mounts")
37
- }
38
- };
39
- VOCAB.SHAPE_SYMBOLS = new Set(Object.values(VOCAB.SHAPE));
40
- var ROUTE_SEGMENT = /^[A-Za-z0-9._~-]+$/;
41
- function assertRouteSegment(segment) {
42
- if (typeof segment !== "string" || segment.length === 0 || !ROUTE_SEGMENT.test(segment)) {
43
- throw new Error("Route segments must be non-empty URL-safe strings");
44
- }
45
- }
46
-
47
- // ../orbz/src/utils/shapePlan.js
48
- var hasOwn = Object.prototype.hasOwnProperty;
49
- function createShapePlan(definition, options = {}) {
50
- if (!definition || typeof definition !== "object") {
51
- throw new TypeError("Shape definition must be an object");
52
- }
53
- const descriptors = Object.getOwnPropertyDescriptors(definition);
54
- const identity = readShapeIdentity(descriptors);
55
- const parents = options.parents ?? [];
56
- const directParents = parents.map((plan2) => ({ id: plan2.id, name: plan2.name }));
57
- const ancestry = uniqueShapeRefs([
58
- ...parents.flatMap((parent) => parent.ancestry),
59
- ...directParents
60
- ]);
61
- const plan = {
62
- id: identity.id,
63
- name: identity.name,
64
- parents: directParents,
65
- ancestry,
66
- ancestryIds: new Set(ancestry.map((parent) => parent.id)),
67
- descriptors,
68
- entries: [],
69
- byKey: new Map,
70
- state: [],
71
- publicState: [],
72
- internalState: [],
73
- slots: [],
74
- serializable: [],
75
- enumerable: [],
76
- getters: [],
77
- pairedAccessors: [],
78
- shortcutSetters: [],
79
- methods: [],
80
- generatorMethods: [],
81
- protocol: {
82
- init: undefined,
83
- keys: undefined,
84
- edge: undefined,
85
- save: undefined,
86
- load: undefined
87
- },
88
- mounts: {}
89
- };
90
- let mountDescriptors;
91
- for (const key of Reflect.ownKeys(descriptors)) {
92
- if (typeof key === "symbol") {
93
- if (!VOCAB.SHAPE_SYMBOLS.has(key)) {
94
- throw new Error("Shape definitions may not use arbitrary symbol keys");
95
- }
96
- if (key === VOCAB.SHAPE.MOUNTS) {
97
- mountDescriptors = readMountDescriptors(descriptors[key]);
98
- continue;
99
- }
100
- indexProtocolMember(plan, key, descriptors[key]);
101
- continue;
102
- }
103
- if (key === "$") {
104
- throw new Error("Shape cannot define reserved key '$'");
105
- }
106
- const descriptor = descriptors[key];
107
- const entry = classifyShapeMember(key, descriptor);
108
- if (entry.meta.serializable) {
109
- assertRouteSegment(key);
110
- }
111
- plan.entries.push(entry);
112
- plan.byKey.set(key, entry);
113
- indexShapeEntry(plan, entry);
114
- }
115
- plan.mounts = normalizeMountDescriptors(mountDescriptors, plan);
116
- registerShapeName(identity.name);
117
- return plan;
118
- }
119
- function createExtendedShapeDefinition(parentPlans, definition) {
120
- if (!definition || typeof definition !== "object") {
121
- throw new TypeError("Shape definition must be an object");
122
- }
123
- const merged = {};
124
- for (const parent of parentPlans) {
125
- for (const [key, descriptor] of Object.entries(parent.descriptors)) {
126
- Object.defineProperty(merged, key, descriptor);
127
- }
128
- }
129
- for (const key of Reflect.ownKeys(definition)) {
130
- Object.defineProperty(merged, key, Object.getOwnPropertyDescriptor(definition, key));
131
- }
132
- return merged;
133
- }
134
- function indexProtocolMember(plan, key, descriptor) {
135
- if (key === VOCAB.SHAPE.NAME) {
136
- return;
137
- }
138
- if (!Object.prototype.hasOwnProperty.call(descriptor, "value") || typeof descriptor.value !== "function") {
139
- throw new Error("Shape protocol members must be methods");
140
- }
141
- if (key === VOCAB.SHAPE.INIT) {
142
- plan.protocol.init = descriptor.value;
143
- } else if (key === VOCAB.SHAPE.KEYS) {
144
- plan.protocol.keys = descriptor.value;
145
- } else if (key === VOCAB.SHAPE.EDGE) {
146
- plan.protocol.edge = descriptor.value;
147
- } else if (key === VOCAB.SHAPE.SAVE) {
148
- plan.protocol.save = descriptor.value;
149
- } else if (key === VOCAB.SHAPE.LOAD) {
150
- plan.protocol.load = descriptor.value;
151
- } else if (key === VOCAB.SHAPE.MOUNTS) {
152
- return;
153
- } else {
154
- throw new Error("Unknown Shape protocol member");
155
- }
156
- }
157
- function readShapeIdentity(descriptors) {
158
- const nameDescriptor = descriptors[VOCAB.SHAPE.NAME];
159
- if (!nameDescriptor || !Object.prototype.hasOwnProperty.call(nameDescriptor, "value")) {
160
- throw new Error("Shape.name is required");
161
- }
162
- const name = nameDescriptor.value;
163
- if (typeof name !== "string" || name.length === 0) {
164
- throw new TypeError("Shape.name must be a non-empty string");
165
- }
166
- return { id: name, name };
167
- }
168
- function uniqueShapeRefs(refs) {
169
- const seen = new Set;
170
- const out = [];
171
- for (const ref of refs) {
172
- if (seen.has(ref.id))
173
- continue;
174
- seen.add(ref.id);
175
- out.push(ref);
176
- }
177
- return out;
178
- }
179
- function registerShapeName(name) {
180
- if (MEM.SHAPE_NAMES.has(name)) {
181
- throw new Error(`Shape '${name}' is already defined`);
182
- }
183
- MEM.SHAPE_NAMES.add(name);
184
- }
185
- function classifyShapeMember(key, descriptor) {
186
- const hasValue = hasOwn.call(descriptor, "value");
187
- const hasGetter = typeof descriptor.get === "function";
188
- const hasSetter = typeof descriptor.set === "function";
189
- const internal = key.startsWith("_");
190
- if (hasValue) {
191
- if (typeof descriptor.value === "function") {
192
- if (isOrbFactory(descriptor.value)) {
193
- return {
194
- key,
195
- kind: "slot",
196
- value: descriptor.value,
197
- shapeId: descriptor.value.shapeId,
198
- descriptor,
199
- meta: {
200
- visibility: internal ? "internal" : "public",
201
- internal,
202
- enumerable: !internal,
203
- serializable: true,
204
- writableFromPublic: !internal,
205
- writableFromBehavior: true,
206
- acceptedInConstructor: true
207
- }
208
- };
209
- }
210
- const generator = isGeneratorFunction(descriptor.value);
211
- return {
212
- key,
213
- kind: generator ? "generatorMethod" : "method",
214
- value: descriptor.value,
215
- descriptor,
216
- meta: {
217
- internal: false,
218
- enumerable: false,
219
- serializable: false
220
- }
221
- };
222
- }
223
- assertJsonCompatibleStateDefault(key, descriptor.value);
224
- return {
225
- key,
226
- kind: "state",
227
- value: descriptor.value,
228
- descriptor,
229
- meta: {
230
- visibility: internal ? "internal" : "public",
231
- internal,
232
- enumerable: !internal,
233
- serializable: true,
234
- writableFromPublic: !internal,
235
- writableFromBehavior: true,
236
- acceptedInConstructor: true
237
- }
238
- };
239
- }
240
- if (hasGetter && hasSetter) {
241
- return {
242
- key,
243
- kind: "pairedAccessor",
244
- get: descriptor.get,
245
- set: descriptor.set,
246
- descriptor,
247
- meta: {
248
- internal,
249
- enumerable: false,
250
- serializable: false,
251
- acceptedInConstructor: true
252
- }
253
- };
254
- }
255
- if (hasGetter) {
256
- return {
257
- key,
258
- kind: "getter",
259
- get: descriptor.get,
260
- descriptor,
261
- meta: {
262
- internal,
263
- enumerable: false,
264
- serializable: false
265
- }
266
- };
267
- }
268
- if (hasSetter) {
269
- return {
270
- key,
271
- kind: "shortcutSetter",
272
- set: descriptor.set,
273
- descriptor,
274
- meta: {
275
- internal,
276
- enumerable: false,
277
- serializable: false,
278
- acceptedInConstructor: true
279
- }
280
- };
281
- }
282
- throw new Error(`Unsupported Shape member '${key}'`);
283
- }
284
- function indexShapeEntry(plan, entry) {
285
- if (entry.kind === "state") {
286
- plan.state.push(entry);
287
- plan.serializable.push(entry);
288
- if (entry.meta.internal) {
289
- plan.internalState.push(entry);
290
- } else {
291
- plan.publicState.push(entry);
292
- plan.enumerable.push(entry);
293
- }
294
- } else if (entry.kind === "slot") {
295
- plan.state.push(entry);
296
- plan.slots.push(entry);
297
- plan.serializable.push(entry);
298
- if (entry.meta.internal) {
299
- plan.internalState.push(entry);
300
- } else {
301
- plan.publicState.push(entry);
302
- plan.enumerable.push(entry);
303
- }
304
- } else if (entry.kind === "getter") {
305
- plan.getters.push(entry);
306
- } else if (entry.kind === "pairedAccessor") {
307
- plan.pairedAccessors.push(entry);
308
- } else if (entry.kind === "shortcutSetter") {
309
- plan.shortcutSetters.push(entry);
310
- } else if (entry.kind === "method") {
311
- plan.methods.push(entry);
312
- } else if (entry.kind === "generatorMethod") {
313
- plan.generatorMethods.push(entry);
314
- } else {
315
- throw new Error(`Unknown Shape entry kind '${entry.kind}'`);
316
- }
317
- }
318
- function readMountDescriptors(descriptor) {
319
- if (!Object.prototype.hasOwnProperty.call(descriptor, "value")) {
320
- throw new Error("Shape.mounts must be a plain object");
321
- }
322
- return descriptor.value;
323
- }
324
- function normalizeMountDescriptors(value, plan) {
325
- if (value === undefined)
326
- return {};
327
- if (!value || typeof value !== "object" || Array.isArray(value)) {
328
- throw new TypeError("Shape.mounts must be a plain object");
329
- }
330
- const out = {};
331
- const getters = new Set(plan.getters.map((entry) => entry.key));
332
- const commands = new Set([
333
- ...plan.methods.map((entry) => entry.key),
334
- ...plan.generatorMethods.map((entry) => entry.key)
335
- ]);
336
- for (const [target, rawConfig] of Object.entries(value)) {
337
- assertRouteSegment(target);
338
- if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
339
- throw new TypeError(`Shape.mounts.${target} must be a plain object`);
340
- }
341
- for (const key of Object.keys(rawConfig)) {
342
- if (key !== "outsource") {
343
- throw new Error(`Unsupported Shape.mounts.${target} option '${key}'`);
344
- }
345
- }
346
- const outsource = normalizeOutsourceList(rawConfig.outsource, target);
347
- const projections = [];
348
- const methods = [];
349
- for (const key of outsource) {
350
- if (getters.has(key)) {
351
- projections.push(key);
352
- } else if (commands.has(key)) {
353
- methods.push(key);
354
- } else {
355
- throw new Error(`Shape.mounts.${target} cannot outsource '${key}'`);
356
- }
357
- }
358
- out[target] = {
359
- target,
360
- outsource,
361
- projections,
362
- commands: methods
363
- };
364
- }
365
- return out;
366
- }
367
- function normalizeOutsourceList(value, target) {
368
- if (value === undefined)
369
- return [];
370
- if (!Array.isArray(value)) {
371
- throw new TypeError(`Shape.mounts.${target}.outsource must be an array`);
372
- }
373
- const seen = new Set;
374
- const out = [];
375
- for (const key of value) {
376
- if (typeof key !== "string" || key.length === 0) {
377
- throw new TypeError(`Shape.mounts.${target}.outsource entries must be non-empty strings`);
378
- }
379
- if (seen.has(key))
380
- continue;
381
- seen.add(key);
382
- out.push(key);
383
- }
384
- return out;
385
- }
386
- function isGeneratorFunction(value) {
387
- return typeof value === "function" && value.constructor && value.constructor.name === "GeneratorFunction";
388
- }
389
- function isOrbFactory(value) {
390
- return typeof value === "function" && typeof value.shapeId === "string";
391
- }
392
- function assertJsonCompatibleStateDefault(key, value) {
393
- if (isJsonCompatibleValue(value))
394
- return;
395
- throw new Error(`State default '${key}' must be JSON-compatible in v1`);
396
- }
397
- function isJsonCompatibleValue(value) {
398
- if (value === null)
399
- return true;
400
- switch (typeof value) {
401
- case "string":
402
- case "boolean":
403
- return true;
404
- case "number":
405
- return Number.isFinite(value);
406
- case "object":
407
- return isJsonCompatibleObject(value);
408
- default:
409
- return false;
410
- }
411
- }
412
- function isJsonCompatibleObject(value) {
413
- if (Array.isArray(value)) {
414
- return value.every(isJsonCompatibleValue);
415
- }
416
- const prototype = Object.getPrototypeOf(value);
417
- if (prototype !== Object.prototype && prototype !== null) {
418
- return false;
419
- }
420
- return Object.values(value).every(isJsonCompatibleValue);
421
- }
422
- function describe(value) {
423
- const plan = MEM.FACTORY_PLAN.get(value) ?? MEM.ORB_PLAN.get(value);
424
- if (!plan) {
425
- throw new TypeError("describe() expects a Shape factory or OrbNode");
426
- }
427
- return describeShapePlan(plan);
428
- }
429
- function describeShapePlan(plan) {
430
- const description = {
431
- id: plan.id,
432
- name: plan.name,
433
- state: plan.state.filter((entry) => entry.kind === "state").map(describeStateEntry),
434
- slots: plan.slots.map(describeSlotEntry),
435
- getters: plan.getters.map((entry) => entry.key),
436
- pairedAccessors: plan.pairedAccessors.map((entry) => entry.key),
437
- shortcutSetters: plan.shortcutSetters.map((entry) => entry.key),
438
- methods: plan.methods.map((entry) => entry.key),
439
- generatorMethods: plan.generatorMethods.map((entry) => entry.key),
440
- mounts: cloneJson(plan.mounts)
441
- };
442
- if (plan.parents.length > 0) {
443
- description.parents = cloneShapeRefs(plan.parents);
444
- description.extends = cloneShapeRefs(plan.ancestry);
445
- }
446
- return description;
447
- }
448
- function describeSlotEntry(entry) {
449
- return {
450
- key: entry.key,
451
- shape: entry.shapeId
452
- };
453
- }
454
- function describeStateEntry(entry) {
455
- return {
456
- key: entry.key,
457
- visibility: entry.meta.visibility,
458
- enumerable: entry.meta.enumerable,
459
- serializable: entry.meta.serializable,
460
- default: cloneJson(entry.value)
461
- };
462
- }
463
- function cloneJson(value) {
464
- if (value === undefined)
465
- return;
466
- return JSON.parse(JSON.stringify(value));
467
- }
468
- function cloneShapeRefs(refs) {
469
- return refs.map((ref) => ({ ...ref }));
470
- }
471
-
472
- // ../orbz/src/utils/inspection.js
473
- function emitInspectionEvent(event) {
474
- if (MEM.INSPECTORS.size === 0)
475
- return;
476
- const frozenEvent = Object.freeze({ ...event });
477
- for (const listener of [...MEM.INSPECTORS]) {
478
- listener(frozenEvent);
479
- }
480
- }
481
-
482
- // ../orbz/src/utils/reactivity.js
483
- var activeComputation = null;
484
- var batchDepth = 0;
485
- var isFlushing = false;
486
- var nextRuntimeOrbId = 1;
487
- var DEPENDENTS = new Map;
488
- var pendingEffects = new Set;
489
- var DEPENDENCY_KEYS = new WeakMap;
490
- var ORB_RUNTIME_ID = new WeakMap;
491
- function trackDependency(orb, key) {
492
- if (!activeComputation)
493
- return;
494
- activeComputation.nextDeps.add(createDependencyKey(orb, key));
495
- }
496
- function runTracked(computation, fn) {
497
- const parentComputation = activeComputation;
498
- computation.nextDeps = new Set;
499
- activeComputation = computation;
500
- try {
501
- return fn();
502
- } finally {
503
- activeComputation = parentComputation;
504
- }
505
- }
506
- function notifyDependencyChanged(orb, key) {
507
- const dependents = DEPENDENTS.get(createDependencyKey(orb, key));
508
- if (!dependents)
509
- return;
510
- for (const computation of [...dependents]) {
511
- if (computation.type === "effect" && computation.active) {
512
- pendingEffects.add(computation);
513
- } else if (computation.type === "getter") {
514
- computation.onDependencyChanged?.();
515
- }
516
- }
517
- flushEffects();
518
- }
519
- function replaceSubscriptions(computation) {
520
- removeSubscriptions(computation);
521
- computation.deps = computation.nextDeps;
522
- computation.nextDeps = new Set;
523
- for (const dependency of computation.deps) {
524
- let dependents = DEPENDENTS.get(dependency);
525
- if (!dependents) {
526
- dependents = new Set;
527
- DEPENDENTS.set(dependency, dependents);
528
- }
529
- dependents.add(computation);
530
- }
531
- }
532
- function removeSubscriptions(computation) {
533
- if (!computation.deps)
534
- return;
535
- for (const dependency of computation.deps) {
536
- const dependents = DEPENDENTS.get(dependency);
537
- if (!dependents)
538
- continue;
539
- dependents.delete(computation);
540
- if (dependents.size === 0) {
541
- DEPENDENTS.delete(dependency);
542
- }
543
- }
544
- computation.deps = new Set;
545
- }
546
- function batch(callback) {
547
- emitInspectionEvent({ type: "batch:start", depth: batchDepth + 1 });
548
- batchDepth++;
549
- try {
550
- return callback();
551
- } finally {
552
- batchDepth--;
553
- emitInspectionEvent({ type: "batch:end", depth: batchDepth + 1 });
554
- if (batchDepth === 0) {
555
- flushEffects();
556
- }
557
- }
558
- }
559
- function fx(callback) {
560
- if (typeof callback !== "function") {
561
- throw new TypeError("fx() expects a callback");
562
- }
563
- const effect = {
564
- type: "effect",
565
- active: true,
566
- deps: new Set,
567
- nextDeps: new Set,
568
- run() {
569
- if (!effect.active)
570
- return;
571
- emitInspectionEvent({ type: "effect:run" });
572
- runTracked(effect, callback);
573
- replaceSubscriptions(effect);
574
- }
575
- };
576
- effect.run();
577
- return () => {
578
- effect.active = false;
579
- pendingEffects.delete(effect);
580
- removeSubscriptions(effect);
581
- };
582
- }
583
- function createDependencyKey(orb, key) {
584
- let keys = DEPENDENCY_KEYS.get(orb);
585
- if (!keys) {
586
- keys = new Map;
587
- DEPENDENCY_KEYS.set(orb, keys);
588
- }
589
- if (!keys.has(key)) {
590
- keys.set(key, {
591
- target: getOrbRuntimeId(orb),
592
- key
593
- });
594
- }
595
- return keys.get(key);
596
- }
597
- function flushEffects() {
598
- if (batchDepth > 0 || isFlushing)
599
- return;
600
- isFlushing = true;
601
- try {
602
- while (pendingEffects.size > 0) {
603
- const effects = [...pendingEffects];
604
- pendingEffects.clear();
605
- for (const effect of effects) {
606
- effect.run();
607
- }
608
- }
609
- } finally {
610
- isFlushing = false;
611
- }
612
- }
613
- function getOrbRuntimeId(orb) {
614
- if (!ORB_RUNTIME_ID.has(orb)) {
615
- ORB_RUNTIME_ID.set(orb, nextRuntimeOrbId++);
616
- }
617
- return ORB_RUNTIME_ID.get(orb);
618
- }
619
- function createEachEffect({ node, callback, options, keys, peek, read }) {
620
- if (typeof callback !== "function") {
621
- throw new TypeError("eachEffect() expects a callback");
622
- }
623
- const itemStops = new Map;
624
- const itemValues = new Map;
625
- const scope = options.scope;
626
- let disposed = false;
627
- const stopMembership = fx(() => {
628
- const activeKeys = new Set;
629
- for (const key of keys()) {
630
- const value = peek(key);
631
- activeKeys.add(key);
632
- if (itemValues.get(key) === value && itemStops.has(key))
633
- continue;
634
- stopItem(key);
635
- itemValues.set(key, value);
636
- itemStops.set(key, fx(() => {
637
- const current = read(key);
638
- itemValues.set(key, current);
639
- callback(current, key, node);
640
- }));
641
- }
642
- for (const key of itemStops.keys()) {
643
- if (!activeKeys.has(key))
644
- stopItem(key);
645
- }
646
- });
647
- const stop = () => {
648
- if (disposed)
649
- return;
650
- disposed = true;
651
- stopMembership();
652
- for (const key of itemStops.keys())
653
- stopItem(key);
654
- };
655
- if (scope)
656
- scope.onDispose(stop);
657
- return stop;
658
- function stopItem(key) {
659
- itemStops.get(key)?.();
660
- itemStops.delete(key);
661
- itemValues.delete(key);
662
- }
663
- }
664
-
665
- // ../orbz/src/utils/createOrbFactory.js
666
- var { ORB_STATE, ORB_PLAN, ORB_GETTER_CACHE, FACTORY_PLAN } = MEM;
667
- var behaviorDepth = 0;
668
- var CONSTRUCT = Symbol("construct");
669
- var HYDRATE = Symbol("hydrate");
670
- function createOrbFactory(plan) {
671
-
672
- class Orb {
673
- constructor(input, mode = CONSTRUCT) {
674
- ORB_PLAN.set(this, plan);
675
- const state = createInitialState(plan);
676
- ORB_STATE.set(this, state);
677
- ORB_GETTER_CACHE.set(this, new Map);
678
- defineInstanceStateAccessors(this, plan);
679
- runWithBehaviorAuthority(() => {
680
- const normalized = mode === HYDRATE ? normalizeHydrationInput(this, plan, input) : normalizeConstructorInput(this, plan, input);
681
- applyConstructorInput(this, plan, normalized, {
682
- hydration: mode === HYDRATE
683
- });
684
- });
685
- MEM.BASE_ANCHOR.adoptRuntimeOrb(this);
686
- }
687
- toJSON() {
688
- return this[VOCAB.SHAPE.SAVE]();
689
- }
690
- }
691
- function OrbFactory(input) {
692
- return new Orb(input);
693
- }
694
- Object.defineProperty(Orb, "name", {
695
- value: sanitizeConstructorName(plan.id),
696
- configurable: true
697
- });
698
- Object.defineProperty(Orb, "shapeId", {
699
- value: plan.id,
700
- enumerable: true
701
- });
702
- Object.defineProperty(Orb, "hydrate", {
703
- enumerable: true,
704
- configurable: false,
705
- value(record) {
706
- return hydrateOrb(Orb, plan, record);
707
- }
708
- });
709
- Object.defineProperty(Orb, "accepts", {
710
- enumerable: true,
711
- configurable: false,
712
- value(value) {
713
- return acceptsShape(plan, value);
714
- }
715
- });
716
- Object.defineProperty(OrbFactory, "name", {
717
- value: sanitizeConstructorName(plan.id),
718
- configurable: true
719
- });
720
- Object.defineProperty(OrbFactory, "prototype", {
721
- value: Orb.prototype,
722
- configurable: false
723
- });
724
- Object.defineProperty(OrbFactory, "shapeId", {
725
- value: plan.id,
726
- enumerable: true
727
- });
728
- Object.defineProperty(OrbFactory, "hydrate", {
729
- enumerable: true,
730
- configurable: false,
731
- value(record) {
732
- return hydrateOrb(Orb, plan, record);
733
- }
734
- });
735
- Object.defineProperty(OrbFactory, "accepts", {
736
- enumerable: true,
737
- configurable: false,
738
- value(value) {
739
- return acceptsShape(plan, value);
740
- }
741
- });
742
- FACTORY_PLAN.set(OrbFactory, plan);
743
- Object.defineProperty(plan, "factory", {
744
- value: OrbFactory,
745
- enumerable: false,
746
- configurable: true
747
- });
748
- for (const entry of plan.entries) {
749
- switch (entry.kind) {
750
- case "state":
751
- case "slot":
752
- defineStateAccessor(Orb.prototype, entry);
753
- break;
754
- case "getter":
755
- defineGetter(Orb.prototype, entry);
756
- break;
757
- case "pairedAccessor":
758
- definePairedAccessor(Orb.prototype, entry);
759
- break;
760
- case "shortcutSetter":
761
- defineShortcutSetter(Orb.prototype, entry);
762
- break;
763
- case "method":
764
- defineMethod(Orb.prototype, entry);
765
- break;
766
- case "generatorMethod":
767
- defineGeneratorMethod(Orb.prototype, entry);
768
- break;
769
- default:
770
- throw new Error(`Unknown Shape entry kind '${entry.kind}'`);
771
- }
772
- }
773
- defineDollar(Orb.prototype);
774
- defineProtocol(Orb.prototype, plan);
775
- return OrbFactory;
776
- }
777
- function hydrateOrb(Orb, plan, record) {
778
- const input = parseHydrationRecord(record, plan);
779
- return new Orb(input, HYDRATE);
780
- }
781
- function parseHydrationRecord(record, plan) {
782
- if (typeof record === "string") {
783
- const parsed = JSON.parse(record);
784
- if (plan.protocol.load) {
785
- return parsed;
786
- } else {
787
- record = parsed;
788
- }
789
- }
790
- if (plan.protocol.load) {
791
- return record;
792
- } else if (!record || typeof record !== "object" || Array.isArray(record)) {
793
- throw new TypeError("Orb hydration record must be an object or JSON string");
794
- } else {
795
- return record;
796
- }
797
- }
798
- function defineInstanceStateAccessors(orb, plan) {
799
- for (const entry of plan.state) {
800
- defineStateAccessor(orb, entry);
801
- }
802
- }
803
- function createInitialState(plan) {
804
- const state = {};
805
- for (const entry of plan.state) {
806
- state[entry.key] = entry.kind === "slot" ? undefined : cloneDefault(entry.value);
807
- }
808
- return state;
809
- }
810
- function applyConstructorInput(orb, plan, input, options = {}) {
811
- if (input == null) {
812
- assertRequiredSlots(orb, plan);
813
- return;
814
- }
815
- if (typeof input !== "object") {
816
- throw new TypeError("Orb constructor input must be an object");
817
- }
818
- for (const [key, value] of Object.entries(input)) {
819
- const entry = plan.byKey.get(key);
820
- if (!entry) {
821
- throw new Error(`Unknown constructor key '${key}' for Shape '${plan.id}'`);
822
- }
823
- switch (entry.kind) {
824
- case "state":
825
- case "slot":
826
- if (value instanceof OrbLink) {
827
- const state = getState(orb);
828
- state[key] = value;
829
- value.bindOrb(orb, key);
830
- markStateChanged(orb, key);
831
- } else {
832
- orb[key] = value;
833
- }
834
- break;
835
- case "pairedAccessor":
836
- case "shortcutSetter":
837
- orb[key] = value;
838
- break;
839
- case "getter":
840
- throw new Error(`Cannot assign derived getter '${key}' during construction`);
841
- case "method":
842
- case "generatorMethod":
843
- throw new Error(`Cannot assign method '${key}' during construction`);
844
- default:
845
- throw new Error(`Unsupported constructor key '${key}'`);
846
- }
847
- }
848
- assertRequiredSlots(orb, plan);
849
- if (options.hydration) {
850
- for (const key of Object.keys(input)) {
851
- const entry = plan.byKey.get(key);
852
- if (entry?.meta?.serializable)
853
- continue;
854
- throw new Error(`Hydration key '${key}' is not persisted state`);
855
- }
856
- }
857
- }
858
- function normalizeConstructorInput(orb, plan, input) {
859
- const normalized = (plan.protocol.init ?? defaultInit).call(orb, input);
860
- if (!normalized || typeof normalized !== "object" || Array.isArray(normalized)) {
861
- throw new TypeError("Shape.init must return constructor state");
862
- }
863
- return normalized;
864
- }
865
- function normalizeHydrationInput(orb, plan, input) {
866
- const normalized = (plan.protocol.load ?? defaultLoad).call(orb, input);
867
- if (!normalized || typeof normalized !== "object" || Array.isArray(normalized)) {
868
- throw new TypeError("Shape.load must return constructor state");
869
- }
870
- return normalized;
871
- }
872
- function serializeDefaultOrb(orb, plan) {
873
- const state = getState(orb);
874
- const out = {};
875
- for (const entry of plan.serializable) {
876
- out[entry.key] = serializeSlot(state[entry.key]);
877
- }
878
- return out;
879
- }
880
- function defaultInit(input = {}) {
881
- if (!input || typeof input !== "object" || Array.isArray(input)) {
882
- throw new TypeError("Orb constructor input must be an object");
883
- }
884
- return input;
885
- }
886
- function defaultLoad(input = {}) {
887
- if (!input || typeof input !== "object" || Array.isArray(input)) {
888
- throw new TypeError("Orb hydration record must be an object or JSON string");
889
- }
890
- return input;
891
- }
892
- function defineStateAccessor(proto, entry) {
893
- Object.defineProperty(proto, entry.key, {
894
- enumerable: entry.meta.enumerable,
895
- configurable: false,
896
- get() {
897
- const state = getState(this);
898
- if (entry.meta.internal && !hasBehaviorAuthority()) {
899
- throw new Error(`Cannot read internal state '${entry.key}' from outside Shape behavior`);
900
- }
901
- trackDependency(this, entry.key);
902
- return readSlot(state[entry.key]);
903
- },
904
- set(value) {
905
- if (entry.meta.internal && !hasBehaviorAuthority()) {
906
- throw new Error(`Cannot write internal state '${entry.key}' from outside Shape behavior`);
907
- }
908
- const state = getState(this);
909
- const previous = state[entry.key];
910
- if (previous instanceof OrbLink) {
911
- throw new Error(`Cannot write linked state slot '${entry.key}'`);
912
- }
913
- state[entry.key] = prepareStateValue(this, entry, value);
914
- if (!Object.is(previous, value)) {
915
- batch(() => {
916
- emitOrbEvent(this, "state:write", entry.key);
917
- markStateChanged(this, entry.key);
918
- const meta = MEM.ORB_META.get(this);
919
- meta?.anchor?.handleOrbSlotChanged?.(this, entry.key);
920
- });
921
- }
922
- }
923
- });
924
- }
925
- function prepareStateValue(orb, entry, value) {
926
- if (entry.kind === "slot") {
927
- assertSlotValue(entry, value);
928
- }
929
- return value;
930
- }
931
- function assertRequiredSlots(orb, plan) {
932
- const state = getState(orb);
933
- for (const entry of plan.slots) {
934
- if (state[entry.key] === undefined) {
935
- throw new Error(`Missing required slot '${entry.key}'`);
936
- }
937
- }
938
- }
939
- function assertSlotValue(entry, value) {
940
- if (value instanceof OrbLink)
941
- return;
942
- if (value instanceof LazyRef)
943
- return;
944
- if (!entry.value.accepts(value)) {
945
- throw new Error(`Slot '${entry.key}' expects Shape '${entry.shapeId}'`);
946
- }
947
- }
948
- function defineGetter(proto, entry) {
949
- Object.defineProperty(proto, entry.key, {
950
- enumerable: false,
951
- configurable: false,
952
- get() {
953
- return readCachedGetter(this, entry);
954
- }
955
- });
956
- }
957
- function definePairedAccessor(proto, entry) {
958
- Object.defineProperty(proto, entry.key, {
959
- enumerable: false,
960
- configurable: false,
961
- get() {
962
- return readCachedGetter(this, entry);
963
- },
964
- set(value) {
965
- return batch(() => runWithBehaviorAuthority(() => entry.set.call(this, value)));
966
- }
967
- });
968
- }
969
- function defineShortcutSetter(proto, entry) {
970
- Object.defineProperty(proto, entry.key, {
971
- enumerable: false,
972
- configurable: false,
973
- get() {
974
- return;
975
- },
976
- set(value) {
977
- return batch(() => runWithBehaviorAuthority(() => entry.set.call(this, value)));
978
- }
979
- });
980
- }
981
- function defineMethod(proto, entry) {
982
- Object.defineProperty(proto, entry.key, {
983
- enumerable: false,
984
- configurable: false,
985
- value(...args) {
986
- return batch(() => runWithBehaviorAuthority(() => entry.value.apply(this, args)));
987
- }
988
- });
989
- }
990
- function defineGeneratorMethod(proto, entry) {
991
- Object.defineProperty(proto, entry.key, {
992
- enumerable: false,
993
- configurable: false,
994
- value(...args) {
995
- const iterator = runWithBehaviorAuthority(() => entry.value.apply(this, args));
996
- return runGeneratorFlow(iterator);
997
- }
998
- });
999
- }
1000
- function defineDollar(proto) {
1001
- Object.defineProperty(proto, "$", {
1002
- enumerable: false,
1003
- configurable: false,
1004
- get() {
1005
- const orb = this;
1006
- function createLink(key) {
1007
- if (typeof key !== "string") {
1008
- throw new TypeError("orb.$() expects a property key string in v1");
1009
- }
1010
- const plan = ORB_PLAN.get(orb);
1011
- if (!plan.byKey.has(key)) {
1012
- throw new Error(`Cannot create link to unknown key '${key}'`);
1013
- }
1014
- const entry = plan.byKey.get(key);
1015
- if (!isPublicReadableEntry(entry)) {
1016
- throw new Error(`Cannot create link to unreadable key '${key}'`);
1017
- }
1018
- return new OrbLink(orb, key, { $: `${getOrbId(orb)}/${key}` });
1019
- }
1020
- Object.defineProperty(createLink, "uuid", {
1021
- enumerable: true,
1022
- configurable: true,
1023
- get() {
1024
- return MEM.ORB_META.get(orb)?.uuid ?? getOrbRuntimeId2(orb);
1025
- }
1026
- });
1027
- Object.defineProperty(createLink, "anchor", {
1028
- enumerable: true,
1029
- configurable: true,
1030
- get() {
1031
- return MEM.ORB_META.get(orb)?.anchor;
1032
- }
1033
- });
1034
- Object.defineProperty(createLink, "routes", {
1035
- enumerable: true,
1036
- configurable: true,
1037
- get() {
1038
- return [...MEM.ORB_META.get(orb)?.routes ?? []];
1039
- }
1040
- });
1041
- Object.defineProperty(createLink, "mount", {
1042
- enumerable: true,
1043
- configurable: true,
1044
- get() {
1045
- return createMountApi(orb);
1046
- }
1047
- });
1048
- Object.defineProperty(createLink, "track", {
1049
- enumerable: true,
1050
- configurable: true,
1051
- value(token) {
1052
- assertBehaviorAuthority("track");
1053
- trackDependency(orb, token);
1054
- }
1055
- });
1056
- Object.defineProperty(createLink, "changed", {
1057
- enumerable: true,
1058
- configurable: true,
1059
- value(token) {
1060
- assertBehaviorAuthority("changed");
1061
- markStateChanged(orb, token);
1062
- const meta = MEM.ORB_META.get(orb);
1063
- meta?.anchor?.handleOrbProtocolChanged?.(orb, token);
1064
- }
1065
- });
1066
- return createLink;
1067
- }
1068
- });
1069
- }
1070
- function createMountApi(orb) {
1071
- return {
1072
- get info() {
1073
- return cloneMountInfo(MEM.MOUNTS.get(orb));
1074
- },
1075
- status(key) {
1076
- return readMountBackingState(orb, "_mount_statuses", key);
1077
- },
1078
- error(key) {
1079
- return readMountBackingState(orb, "_mount_errors", key);
1080
- },
1081
- apply(patch = {}) {
1082
- return applyMountPatch(orb, patch);
1083
- }
1084
- };
1085
- }
1086
- function applyMountPatch(orb, patch = {}) {
1087
- const runtime = MEM.MOUNTS.get(orb);
1088
- if (!runtime)
1089
- return;
1090
- const apply = orb?._mountApply;
1091
- if (typeof apply !== "function") {
1092
- throw new Error("Mounted orb is missing generated _mountApply()");
1093
- }
1094
- return apply.call(orb, patch);
1095
- }
1096
- function readMountBackingState(orb, stateKey, key) {
1097
- if (!MEM.MOUNTS.has(orb))
1098
- return;
1099
- const values = runWithBehaviorAuthority(() => orb[stateKey]);
1100
- if (key === undefined)
1101
- return values;
1102
- return values?.[key];
1103
- }
1104
- function cloneMountInfo(runtime) {
1105
- if (!runtime)
1106
- return;
1107
- return {
1108
- source: { ...runtime.source },
1109
- target: runtime.target,
1110
- shape: { ...runtime.shape },
1111
- outsource: [...runtime.outsource],
1112
- projections: [...runtime.projections],
1113
- commands: [...runtime.commands]
1114
- };
1115
- }
1116
- function defineProtocol(proto, plan) {
1117
- const protocol = {
1118
- [VOCAB.SHAPE.KEYS]: plan.protocol.keys ?? defaultKeys,
1119
- [VOCAB.SHAPE.EDGE]: plan.protocol.edge ?? defaultEdge,
1120
- [VOCAB.SHAPE.SAVE]: plan.protocol.save ?? defaultSave,
1121
- [VOCAB.SHAPE.LOAD]: plan.protocol.load ?? defaultLoad,
1122
- [VOCAB.SHAPE.INIT]: plan.protocol.init ?? defaultInit
1123
- };
1124
- defineProtocolMethod(proto, VOCAB.SHAPE.INIT, protocol[VOCAB.SHAPE.INIT]);
1125
- defineProtocolMethod(proto, VOCAB.SHAPE.KEYS, protocol[VOCAB.SHAPE.KEYS]);
1126
- defineProtocolMethod(proto, VOCAB.SHAPE.EDGE, protocol[VOCAB.SHAPE.EDGE]);
1127
- defineProtocolMethod(proto, VOCAB.SHAPE.SAVE, protocol[VOCAB.SHAPE.SAVE]);
1128
- defineProtocolMethod(proto, VOCAB.SHAPE.LOAD, protocol[VOCAB.SHAPE.LOAD]);
1129
- function defaultKeys() {
1130
- return plan.serializable.map((entry) => entry.key);
1131
- }
1132
- function defaultEdge(key) {
1133
- const entry = plan.byKey.get(key);
1134
- if (!entry || !entry.meta.serializable) {
1135
- throw new Error(`Unknown edge '${String(key)}'`);
1136
- }
1137
- const orb = this;
1138
- const state = getState(orb);
1139
- return {
1140
- key,
1141
- segment: String(key),
1142
- read() {
1143
- trackDependency(orb, key);
1144
- return readSlot(state[key]);
1145
- },
1146
- peek() {
1147
- return state[key];
1148
- },
1149
- write(value) {
1150
- return runWithBehaviorAuthority(() => {
1151
- orb[key] = value;
1152
- return value;
1153
- });
1154
- }
1155
- };
1156
- }
1157
- function defaultSave() {
1158
- return serializeDefaultOrb(this, plan);
1159
- }
1160
- }
1161
- function defineProtocolMethod(proto, symbol, method) {
1162
- Object.defineProperty(proto, symbol, {
1163
- enumerable: false,
1164
- configurable: false,
1165
- value(...args) {
1166
- return runWithBehaviorAuthority(() => {
1167
- const result = method.apply(this, args);
1168
- return symbol === VOCAB.SHAPE.EDGE ? wrapEdgeBehavior(result) : result;
1169
- });
1170
- }
1171
- });
1172
- }
1173
- function wrapEdgeBehavior(edge) {
1174
- if (!edge || typeof edge !== "object") {
1175
- return edge;
1176
- }
1177
- const wrapped = { ...edge };
1178
- for (const key of Reflect.ownKeys(wrapped)) {
1179
- if (typeof wrapped[key] !== "function")
1180
- continue;
1181
- const method = wrapped[key];
1182
- wrapped[key] = function edgeBehaviorMethod(...args) {
1183
- const run = () => runWithBehaviorAuthority(() => method.apply(edge, args));
1184
- return key === "write" || key === "delete" ? batch(run) : run();
1185
- };
1186
- }
1187
- return wrapped;
1188
- }
1189
- function isPublicReadableEntry(entry) {
1190
- if (entry.meta.internal)
1191
- return false;
1192
- return entry.kind === "state" || entry.kind === "getter" || entry.kind === "pairedAccessor";
1193
- }
1194
- function readCachedGetter(orb, entry) {
1195
- trackDependency(orb, entry.key);
1196
- const cache = getGetterCache(orb, entry.key);
1197
- if (cache.hasValue && !cache.dirty) {
1198
- emitOrbEvent(orb, "getter:cache-hit", entry.key);
1199
- return cache.value;
1200
- }
1201
- const computation = getGetterComputation(orb, entry.key);
1202
- try {
1203
- emitOrbEvent(orb, "getter:compute", entry.key);
1204
- const value = runTracked(computation, () => runWithBehaviorAuthority(() => entry.get.call(orb)));
1205
- cache.value = wrapBehaviorFunction(value, orb);
1206
- replaceSubscriptions(computation);
1207
- cache.deps = computation.deps;
1208
- cache.dirty = false;
1209
- cache.hasValue = true;
1210
- return cache.value;
1211
- } catch (error) {
1212
- replaceSubscriptions(computation);
1213
- cache.deps = computation.deps;
1214
- cache.dirty = true;
1215
- cache.hasValue = false;
1216
- throw error;
1217
- }
1218
- }
1219
- function wrapBehaviorFunction(value, orb) {
1220
- if (typeof value !== "function")
1221
- return value;
1222
- return function behaviorFunction(...args) {
1223
- return runWithBehaviorAuthority(() => value.apply(orb, args));
1224
- };
1225
- }
1226
- function getGetterCache(orb, key) {
1227
- const getterCache = ORB_GETTER_CACHE.get(orb);
1228
- if (!getterCache) {
1229
- throw new Error("Invalid Orb receiver");
1230
- }
1231
- if (!getterCache.has(key)) {
1232
- getterCache.set(key, {
1233
- value: undefined,
1234
- deps: new Set,
1235
- dirty: true,
1236
- hasValue: false,
1237
- computation: {
1238
- type: "getter",
1239
- orb,
1240
- key,
1241
- deps: new Set,
1242
- nextDeps: new Set,
1243
- onDependencyChanged() {
1244
- markGetterDirty(orb, key);
1245
- }
1246
- }
1247
- });
1248
- }
1249
- return getterCache.get(key);
1250
- }
1251
- function getGetterComputation(orb, key) {
1252
- return getGetterCache(orb, key).computation;
1253
- }
1254
- function markGetterDependentsDirty(orb, changedKey) {
1255
- const getterCache = ORB_GETTER_CACHE.get(orb);
1256
- if (!getterCache)
1257
- return;
1258
- const changedDependency = createDependencyKey(orb, changedKey);
1259
- for (const [getterKey, cache] of getterCache) {
1260
- if (cache.deps.has(changedDependency)) {
1261
- markGetterDirty(orb, getterKey);
1262
- }
1263
- }
1264
- }
1265
- function markGetterDirty(orb, getterKey) {
1266
- const cache = getGetterCache(orb, getterKey);
1267
- if (cache.dirty) {
1268
- emitOrbEvent(orb, "getter:dirty", getterKey);
1269
- notifyDependencyChanged(orb, getterKey);
1270
- propagateLinkedState(orb, getterKey);
1271
- return;
1272
- }
1273
- cache.dirty = true;
1274
- emitOrbEvent(orb, "getter:dirty", getterKey);
1275
- notifyDependencyChanged(orb, getterKey);
1276
- propagateLinkedState(orb, getterKey);
1277
- markGetterDependentsDirty(orb, getterKey);
1278
- }
1279
- function markStateChanged(orb, key) {
1280
- markGetterDependentsDirty(orb, key);
1281
- notifyDependencyChanged(orb, key);
1282
- propagateLinkedState(orb, key);
1283
- }
1284
- function propagateLinkedState(source, sourceKey) {
1285
- for (const { target, key } of OrbLink.linkedTargets(source, sourceKey)) {
1286
- markStateChanged(target, key);
1287
- }
1288
- }
1289
- function runGeneratorFlow(iterator) {
1290
- return new Promise((resolve, reject) => {
1291
- function step(method, value) {
1292
- let result;
1293
- try {
1294
- result = batch(() => runWithBehaviorAuthority(() => iterator[method](value)));
1295
- } catch (error) {
1296
- reject(error);
1297
- return;
1298
- }
1299
- if (result.done) {
1300
- resolve(result.value);
1301
- return;
1302
- }
1303
- Promise.resolve(result.value).then((value2) => step("next", value2), (error) => step("throw", error));
1304
- }
1305
- step("next");
1306
- });
1307
- }
1308
- function runWithBehaviorAuthority(fn) {
1309
- behaviorDepth++;
1310
- try {
1311
- return fn();
1312
- } finally {
1313
- behaviorDepth--;
1314
- }
1315
- }
1316
- function hasBehaviorAuthority() {
1317
- return behaviorDepth > 0;
1318
- }
1319
- function assertBehaviorAuthority(method) {
1320
- if (!hasBehaviorAuthority()) {
1321
- throw new Error(`node.$.${method}() may only be called from Shape behavior`);
1322
- }
1323
- }
1324
- function getState(orb) {
1325
- const state = ORB_STATE.get(orb);
1326
- if (!state) {
1327
- throw new Error("Invalid Orb receiver");
1328
- }
1329
- return state;
1330
- }
1331
- function emitOrbEvent(orb, type, key) {
1332
- emitInspectionEvent({ type, key, shapeId: ORB_PLAN.get(orb)?.id });
1333
- }
1334
- function cloneDefault(value) {
1335
- if (value === undefined)
1336
- return;
1337
- return JSON.parse(JSON.stringify(value));
1338
- }
1339
- function sanitizeConstructorName(shapeId) {
1340
- const name = shapeId.replace(/[^a-zA-Z0-9_$]/g, "_");
1341
- if (/^[a-zA-Z_$]/.test(name)) {
1342
- return name;
1343
- }
1344
- return `Shape_${name}`;
1345
- }
1346
- function getOrbId(orb) {
1347
- return `$uuid:${getOrbRuntimeId2(orb)}`;
1348
- }
1349
- var nextRuntimeOrbId2 = 1;
1350
- var ORB_RUNTIME_ID2 = new WeakMap;
1351
- function getOrbRuntimeId2(orb) {
1352
- if (!ORB_RUNTIME_ID2.has(orb)) {
1353
- ORB_RUNTIME_ID2.set(orb, nextRuntimeOrbId2++);
1354
- }
1355
- return ORB_RUNTIME_ID2.get(orb);
1356
- }
1357
- function acceptsShape(expectedPlan, value) {
1358
- const valuePlan = FACTORY_PLAN.get(value) ?? ORB_PLAN.get(value);
1359
- if (!valuePlan)
1360
- return false;
1361
- return valuePlan.id === expectedPlan.id || valuePlan.ancestryIds.has(expectedPlan.id);
1362
- }
1363
- function resolveLazyRef(orb, key, value) {
1364
- const plan = ORB_PLAN.get(orb);
1365
- const entry = plan?.byKey.get(key);
1366
- if (!entry || !entry.meta?.serializable) {
1367
- return resolveProtocolLazyRef(orb, key, value);
1368
- }
1369
- const state = ORB_STATE.get(orb);
1370
- if (!state) {
1371
- throw new Error("Invalid Orb receiver");
1372
- }
1373
- if (!(state[key] instanceof LazyRef)) {
1374
- throw new Error(`Slot '${key}' is not a lazy ref`);
1375
- }
1376
- state[key] = prepareStateValue(orb, entry, value);
1377
- batch(() => {
1378
- emitOrbEvent(orb, "state:write", key);
1379
- markStateChanged(orb, key);
1380
- const meta = MEM.ORB_META.get(orb);
1381
- meta?.anchor?.handleOrbSlotChanged?.(orb, key);
1382
- });
1383
- return value;
1384
- }
1385
- function resolveProtocolLazyRef(orb, key, value) {
1386
- const edge = orb[VOCAB.SHAPE.EDGE](key);
1387
- const current = edge.peek();
1388
- if (current !== undefined && !(current instanceof LazyRef)) {
1389
- throw new Error(`Protocol edge '${key}' is not a lazy ref`);
1390
- }
1391
- edge.write(value);
1392
- return value;
1393
- }
1394
-
1395
- class OrbLink {
1396
- constructor(source, key, descriptor) {
1397
- this.source = source;
1398
- this.key = key;
1399
- this.descriptor = descriptor;
1400
- }
1401
- read() {
1402
- return this.source[this.key];
1403
- }
1404
- serialize() {
1405
- return this.descriptor;
1406
- }
1407
- target() {
1408
- return { source: this.source, key: this.key };
1409
- }
1410
- bindOrb(target, key) {
1411
- const dependency = createDependencyKey(this.source, this.key);
1412
- let targets = MEM.LINKS_BY_SOURCE.get(dependency);
1413
- if (!targets) {
1414
- targets = new Set;
1415
- MEM.LINKS_BY_SOURCE.set(dependency, targets);
1416
- }
1417
- targets.add({ target, key });
1418
- }
1419
- static linkedTargets(source, key) {
1420
- const targets = MEM.LINKS_BY_SOURCE.get(createDependencyKey(source, key));
1421
- return targets ? [...targets] : [];
1422
- }
1423
- }
1424
-
1425
- class LazyRef {
1426
- constructor(ref) {
1427
- if (typeof ref !== "string" || ref.length === 0) {
1428
- throw new TypeError("LazyRef expects a non-empty ref string");
1429
- }
1430
- this.ref = ref;
1431
- this.status = "idle";
1432
- }
1433
- }
1434
- function readSlot(value) {
1435
- if (value instanceof OrbLink)
1436
- return value.read();
1437
- if (value instanceof LazyRef)
1438
- return;
1439
- return value;
1440
- }
1441
- function serializeSlot(value) {
1442
- if (value instanceof OrbLink)
1443
- return value.serialize();
1444
- if (value instanceof LazyRef)
1445
- return { $: value.ref };
1446
- return value;
1447
- }
1448
-
1449
- // ../orbz/src/Shape.js
1450
- function Shape(...defs) {
1451
- if (defs.length < 1) {
1452
- throw new TypeError("Shape() expects a definition object");
1453
- }
1454
- const finalDefinition = defs.at(-1);
1455
- const parents = defs.slice(0, -1);
1456
- if (parents.length === 0) {
1457
- const plan2 = createShapePlan(finalDefinition);
1458
- return createOrbFactory(plan2);
1459
- }
1460
- const parentPlans = parents.map((parent) => {
1461
- const plan2 = MEM.FACTORY_PLAN.get(parent);
1462
- if (!plan2) {
1463
- throw new TypeError("Shape extension parents must be Shape factories");
1464
- }
1465
- return plan2;
1466
- });
1467
- const extendedDefinition = createExtendedShapeDefinition(parentPlans, finalDefinition);
1468
- const plan = createShapePlan(extendedDefinition, { parents: parentPlans });
1469
- return createOrbFactory(plan);
1470
- }
1471
- Object.defineProperties(Shape, {
1472
- name: { value: VOCAB.SHAPE.NAME, enumerable: true, configurable: true },
1473
- init: { value: VOCAB.SHAPE.INIT, enumerable: true },
1474
- keys: { value: VOCAB.SHAPE.KEYS, enumerable: true },
1475
- edge: { value: VOCAB.SHAPE.EDGE, enumerable: true },
1476
- save: { value: VOCAB.SHAPE.SAVE, enumerable: true },
1477
- load: { value: VOCAB.SHAPE.LOAD, enumerable: true },
1478
- mounts: { value: VOCAB.SHAPE.MOUNTS, enumerable: true }
1479
- });
1480
- // ../orbz/src/libShapes/Mount.js
1481
- var MOUNT_RESERVED_KEYS = new Set([
1482
- "_mount_values",
1483
- "_mount_statuses",
1484
- "_mount_errors",
1485
- "_mount_logs",
1486
- "_mountApply",
1487
- "_mountDispose"
1488
- ]);
1489
- var FACTORY_CACHE = new WeakMap;
1490
- function createMountedFactory(SourceShape, target) {
1491
- const sourcePlan = MEM.FACTORY_PLAN.get(SourceShape);
1492
- if (!sourcePlan)
1493
- throw new TypeError("createMountedFactory() expects a Shape factory");
1494
- const mount = sourcePlan.mounts?.[target];
1495
- if (!mount)
1496
- return null;
1497
- let byTarget = FACTORY_CACHE.get(SourceShape);
1498
- if (!byTarget) {
1499
- byTarget = new Map;
1500
- FACTORY_CACHE.set(SourceShape, byTarget);
1501
- }
1502
- if (byTarget.has(target))
1503
- return byTarget.get(target);
1504
- assertOrdinarySourceShape(sourcePlan);
1505
- assertReservedKeysAvailable(sourcePlan);
1506
- const mountedName = `${sourcePlan.name}$mount$${target}`;
1507
- const definition = createMountDefinition(sourcePlan, {
1508
- target,
1509
- name: mountedName,
1510
- source: {
1511
- id: sourcePlan.id,
1512
- name: sourcePlan.name
1513
- },
1514
- outsource: mount.outsource,
1515
- projections: mount.projections,
1516
- commands: mount.commands
1517
- });
1518
- const MountedShape = Shape(SourceShape, definition);
1519
- MEM.MOUNT_FACTORIES.set(MountedShape, {
1520
- sourceFactory: SourceShape,
1521
- source: {
1522
- id: sourcePlan.id,
1523
- name: sourcePlan.name
1524
- },
1525
- sourcePlan,
1526
- target,
1527
- shape: {
1528
- id: mountedName,
1529
- name: mountedName
1530
- },
1531
- outsource: [...mount.outsource],
1532
- projections: [...mount.projections],
1533
- commands: [...mount.commands]
1534
- });
1535
- byTarget.set(target, MountedShape);
1536
- return MountedShape;
1537
- }
1538
- function isMountedOrb(value) {
1539
- return MEM.MOUNTS.has(value);
1540
- }
1541
- function getMountSourcePlan(orb) {
1542
- return MEM.MOUNTS.get(orb)?.sourcePlan;
1543
- }
1544
- function bindMountedOrb(anchor, orb) {
1545
- const runtime = MEM.MOUNTS.get(orb);
1546
- if (!runtime)
1547
- return;
1548
- const routes = [...MEM.ORB_META.get(orb)?.routes ?? []];
1549
- const contextKey = `${anchor.id}:${routes.join("|")}`;
1550
- if (runtime.anchor === anchor && runtime.contextKey === contextKey)
1551
- return;
1552
- runtime.unsubscribe?.();
1553
- runtime.anchor = anchor;
1554
- runtime.contextKey = contextKey;
1555
- runtime.routes = routes;
1556
- runtime.unsubscribe = undefined;
1557
- if (routes.length === 0)
1558
- return;
1559
- const subscribe = anchor.adapter.mount?.subscribe;
1560
- if (typeof subscribe !== "function") {
1561
- applyMountPatch2(orb, {
1562
- statuses: Object.fromEntries(runtime.projections.map((key) => [key, "pending"]))
1563
- });
1564
- return;
1565
- }
1566
- const unsubscribe = subscribe.call(anchor.adapter.mount, createMountContext(anchor, orb, runtime), (patch) => applyMountPatch2(orb, patch));
1567
- runtime.unsubscribe = typeof unsubscribe === "function" ? unsubscribe : undefined;
1568
- }
1569
- function disposeMountedOrb(orb) {
1570
- const runtime = MEM.MOUNTS.get(orb);
1571
- if (!runtime)
1572
- return;
1573
- runtime.unsubscribe?.();
1574
- runtime.unsubscribe = undefined;
1575
- runtime.anchor = null;
1576
- MEM.MOUNTS.delete(orb);
1577
- return;
1578
- }
1579
- function commandMountedOrb(orb, method, args) {
1580
- const runtime = MEM.MOUNTS.get(orb);
1581
- if (!runtime) {
1582
- throw new Error(`Cannot call mounted method '${method}' on a non-mounted Orb`);
1583
- }
1584
- const anchor = runtime.anchor ?? MEM.ORB_META.get(orb)?.anchor;
1585
- const command = anchor?.adapter.mount?.command;
1586
- if (typeof command !== "function") {
1587
- throw new Error(`Mounted method '${method}' requires an Anchor mount adapter`);
1588
- }
1589
- return command.call(anchor.adapter.mount, createMountContext(anchor, orb, runtime), method, args);
1590
- }
1591
- function applyMountPatch2(orb, patch = {}) {
1592
- const runtime = MEM.MOUNTS.get(orb);
1593
- if (!runtime)
1594
- return;
1595
- const normalized = normalizePatch(patch);
1596
- const apply = orb?._mountApply;
1597
- if (typeof apply !== "function") {
1598
- throw new Error("Mounted orb is missing generated _mountApply()");
1599
- }
1600
- return apply.call(orb, normalized);
1601
- }
1602
- function createMountDefinition(sourcePlan, config) {
1603
- const projections = new Set(config.projections);
1604
- const commands = new Set(config.commands);
1605
- const definition = {};
1606
- Object.defineProperty(definition, VOCAB.SHAPE.NAME, {
1607
- value: config.name,
1608
- enumerable: true,
1609
- configurable: true
1610
- });
1611
- for (const key of projections) {
1612
- const descriptor = sourcePlan.descriptors[key];
1613
- Object.defineProperty(definition, key, {
1614
- get() {
1615
- return this._mount_values[key];
1616
- },
1617
- enumerable: descriptor.enumerable,
1618
- configurable: descriptor.configurable
1619
- });
1620
- }
1621
- for (const key of commands) {
1622
- const descriptor = sourcePlan.descriptors[key];
1623
- Object.defineProperty(definition, key, {
1624
- value(...args) {
1625
- return commandMountedOrb(this, key, args);
1626
- },
1627
- enumerable: descriptor.enumerable,
1628
- configurable: descriptor.configurable,
1629
- writable: descriptor.writable
1630
- });
1631
- }
1632
- defineMountState(definition);
1633
- defineGeneratedMethod(definition, "_mountApply", mountApplyBehavior);
1634
- defineGeneratedMethod(definition, "_mountDispose", mountDisposeBehavior);
1635
- defineMountProtocol(definition, sourcePlan);
1636
- Object.defineProperty(definition, VOCAB.SHAPE.INIT, {
1637
- value(input = {}) {
1638
- initializeMountRuntime(this, config);
1639
- return normalizeConstructorState(input, "Orb constructor input");
1640
- },
1641
- enumerable: true,
1642
- configurable: true,
1643
- writable: true
1644
- });
1645
- Object.defineProperty(definition, VOCAB.SHAPE.LOAD, {
1646
- value(input = {}) {
1647
- initializeMountRuntime(this, config);
1648
- return normalizeConstructorState(input, "Orb hydration record");
1649
- },
1650
- enumerable: true,
1651
- configurable: true,
1652
- writable: true
1653
- });
1654
- return definition;
1655
- }
1656
- function defineMountProtocol(definition, sourcePlan) {
1657
- const sourceKeys = sourcePlan.serializable.map((entry) => entry.key);
1658
- const sourceKeySet = new Set(sourceKeys);
1659
- Object.defineProperty(definition, VOCAB.SHAPE.KEYS, {
1660
- value() {
1661
- return [...sourceKeys];
1662
- },
1663
- enumerable: true,
1664
- configurable: true,
1665
- writable: true
1666
- });
1667
- Object.defineProperty(definition, VOCAB.SHAPE.EDGE, {
1668
- value(key) {
1669
- if (!sourceKeySet.has(key)) {
1670
- throw new Error(`Unknown mount edge '${String(key)}'`);
1671
- }
1672
- return {
1673
- key,
1674
- segment: String(key),
1675
- read: () => this[key],
1676
- peek: () => this[key],
1677
- write: (value) => {
1678
- this[key] = value;
1679
- return value;
1680
- }
1681
- };
1682
- },
1683
- enumerable: true,
1684
- configurable: true,
1685
- writable: true
1686
- });
1687
- Object.defineProperty(definition, VOCAB.SHAPE.SAVE, {
1688
- value() {
1689
- const out = {};
1690
- for (const key of sourceKeys) {
1691
- out[key] = this[key];
1692
- }
1693
- return out;
1694
- },
1695
- enumerable: true,
1696
- configurable: true,
1697
- writable: true
1698
- });
1699
- }
1700
- function defineMountState(definition) {
1701
- Object.defineProperties(definition, {
1702
- _mount_values: {
1703
- value: {},
1704
- enumerable: true,
1705
- configurable: true,
1706
- writable: true
1707
- },
1708
- _mount_statuses: {
1709
- value: {},
1710
- enumerable: true,
1711
- configurable: true,
1712
- writable: true
1713
- },
1714
- _mount_errors: {
1715
- value: {},
1716
- enumerable: true,
1717
- configurable: true,
1718
- writable: true
1719
- },
1720
- _mount_logs: {
1721
- value: [],
1722
- enumerable: true,
1723
- configurable: true,
1724
- writable: true
1725
- }
1726
- });
1727
- }
1728
- function defineGeneratedMethod(definition, key, value) {
1729
- Object.defineProperty(definition, key, {
1730
- value,
1731
- enumerable: false,
1732
- configurable: true,
1733
- writable: true
1734
- });
1735
- }
1736
- function initializeMountRuntime(orb, config) {
1737
- MEM.MOUNTS.set(orb, {
1738
- source: config.source,
1739
- sourcePlan: null,
1740
- target: config.target,
1741
- shape: {
1742
- id: config.name,
1743
- name: config.name
1744
- },
1745
- outsource: [...config.outsource],
1746
- projections: [...config.projections],
1747
- commands: [...config.commands],
1748
- anchor: null,
1749
- routes: [],
1750
- contextKey: "",
1751
- unsubscribe: undefined
1752
- });
1753
- const factoryInfo = MEM.MOUNT_FACTORIES.get(MEM.ORB_PLAN.get(orb)?.factory);
1754
- const runtime = MEM.MOUNTS.get(orb);
1755
- if (factoryInfo) {
1756
- runtime.sourcePlan = factoryInfo.sourcePlan;
1757
- }
1758
- }
1759
- function mountApplyBehavior(patch = {}) {
1760
- const normalized = normalizePatch(patch);
1761
- if (normalized.values) {
1762
- this._mount_values = {
1763
- ...readObjectState(this._mount_values),
1764
- ...normalized.values
1765
- };
1766
- }
1767
- if (normalized.statuses) {
1768
- this._mount_statuses = {
1769
- ...readObjectState(this._mount_statuses),
1770
- ...normalized.statuses
1771
- };
1772
- }
1773
- if (normalized.errors) {
1774
- this._mount_errors = {
1775
- ...readObjectState(this._mount_errors),
1776
- ...normalized.errors
1777
- };
1778
- }
1779
- if (normalized.logs) {
1780
- this._mount_logs = [
1781
- ...readArrayState(this._mount_logs),
1782
- ...normalized.logs
1783
- ];
1784
- }
1785
- return this;
1786
- }
1787
- function mountDisposeBehavior() {
1788
- return disposeMountedOrb(this);
1789
- }
1790
- function createMountContext(anchor, orb, runtime) {
1791
- const meta = MEM.ORB_META.get(orb);
1792
- return {
1793
- anchor,
1794
- anchorId: anchor.id,
1795
- orb,
1796
- uuid: meta?.uuid,
1797
- routes: [...meta?.routes ?? []],
1798
- sourceShape: { ...runtime.source },
1799
- mountShape: { ...runtime.shape },
1800
- target: runtime.target,
1801
- outsource: [...runtime.outsource],
1802
- projections: [...runtime.projections],
1803
- commands: [...runtime.commands]
1804
- };
1805
- }
1806
- function normalizePatch(patch) {
1807
- if (!patch || typeof patch !== "object" || Array.isArray(patch)) {
1808
- throw new TypeError("Mount patch must be an object");
1809
- }
1810
- const normalized = {};
1811
- if (patch.values !== undefined) {
1812
- assertPlainObject(patch.values, "Mount patch values");
1813
- normalized.values = patch.values;
1814
- }
1815
- if (patch.statuses !== undefined) {
1816
- assertPlainObject(patch.statuses, "Mount patch statuses");
1817
- for (const [key, value] of Object.entries(patch.statuses)) {
1818
- if (typeof value !== "string") {
1819
- throw new TypeError(`Mount patch status '${key}' must be a string`);
1820
- }
1821
- }
1822
- normalized.statuses = patch.statuses;
1823
- }
1824
- if (patch.errors !== undefined) {
1825
- assertPlainObject(patch.errors, "Mount patch errors");
1826
- normalized.errors = patch.errors;
1827
- }
1828
- if (patch.logs !== undefined) {
1829
- if (!Array.isArray(patch.logs)) {
1830
- throw new TypeError("Mount patch logs must be an array");
1831
- }
1832
- normalized.logs = patch.logs;
1833
- }
1834
- return normalized;
1835
- }
1836
- function normalizeConstructorState(input, label) {
1837
- if (!input || typeof input !== "object" || Array.isArray(input)) {
1838
- throw new TypeError(`${label} must be an object`);
1839
- }
1840
- return input;
1841
- }
1842
- function readObjectState(value) {
1843
- if (value && typeof value === "object" && !Array.isArray(value))
1844
- return value;
1845
- return {};
1846
- }
1847
- function readArrayState(value) {
1848
- if (Array.isArray(value))
1849
- return value;
1850
- return [];
1851
- }
1852
- function assertOrdinarySourceShape(sourcePlan) {
1853
- for (const symbol of VOCAB.SHAPE_SYMBOLS) {
1854
- if (symbol !== VOCAB.SHAPE.NAME && symbol !== VOCAB.SHAPE.MOUNTS && sourcePlan.protocol[protocolKey(symbol)]) {
1855
- throw new Error(`Mount only supports ordinary Shapes (Shape '${sourcePlan.id}')`);
1856
- }
1857
- }
1858
- }
1859
- function protocolKey(symbol) {
1860
- if (symbol === VOCAB.SHAPE.INIT)
1861
- return "init";
1862
- if (symbol === VOCAB.SHAPE.KEYS)
1863
- return "keys";
1864
- if (symbol === VOCAB.SHAPE.EDGE)
1865
- return "edge";
1866
- if (symbol === VOCAB.SHAPE.SAVE)
1867
- return "save";
1868
- if (symbol === VOCAB.SHAPE.LOAD)
1869
- return "load";
1870
- throw new Error("Unknown Shape protocol symbol");
1871
- }
1872
- function assertReservedKeysAvailable(sourcePlan) {
1873
- for (const key of MOUNT_RESERVED_KEYS) {
1874
- if (sourcePlan.byKey.has(key)) {
1875
- throw new Error(`Cannot mount Shape '${sourcePlan.id}' because '${key}' is reserved for Mount`);
1876
- }
1877
- }
1878
- }
1879
- function assertPlainObject(value, label) {
1880
- if (!value || typeof value !== "object" || Array.isArray(value)) {
1881
- throw new TypeError(`${label} must be an object`);
1882
- }
1883
- }
1884
-
1885
- // ../orbz/src/Anchor.js
1886
- class Anchor {
1887
- constructor(options = {}) {
1888
- const normalized = typeof options === "string" ? { id: options } : options;
1889
- this.id = normalized.id ?? `anchor${MEM.LAST_ANCHOR_ID++}`;
1890
- this._connections = new Map;
1891
- this._uuidToOrb = new Map;
1892
- this._routeToUuid = new Map;
1893
- this._observers = new Set;
1894
- this._nextUuid = 1;
1895
- this.adapter = normalized.adapter ?? createMemoryAdapter();
1896
- this.loading = normalized.loading ?? "eager";
1897
- this.mountTargets = normalizeMountTargets(normalized.mountTargets ?? normalized.mountTarget);
1898
- this._resolveAnchor = normalized.resolveAnchor ?? null;
1899
- this._dirty = new Set;
1900
- this._deletedRoutes = new Set;
1901
- this._pendingLazyByUuid = new Map;
1902
- this._disposed = false;
1903
- this._autosaveRunning = false;
1904
- this._autosaveTimer = null;
1905
- if (normalized.autosave) {
1906
- this._startAutosave(normalized.autosave);
1907
- }
1908
- }
1909
- connect(anchor) {
1910
- if (!anchor || typeof anchor.id !== "string") {
1911
- throw new TypeError("connect() expects an Anchor");
1912
- }
1913
- if (hasSharedAnchorId(this, anchor)) {
1914
- throw new Error(`Anchor '${anchor.id}' is already connected`);
1915
- }
1916
- this._connections.set(anchor.id, anchor);
1917
- }
1918
- observe(listener) {
1919
- if (typeof listener !== "function") {
1920
- throw new TypeError("Anchor.observe() expects a listener function");
1921
- }
1922
- this._observers.add(listener);
1923
- let active = true;
1924
- return () => {
1925
- if (!active)
1926
- return;
1927
- active = false;
1928
- this._observers.delete(listener);
1929
- };
1930
- }
1931
- adoptRuntimeOrb(orb) {
1932
- return this._ensureOrb(orb);
1933
- }
1934
- resolveMount(shapeFactory) {
1935
- if (typeof shapeFactory !== "function") {
1936
- throw new TypeError("Anchor.resolveMount() expects a Shape factory");
1937
- }
1938
- for (const target of this.mountTargets) {
1939
- const mounted = createMountedFactory(shapeFactory, target);
1940
- if (mounted)
1941
- return mounted;
1942
- }
1943
- return;
1944
- }
1945
- set(route, orb) {
1946
- assertRoute(route);
1947
- return this._adoptValueAtRoute(route, orb) || orb;
1948
- }
1949
- handleOrbSlotChanged(orb, key) {
1950
- const meta = MEM.ORB_META.get(orb);
1951
- if (meta?.anchor === this) {
1952
- this._dirty.add(meta.uuid);
1953
- const shape = MEM.ORB_PLAN.get(orb)?.id;
1954
- const edge = getEdge(orb, key);
1955
- if (!edge) {
1956
- for (const route of meta.routes) {
1957
- this._deriveOrbRoutes(orb, route);
1958
- }
1959
- return;
1960
- }
1961
- this._emitObserve({
1962
- type: "state:write",
1963
- uuid: meta.uuid,
1964
- shape,
1965
- key,
1966
- value: this._serializeValue(edge.peek()),
1967
- routes: [...meta.routes]
1968
- });
1969
- for (const route of meta.routes) {
1970
- const edgeRoute = joinRoute(route, edge.segment);
1971
- if (!this._adoptValueAtRoute(edgeRoute, edge.peek())) {
1972
- this._deleteRoute(edgeRoute);
1973
- }
1974
- }
1975
- return;
1976
- }
1977
- }
1978
- handleOrbProtocolChanged(orb) {
1979
- const meta = MEM.ORB_META.get(orb);
1980
- if (!meta || meta.anchor !== this)
1981
- return;
1982
- this._dirty.add(meta.uuid);
1983
- this._emitObserve({
1984
- type: "protocol:change",
1985
- uuid: meta.uuid,
1986
- shape: MEM.ORB_PLAN.get(orb)?.id,
1987
- routes: [...meta.routes]
1988
- });
1989
- for (const route of meta.routes) {
1990
- this._deriveOrbRoutes(orb, route);
1991
- }
1992
- }
1993
- at(route) {
1994
- const { anchor, local } = this._resolveRouteOwner(route);
1995
- trackDependency(anchor, routeDependency(local));
1996
- return anchor.get(local);
1997
- }
1998
- get(routeOrUuid) {
1999
- if (typeof routeOrUuid !== "string") {
2000
- throw new TypeError("Anchor.get() expects a route or UUID ref");
2001
- }
2002
- if (routeOrUuid.startsWith("$uuid:")) {
2003
- return this._uuidToOrb.get(parseUuidRef(routeOrUuid).uuid);
2004
- }
2005
- const { anchor, local } = this._resolveRouteOwner(routeOrUuid);
2006
- const uuid = anchor._routeToUuid.get(local);
2007
- return uuid ? anchor._uuidToOrb.get(uuid) : undefined;
2008
- }
2009
- async load(routeOrUuid) {
2010
- if (routeOrUuid.startsWith("$uuid:")) {
2011
- return this._loadUuid(parseUuidRef(routeOrUuid).uuid);
2012
- }
2013
- const { anchor, local } = await this._resolveRouteOwnerAsync(routeOrUuid);
2014
- if (anchor !== this) {
2015
- return anchor.load(local);
2016
- }
2017
- let uuid = this._routeToUuid.get(local);
2018
- if (!uuid) {
2019
- uuid = await this.adapter.routes?.get?.(local);
2020
- }
2021
- if (!uuid)
2022
- return;
2023
- assertUuid(uuid, `Malformed route '${local}'`);
2024
- const orb = await this._loadUuid(uuid);
2025
- this._setRoute(local, uuid);
2026
- this._deriveOrbRoutes(orb, local);
2027
- return orb;
2028
- }
2029
- async save(routeOrUuid) {
2030
- if (routeOrUuid) {
2031
- if (!routeOrUuid.startsWith("$uuid:")) {
2032
- const { anchor, local } = this._resolveRouteOwner(routeOrUuid);
2033
- if (anchor !== this) {
2034
- return anchor.save(local);
2035
- }
2036
- const uuid = this._routeToUuid.get(local);
2037
- if (uuid) {
2038
- this._deletedRoutes.delete(local);
2039
- await this.adapter.routes?.set?.(local, uuid);
2040
- }
2041
- }
2042
- const orb = this.get(routeOrUuid);
2043
- if (!orb)
2044
- return;
2045
- await this._saveOrb(orb);
2046
- return;
2047
- }
2048
- await this.saveAllDirty();
2049
- }
2050
- async saveAllDirty() {
2051
- for (const [route, uuid] of this._routeToUuid) {
2052
- this._deletedRoutes.delete(route);
2053
- await this.adapter.routes?.set?.(route, uuid);
2054
- }
2055
- for (const route of this._deletedRoutes) {
2056
- await this.adapter.routes?.delete?.(route);
2057
- }
2058
- this._deletedRoutes.clear();
2059
- const reachable = this._collectLiveReachableUuids();
2060
- const dirty = [...this._dirty].filter((uuid) => reachable.has(uuid));
2061
- this._dirty.clear();
2062
- for (const uuid of dirty) {
2063
- const orb = this._uuidToOrb.get(uuid);
2064
- if (orb) {
2065
- await this._saveOrb(orb);
2066
- }
2067
- }
2068
- }
2069
- async collectGarbage() {
2070
- const listRoutes = this.adapter.routes?.list;
2071
- const deleteRoute = this.adapter.routes?.delete;
2072
- const listOrbs = this.adapter.state?.listOrbs;
2073
- const deleteOrb = this.adapter.state?.deleteOrb;
2074
- if (typeof listRoutes !== "function") {
2075
- throw new Error("Anchor GC requires adapter.routes.list()");
2076
- }
2077
- if (typeof deleteRoute !== "function") {
2078
- throw new Error("Anchor GC requires adapter.routes.delete()");
2079
- }
2080
- if (typeof listOrbs !== "function") {
2081
- throw new Error("Anchor GC requires adapter.state.listOrbs()");
2082
- }
2083
- if (typeof deleteOrb !== "function") {
2084
- throw new Error("Anchor GC requires adapter.state.deleteOrb()");
2085
- }
2086
- await this.saveAllDirty();
2087
- const routeRecords = await listRoutes.call(this.adapter.routes);
2088
- const orbRecords = await listOrbs.call(this.adapter.state);
2089
- const recordsByUuid = new Map;
2090
- const routeToUuid = new Map;
2091
- for (const record of orbRecords ?? []) {
2092
- if (record?.uuid) {
2093
- recordsByUuid.set(record.uuid, record);
2094
- }
2095
- }
2096
- for (const record of routeRecords ?? []) {
2097
- if (!record)
2098
- continue;
2099
- const route = record.route;
2100
- const uuid = record.uuid;
2101
- assertRoute(route);
2102
- assertUuid(uuid, `Malformed route '${route}'`);
2103
- routeToUuid.set(route, uuid);
2104
- }
2105
- const retained = new Set;
2106
- const pending = [...routeToUuid.values()];
2107
- while (pending.length > 0) {
2108
- const uuid = pending.pop();
2109
- if (retained.has(uuid))
2110
- continue;
2111
- retained.add(uuid);
2112
- const record = recordsByUuid.get(uuid);
2113
- if (!record)
2114
- continue;
2115
- assertOrbRecord(record, uuid);
2116
- for (const ref of collectSerializedRefs(record.state)) {
2117
- const targetUuid = resolveLocalSerializedRef(ref, routeToUuid, this.id);
2118
- if (targetUuid && !retained.has(targetUuid)) {
2119
- pending.push(targetUuid);
2120
- }
2121
- }
2122
- }
2123
- const deleted = [];
2124
- for (const uuid of recordsByUuid.keys()) {
2125
- if (retained.has(uuid))
2126
- continue;
2127
- await deleteOrb.call(this.adapter.state, uuid);
2128
- this._dirty.delete(uuid);
2129
- deleted.push(uuid);
2130
- }
2131
- return { retained: retained.size, deleted };
2132
- }
2133
- dispose() {
2134
- if (this._disposed)
2135
- return;
2136
- this._disposed = true;
2137
- if (this._autosaveTimer) {
2138
- clearInterval(this._autosaveTimer);
2139
- this._autosaveTimer = null;
2140
- }
2141
- for (const orb of this._uuidToOrb.values()) {
2142
- disposeMountedOrb(orb);
2143
- }
2144
- }
2145
- fullRef(ref) {
2146
- if (ref.startsWith("$uuid:") || ref.includes(":"))
2147
- return ref;
2148
- return `${this.id}:${ref}`;
2149
- }
2150
- _ensureOrb(orb) {
2151
- if (!MEM.ORB_PLAN.get(orb)) {
2152
- throw new TypeError("Anchor can only adopt Orb nodes");
2153
- }
2154
- const existing = MEM.ORB_META.get(orb);
2155
- if (existing?.anchor === this) {
2156
- return existing.uuid;
2157
- }
2158
- const uuid = this._createUuid();
2159
- MEM.ORB_META.set(orb, {
2160
- anchor: this,
2161
- uuid,
2162
- routes: existing?.routes ?? new Set
2163
- });
2164
- this._uuidToOrb.set(uuid, orb);
2165
- this._dirty.add(uuid);
2166
- bindMountedOrb(this, orb);
2167
- return uuid;
2168
- }
2169
- _adoptValueAtRoute(route, value) {
2170
- if (value instanceof LazyRef) {
2171
- const ref = parseLazyUuidRef(value);
2172
- if (ref && !ref.path) {
2173
- this._setRoute(route, ref.uuid, { dirty: false });
2174
- return true;
2175
- }
2176
- return false;
2177
- }
2178
- if (MEM.ORB_PLAN.get(value)) {
2179
- const adopted = this._mountValueForAnchor(value);
2180
- const uuid = this._ensureOrb(adopted);
2181
- this._setRoute(route, uuid);
2182
- this._deriveOrbRoutes(adopted, route);
2183
- return adopted;
2184
- }
2185
- return false;
2186
- }
2187
- _deriveOrbRoutes(orb, route) {
2188
- if (!MEM.ORB_PLAN.get(orb))
2189
- return;
2190
- const seenRoutes = new Set;
2191
- for (const edge of getEdges(orb)) {
2192
- const edgeRoute = joinRoute(route, edge.segment);
2193
- if (this._adoptValueAtRoute(edgeRoute, edge.peek())) {
2194
- seenRoutes.add(edgeRoute);
2195
- }
2196
- }
2197
- for (const existingRoute of [...this._routeToUuid.keys()]) {
2198
- if (isDirectEdgeRoute(route, existingRoute) && !seenRoutes.has(existingRoute)) {
2199
- this._deleteRoute(existingRoute);
2200
- }
2201
- }
2202
- }
2203
- _createUuid() {
2204
- const adapterUuid = this.adapter.state?.createUuid?.();
2205
- if (adapterUuid) {
2206
- return adapterUuid;
2207
- }
2208
- return `${this.id.replace(/[^a-zA-Z0-9_-]/g, "_")}_${this._nextUuid++}`;
2209
- }
2210
- _setRoute(route, uuid, options = {}) {
2211
- const previousUuid = this._routeToUuid.get(route);
2212
- const dirty = options.dirty ?? true;
2213
- this._deletedRoutes.delete(route);
2214
- this._routeToUuid.set(route, uuid);
2215
- const orb = this._uuidToOrb.get(uuid);
2216
- if (orb) {
2217
- const meta = MEM.ORB_META.get(orb);
2218
- meta.routes.add(route);
2219
- bindMountedOrb(this, orb);
2220
- }
2221
- if (dirty) {
2222
- this._dirty.add(uuid);
2223
- }
2224
- notifyDependencyChanged(this, routeDependency(route));
2225
- const event = {
2226
- type: "route:set",
2227
- route,
2228
- uuid
2229
- };
2230
- if (previousUuid && previousUuid !== uuid) {
2231
- event.previousUuid = previousUuid;
2232
- }
2233
- if (orb) {
2234
- event.shape = MEM.ORB_PLAN.get(orb)?.id;
2235
- }
2236
- this._emitObserve(event);
2237
- }
2238
- _deleteRoute(route) {
2239
- const uuid = this._routeToUuid.get(route);
2240
- if (!uuid)
2241
- return;
2242
- this._routeToUuid.delete(route);
2243
- this._deletedRoutes.add(route);
2244
- const orb = this._uuidToOrb.get(uuid);
2245
- const meta = orb ? MEM.ORB_META.get(orb) : null;
2246
- meta?.routes?.delete(route);
2247
- if (orb)
2248
- bindMountedOrb(this, orb);
2249
- notifyDependencyChanged(this, routeDependency(route));
2250
- this._emitObserve({
2251
- type: "route:delete",
2252
- route,
2253
- uuid
2254
- });
2255
- }
2256
- _emitObserve(event) {
2257
- if (this._observers.size === 0)
2258
- return;
2259
- const frozen = Object.freeze({
2260
- anchorId: this.id,
2261
- ...event
2262
- });
2263
- for (const observer of [...this._observers]) {
2264
- observer(frozen);
2265
- }
2266
- }
2267
- async _saveOrb(orb) {
2268
- const meta = MEM.ORB_META.get(orb);
2269
- const plan = MEM.ORB_PLAN.get(orb);
2270
- if (!meta || !plan)
2271
- return;
2272
- const sourcePlan = getMountSourcePlan(orb);
2273
- const record = {
2274
- uuid: meta.uuid,
2275
- shape: sourcePlan?.id ?? plan.id,
2276
- state: sourcePlan ? this._serializeOrbStateForPlan(orb, sourcePlan) : this._serializeOrbState(orb)
2277
- };
2278
- await this.adapter.state?.saveOrb?.(record);
2279
- }
2280
- _serializeOrbState(orb) {
2281
- const saved = orb[VOCAB.SHAPE.SAVE]();
2282
- if (Array.isArray(saved)) {
2283
- const out2 = [];
2284
- for (const edge of getEdges(orb)) {
2285
- out2[Number(edge.key)] = this._serializeValue(edge.peek());
2286
- }
2287
- return out2;
2288
- }
2289
- if (!saved || typeof saved !== "object") {
2290
- return saved;
2291
- }
2292
- const out = JSON.parse(JSON.stringify(saved));
2293
- for (const edge of getEdges(orb)) {
2294
- out[edge.key] = this._serializeValue(edge.peek());
2295
- }
2296
- return out;
2297
- }
2298
- _serializeValue(value) {
2299
- if (value instanceof OrbLink) {
2300
- const { source, key } = value.target();
2301
- return { $: `$uuid:${this._ensureOrb(source)}/${key}` };
2302
- }
2303
- if (value instanceof LazyRef) {
2304
- return { $: value.ref };
2305
- }
2306
- if (MEM.ORB_PLAN.get(value)) {
2307
- return { $: `$uuid:${this._ensureOrb(value)}` };
2308
- }
2309
- if (value === undefined)
2310
- return;
2311
- return JSON.parse(JSON.stringify(value));
2312
- }
2313
- _serializeOrbStateForPlan(orb, plan) {
2314
- const out = {};
2315
- for (const entry of plan.serializable) {
2316
- const edge = orb[VOCAB.SHAPE.EDGE](entry.key);
2317
- out[entry.key] = this._serializeValue(edge.peek());
2318
- }
2319
- return out;
2320
- }
2321
- _collectLiveReachableUuids() {
2322
- const reachable = new Set;
2323
- for (const uuid of this._routeToUuid.values()) {
2324
- this._collectLiveReachableUuid(uuid, reachable);
2325
- }
2326
- return reachable;
2327
- }
2328
- _collectLiveReachableUuid(uuid, reachable) {
2329
- if (!uuid || reachable.has(uuid))
2330
- return;
2331
- reachable.add(uuid);
2332
- const orb = this._uuidToOrb.get(uuid);
2333
- if (!orb)
2334
- return;
2335
- for (const edge of getEdges(orb)) {
2336
- this._collectLiveReachableValue(edge.peek(), reachable);
2337
- }
2338
- }
2339
- _collectLiveReachableValue(value, reachable) {
2340
- if (value instanceof OrbLink) {
2341
- const { source } = value.target();
2342
- this._collectLiveReachableUuid(this._ensureOrb(source), reachable);
2343
- return;
2344
- }
2345
- if (value instanceof LazyRef) {
2346
- const ref = parseLazyUuidRef(value);
2347
- if (ref) {
2348
- this._collectLiveReachableUuid(ref.uuid, reachable);
2349
- }
2350
- return;
2351
- }
2352
- if (MEM.ORB_PLAN.get(value)) {
2353
- this._collectLiveReachableUuid(this._ensureOrb(value), reachable);
2354
- }
2355
- }
2356
- async _loadUuid(uuid) {
2357
- assertUuid(uuid, "Malformed UUID");
2358
- if (this._uuidToOrb.has(uuid)) {
2359
- return this._uuidToOrb.get(uuid);
2360
- }
2361
- const record = await this.adapter.state?.loadOrb?.(uuid);
2362
- if (!record)
2363
- return;
2364
- assertOrbRecord(record, uuid);
2365
- let shape = await this.adapter.shapes?.load?.(record.shape);
2366
- if (!shape) {
2367
- throw new Error(`Missing Shape '${record.shape}'`);
2368
- }
2369
- shape = this.resolveMount(shape) ?? shape;
2370
- const input = await this._reviveValue(record.state);
2371
- const orb = shape.hydrate(input);
2372
- MEM.ORB_META.set(orb, {
2373
- anchor: this,
2374
- uuid,
2375
- routes: new Set
2376
- });
2377
- this._uuidToOrb.set(uuid, orb);
2378
- this._registerLazyInputTargets(orb, input);
2379
- this._registerLazyEdges(orb);
2380
- this._resolvePendingLazy(uuid, orb);
2381
- this._deriveOrbRoutesFromKnownRoutes(orb);
2382
- return orb;
2383
- }
2384
- _mountValueForAnchor(value) {
2385
- if (isMountedOrb(value))
2386
- return value;
2387
- const plan = MEM.ORB_PLAN.get(value);
2388
- const factory = plan?.factory;
2389
- if (!factory)
2390
- return value;
2391
- const mountedFactory = this.resolveMount(factory);
2392
- if (!mountedFactory)
2393
- return value;
2394
- return mountedFactory.hydrate(this._serializeOrbStateForPlan(value, plan));
2395
- }
2396
- async _reviveValue(value) {
2397
- if (isSerializedRef(value)) {
2398
- const ref = value.$;
2399
- if (ref.startsWith("$uuid:")) {
2400
- const { uuid, path } = parseUuidRef(ref);
2401
- if (this.loading === "lazy" && !path) {
2402
- return new LazyRef(ref);
2403
- }
2404
- const target = await this._loadUuid(uuid);
2405
- return path ? target.$(path) : target;
2406
- }
2407
- return this.load(ref);
2408
- }
2409
- if (Array.isArray(value)) {
2410
- const out = [];
2411
- for (const item of value) {
2412
- out.push(await this._reviveValue(item));
2413
- }
2414
- return out;
2415
- }
2416
- if (value && typeof value === "object") {
2417
- const out = {};
2418
- for (const [key, nested] of Object.entries(value)) {
2419
- out[key] = await this._reviveValue(nested);
2420
- }
2421
- return out;
2422
- }
2423
- return value;
2424
- }
2425
- _deriveOrbRoutesFromKnownRoutes(orb) {
2426
- const meta = MEM.ORB_META.get(orb);
2427
- if (!meta)
2428
- return;
2429
- for (const [route, uuid] of this._routeToUuid) {
2430
- if (uuid === meta.uuid) {
2431
- meta.routes.add(route);
2432
- this._deriveOrbRoutes(orb, route);
2433
- }
2434
- }
2435
- }
2436
- _registerLazyEdges(orb) {
2437
- for (const edge of getEdges(orb)) {
2438
- this._registerLazyTarget(orb, edge.key, edge.peek());
2439
- }
2440
- }
2441
- _registerLazyInputTargets(orb, input) {
2442
- if (!input || typeof input !== "object")
2443
- return;
2444
- if (Array.isArray(input)) {
2445
- input.forEach((value, index) => {
2446
- this._registerLazyTarget(orb, String(index), value);
2447
- });
2448
- return;
2449
- }
2450
- for (const [key, value] of Object.entries(input)) {
2451
- this._registerLazyTarget(orb, key, value);
2452
- }
2453
- }
2454
- _registerLazyTarget(target, key, value) {
2455
- const ref = parseLazyUuidRef(value);
2456
- if (!ref || ref.path)
2457
- return;
2458
- let pending = this._pendingLazyByUuid.get(ref.uuid);
2459
- if (!pending) {
2460
- pending = new Set;
2461
- this._pendingLazyByUuid.set(ref.uuid, pending);
2462
- }
2463
- for (const entry of pending) {
2464
- if (entry.target === target && entry.key === key) {
2465
- return;
2466
- }
2467
- }
2468
- pending.add({ target, key });
2469
- }
2470
- _resolvePendingLazy(uuid, value) {
2471
- const pending = this._pendingLazyByUuid.get(uuid);
2472
- if (!pending)
2473
- return;
2474
- this._pendingLazyByUuid.delete(uuid);
2475
- for (const { target, key } of pending) {
2476
- resolveLazyRef(target, key, value);
2477
- }
2478
- }
2479
- _resolveRouteOwner(ref) {
2480
- const parsed = parseRouteRef(ref);
2481
- if (!parsed.anchorId || parsed.anchorId === this.id) {
2482
- return { anchor: this, local: parsed.route };
2483
- }
2484
- const connected = this._findConnectedAnchor(parsed.anchorId);
2485
- if (!connected) {
2486
- const resolved = this._resolveConfiguredAnchor(parsed.anchorId);
2487
- if (isPromiseLike(resolved)) {
2488
- throw new Error(`Async Anchor resolver for '${parsed.anchorId}' requires load()`);
2489
- }
2490
- if (resolved) {
2491
- return { anchor: resolved, local: parsed.route };
2492
- }
2493
- throw new Error(`Unresolved Anchor '${parsed.anchorId}'`);
2494
- }
2495
- return { anchor: connected, local: parsed.route };
2496
- }
2497
- async _resolveRouteOwnerAsync(ref) {
2498
- const parsed = parseRouteRef(ref);
2499
- if (!parsed.anchorId || parsed.anchorId === this.id) {
2500
- return { anchor: this, local: parsed.route };
2501
- }
2502
- const connected = this._findConnectedAnchor(parsed.anchorId);
2503
- if (connected) {
2504
- return { anchor: connected, local: parsed.route };
2505
- }
2506
- const resolved = await this._resolveConfiguredAnchor(parsed.anchorId);
2507
- if (!resolved) {
2508
- throw new Error(`Unresolved Anchor '${parsed.anchorId}'`);
2509
- }
2510
- assertResolvedAnchor(parsed.anchorId, resolved);
2511
- return { anchor: resolved, local: parsed.route };
2512
- }
2513
- _resolveConfiguredAnchor(anchorId) {
2514
- if (!this._resolveAnchor)
2515
- return null;
2516
- const anchor = this._resolveAnchor(anchorId);
2517
- if (!anchor || isPromiseLike(anchor))
2518
- return anchor;
2519
- assertResolvedAnchor(anchorId, anchor);
2520
- return anchor;
2521
- }
2522
- _findConnectedAnchor(anchorId, seen = new Set) {
2523
- if (this.id === anchorId)
2524
- return this;
2525
- if (seen.has(this))
2526
- return null;
2527
- seen.add(this);
2528
- for (const anchor of this._connections.values()) {
2529
- const found = anchor._findConnectedAnchor(anchorId, seen);
2530
- if (found)
2531
- return found;
2532
- }
2533
- return null;
2534
- }
2535
- _collectAnchorIds(seen = new Set, ids = new Set) {
2536
- if (seen.has(this))
2537
- return ids;
2538
- seen.add(this);
2539
- ids.add(this.id);
2540
- for (const anchor of this._connections.values()) {
2541
- anchor._collectAnchorIds(seen, ids);
2542
- }
2543
- return ids;
2544
- }
2545
- _startAutosave(options) {
2546
- const intervalMs = options?.intervalMs;
2547
- if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
2548
- throw new Error("Anchor autosave intervalMs must be a positive number");
2549
- }
2550
- this._autosaveTimer = setInterval(() => {
2551
- this._runAutosave();
2552
- }, intervalMs);
2553
- this._autosaveTimer.unref?.();
2554
- }
2555
- async _runAutosave() {
2556
- if (this._disposed || this._autosaveRunning)
2557
- return;
2558
- this._autosaveRunning = true;
2559
- try {
2560
- await this.saveAllDirty();
2561
- } finally {
2562
- this._autosaveRunning = false;
2563
- }
2564
- }
2565
- }
2566
- MEM.BASE_ANCHOR = new Anchor({ id: "default" });
2567
- var baseAnchor = MEM.BASE_ANCHOR;
2568
- function parseUuidRef(ref) {
2569
- const body = ref.slice("$uuid:".length);
2570
- if (!body) {
2571
- throw new Error(`Malformed ref '${ref}'`);
2572
- }
2573
- const slash = body.indexOf("/");
2574
- if (slash === -1) {
2575
- return { uuid: body, path: "" };
2576
- }
2577
- const uuid = body.slice(0, slash);
2578
- const path = body.slice(slash + 1);
2579
- if (!uuid || !path) {
2580
- throw new Error(`Malformed ref '${ref}'`);
2581
- }
2582
- return {
2583
- uuid,
2584
- path
2585
- };
2586
- }
2587
- function parseLazyUuidRef(value) {
2588
- if (!(value instanceof LazyRef))
2589
- return null;
2590
- if (!value.ref.startsWith("$uuid:"))
2591
- return null;
2592
- return parseUuidRef(value.ref);
2593
- }
2594
- function parseRouteRef(ref) {
2595
- if (typeof ref !== "string") {
2596
- throw new TypeError("Anchor route ref must be a string");
2597
- }
2598
- const colon = ref.indexOf(":");
2599
- if (colon === -1) {
2600
- assertRoute(ref);
2601
- return { anchorId: undefined, route: ref };
2602
- }
2603
- const anchorId = ref.slice(0, colon);
2604
- const route = ref.slice(colon + 1);
2605
- if (!anchorId) {
2606
- throw new Error(`Malformed route ref '${ref}'`);
2607
- }
2608
- assertRoute(route);
2609
- return { anchorId, route };
2610
- }
2611
- function routeDependency(route) {
2612
- return `route:${route}`;
2613
- }
2614
- function joinRoute(parent, segment) {
2615
- assertRouteSegment(segment);
2616
- return `${parent}/${segment}`;
2617
- }
2618
- function getEdges(value) {
2619
- return value[VOCAB.SHAPE.KEYS]().map((key) => value[VOCAB.SHAPE.EDGE](key));
2620
- }
2621
- function getEdge(value, key) {
2622
- try {
2623
- return value[VOCAB.SHAPE.EDGE](key);
2624
- } catch {
2625
- return;
2626
- }
2627
- }
2628
- function isDirectEdgeRoute(parent, route) {
2629
- if (!route.startsWith(`${parent}/`))
2630
- return false;
2631
- return !route.slice(parent.length + 1).includes("/");
2632
- }
2633
- function assertRoute(route) {
2634
- if (typeof route !== "string" || route.length === 0 || route.startsWith("$uuid:")) {
2635
- throw new Error("Anchor route must be a non-empty route string");
2636
- }
2637
- for (const segment of route.split("/")) {
2638
- assertRouteSegment(segment);
2639
- }
2640
- }
2641
- function assertUuid(uuid, message) {
2642
- if (typeof uuid !== "string" || uuid.length === 0) {
2643
- throw new Error(message);
2644
- }
2645
- }
2646
- function assertOrbRecord(record, expectedUuid) {
2647
- const valid = record && typeof record === "object" && !Array.isArray(record) && typeof record.uuid === "string" && record.uuid === expectedUuid && typeof record.shape === "string" && record.shape.length > 0 && Object.prototype.hasOwnProperty.call(record, "state");
2648
- if (!valid) {
2649
- throw new Error(`Malformed Orb record '${expectedUuid}'`);
2650
- }
2651
- }
2652
- function assertAnchor(anchor) {
2653
- if (!anchor || typeof anchor.id !== "string" || typeof anchor.get !== "function") {
2654
- throw new TypeError("Expected an Anchor");
2655
- }
2656
- }
2657
- function assertResolvedAnchor(anchorId, anchor) {
2658
- assertAnchor(anchor);
2659
- if (anchor.id !== anchorId) {
2660
- throw new Error(`Anchor resolver returned '${anchor.id}' for '${anchorId}'`);
2661
- }
2662
- }
2663
- function hasSharedAnchorId(left, right) {
2664
- const leftIds = left._collectAnchorIds();
2665
- const rightIds = right._collectAnchorIds();
2666
- for (const id of rightIds) {
2667
- if (leftIds.has(id))
2668
- return true;
2669
- }
2670
- return false;
2671
- }
2672
- function isPromiseLike(value) {
2673
- return Boolean(value && typeof value.then === "function");
2674
- }
2675
- function normalizeMountTargets(value) {
2676
- if (value === undefined)
2677
- return [];
2678
- const list = Array.isArray(value) ? value : [value];
2679
- const seen = new Set;
2680
- const out = [];
2681
- for (const target of list) {
2682
- if (typeof target !== "string" || target.length === 0) {
2683
- throw new TypeError("Anchor mount targets must be non-empty strings");
2684
- }
2685
- assertRouteSegment(target);
2686
- if (seen.has(target))
2687
- continue;
2688
- seen.add(target);
2689
- out.push(target);
2690
- }
2691
- return out;
2692
- }
2693
- function isSerializedRef(value) {
2694
- return Boolean(value && typeof value === "object" && !Array.isArray(value) && typeof value.$ === "string" && Object.keys(value).length === 1);
2695
- }
2696
- function collectSerializedRefs(value, refs = []) {
2697
- if (isSerializedRef(value)) {
2698
- refs.push(value.$);
2699
- return refs;
2700
- }
2701
- if (Array.isArray(value)) {
2702
- for (const item of value) {
2703
- collectSerializedRefs(item, refs);
2704
- }
2705
- return refs;
2706
- }
2707
- if (value && typeof value === "object") {
2708
- for (const nested of Object.values(value)) {
2709
- collectSerializedRefs(nested, refs);
2710
- }
2711
- }
2712
- return refs;
2713
- }
2714
- function resolveLocalSerializedRef(ref, routeToUuid, anchorId) {
2715
- if (ref.startsWith("$uuid:")) {
2716
- return parseUuidRef(ref).uuid;
2717
- }
2718
- const parsed = parseRouteRef(ref);
2719
- if (parsed.anchorId && parsed.anchorId !== anchorId) {
2720
- return;
2721
- }
2722
- return routeToUuid.get(parsed.route);
2723
- }
2724
- function createMemoryAdapter() {
2725
- const records = new Map;
2726
- const routes = new Map;
2727
- let nextUuid = 1;
2728
- return {
2729
- state: {
2730
- createUuid() {
2731
- return `u${nextUuid++}`;
2732
- },
2733
- async loadOrb(uuid) {
2734
- return records.get(uuid) ?? null;
2735
- },
2736
- async saveOrb(record) {
2737
- records.set(record.uuid, JSON.parse(JSON.stringify(record)));
2738
- },
2739
- async deleteOrb(uuid) {
2740
- records.delete(uuid);
2741
- },
2742
- async listOrbs() {
2743
- return [...records.values()].map((record) => JSON.parse(JSON.stringify(record)));
2744
- }
2745
- },
2746
- routes: {
2747
- async get(route) {
2748
- return routes.get(route) ?? null;
2749
- },
2750
- async set(route, uuid) {
2751
- routes.set(route, uuid);
2752
- },
2753
- async delete(route) {
2754
- routes.delete(route);
2755
- },
2756
- async list() {
2757
- return [...routes].map(([route, uuid]) => ({ route, uuid }));
2758
- }
2759
- },
2760
- shapes: {
2761
- async load() {
2762
- return null;
2763
- },
2764
- async register() {}
2765
- }
2766
- };
2767
- }
2768
- // ../orbz/src/libShapes/Dict.js
2769
- var DICT_KEYS = "dict:keys";
2770
- var dictValueToken = (key) => `dict:value:${key}`;
2771
- var dictPresenceToken = (key) => `dict:presence:${key}`;
2772
- var Dict = Shape({
2773
- [Shape.name]: "Dict",
2774
- _values: {},
2775
- get get() {
2776
- return (key) => this[Shape.edge](key).peek();
2777
- },
2778
- get at() {
2779
- return (key) => this[Shape.edge](key).read();
2780
- },
2781
- set(key, value) {
2782
- return this[Shape.edge](key).write(value);
2783
- },
2784
- delete(key) {
2785
- return this[Shape.edge](key).delete();
2786
- },
2787
- get has() {
2788
- return (key) => {
2789
- const normalized = normalizeKey(key);
2790
- this.$.track(dictPresenceToken(normalized));
2791
- return Object.prototype.hasOwnProperty.call(this._values, normalized);
2792
- };
2793
- },
2794
- get keys() {
2795
- return () => this[Shape.keys]();
2796
- },
2797
- get all() {
2798
- return () => {
2799
- const out = {};
2800
- for (const key of this[Shape.keys]())
2801
- out[key] = this[Shape.edge](key).read();
2802
- return out;
2803
- };
2804
- },
2805
- get each() {
2806
- return (callback) => {
2807
- if (typeof callback !== "function") {
2808
- throw new TypeError("Dict.each() expects a callback");
2809
- }
2810
- for (const key of this[Shape.keys]())
2811
- callback(this[Shape.edge](key).read(), key, this);
2812
- };
2813
- },
2814
- eachEffect(callback, options = {}) {
2815
- return createEachEffect({
2816
- node: this,
2817
- callback,
2818
- options,
2819
- keys: () => this[Shape.keys](),
2820
- peek: (key) => this[Shape.edge](key).peek(),
2821
- read: (key) => this[Shape.edge](key).read()
2822
- });
2823
- },
2824
- [Shape.init](initial = {}) {
2825
- if (!initial || typeof initial !== "object" || Array.isArray(initial)) {
2826
- throw new TypeError("Dict() expects an object");
2827
- }
2828
- const values = {};
2829
- for (const [key, value] of Object.entries(initial))
2830
- values[normalizeKey(key)] = value;
2831
- return { _values: values };
2832
- },
2833
- [Shape.load](initial = {}) {
2834
- return this[Shape.init](initial);
2835
- },
2836
- [Shape.save]() {
2837
- const out = {};
2838
- for (const key of Object.keys(this._values))
2839
- out[key] = serializeSlot(this._values[key]);
2840
- return out;
2841
- },
2842
- [Shape.keys]() {
2843
- this.$.track(DICT_KEYS);
2844
- return Object.keys(this._values);
2845
- },
2846
- [Shape.edge](key) {
2847
- const normalized = normalizeKey(key);
2848
- const node = this;
2849
- const values = this._values;
2850
- return {
2851
- key: normalized,
2852
- segment: normalized,
2853
- read() {
2854
- node.$.track(dictValueToken(normalized));
2855
- return readSlot(values[normalized]);
2856
- },
2857
- peek() {
2858
- return values[normalized];
2859
- },
2860
- write(value) {
2861
- setDictValue(node, values, normalized, value);
2862
- return value;
2863
- },
2864
- delete() {
2865
- return deleteDictValue(node, values, normalized);
2866
- },
2867
- save() {
2868
- return serializeSlot(values[normalized]);
2869
- }
2870
- };
2871
- }
2872
- });
2873
- function setDictValue(node, values, key, value) {
2874
- const hadKey = Object.prototype.hasOwnProperty.call(values, key);
2875
- const previous = values[key];
2876
- if (Object.is(previous, value) && hadKey)
2877
- return;
2878
- batch(() => {
2879
- values[key] = value;
2880
- node.$.changed(dictValueToken(key));
2881
- if (!hadKey) {
2882
- node.$.changed(DICT_KEYS);
2883
- node.$.changed(dictPresenceToken(key));
2884
- }
2885
- });
2886
- }
2887
- function deleteDictValue(node, values, key) {
2888
- if (!Object.prototype.hasOwnProperty.call(values, key))
2889
- return false;
2890
- batch(() => {
2891
- delete values[key];
2892
- node.$.changed(DICT_KEYS);
2893
- node.$.changed(dictPresenceToken(key));
2894
- node.$.changed(dictValueToken(key));
2895
- });
2896
- return true;
2897
- }
2898
- function normalizeKey(key) {
2899
- if (typeof key !== "string") {
2900
- throw new TypeError("Dict keys must be strings");
2901
- }
2902
- assertRouteSegment(key);
2903
- return key;
2904
- }
2905
- // ../orbz/src/libShapes/List.js
2906
- var LIST_ITEMS = "list:items";
2907
- var LIST_LENGTH = "list:length";
2908
- var listItemToken = (index) => `list:item:${index}`;
2909
- var List = Shape({
2910
- [Shape.name]: "List",
2911
- _values: [],
2912
- get length() {
2913
- this.$.track(LIST_LENGTH);
2914
- return this._values.length;
2915
- },
2916
- get keys() {
2917
- return () => this[Shape.keys]();
2918
- },
2919
- get get() {
2920
- return (index) => this[Shape.edge](index).peek();
2921
- },
2922
- get at() {
2923
- return (index) => this[Shape.edge](index).read();
2924
- },
2925
- set(index, value) {
2926
- return this[Shape.edge](index).write(value);
2927
- },
2928
- push(value) {
2929
- return pushListValue(this, this._values, value);
2930
- },
2931
- removeAt(index) {
2932
- return this[Shape.edge](index).delete();
2933
- },
2934
- get toArray() {
2935
- return () => {
2936
- this.$.track(LIST_ITEMS);
2937
- return [...this._values];
2938
- };
2939
- },
2940
- get all() {
2941
- return () => this.toArray();
2942
- },
2943
- get each() {
2944
- return (callback) => {
2945
- if (typeof callback !== "function") {
2946
- throw new TypeError("List.each() expects a callback");
2947
- }
2948
- for (const index of this[Shape.keys]())
2949
- callback(this[Shape.edge](index).read(), index, this);
2950
- };
2951
- },
2952
- eachEffect(callback, options = {}) {
2953
- return createEachEffect({
2954
- node: this,
2955
- callback,
2956
- options,
2957
- keys: () => this[Shape.keys](),
2958
- peek: (index) => this[Shape.edge](index).peek(),
2959
- read: (index) => this[Shape.edge](index).read()
2960
- });
2961
- },
2962
- get map() {
2963
- return (callback) => new DerivedListView(this, callback);
2964
- },
2965
- [Shape.init](initial = []) {
2966
- if (!Array.isArray(initial)) {
2967
- throw new TypeError("List() expects an array");
2968
- }
2969
- return { _values: [...initial] };
2970
- },
2971
- [Shape.load](initial = []) {
2972
- return this[Shape.init](initial);
2973
- },
2974
- [Shape.save]() {
2975
- return this._values.map(serializeSlot);
2976
- },
2977
- [Shape.keys]() {
2978
- this.$.track(LIST_LENGTH);
2979
- return this._values.map((_, index) => index);
2980
- },
2981
- [Shape.edge](index) {
2982
- const normalized = normalizeIndex(index);
2983
- const node = this;
2984
- const values = this._values;
2985
- return {
2986
- key: normalized,
2987
- segment: String(normalized),
2988
- read() {
2989
- node.$.track(listItemToken(normalized));
2990
- return readSlot(values[normalized]);
2991
- },
2992
- peek() {
2993
- return values[normalized];
2994
- },
2995
- write(value) {
2996
- setListValue(node, values, normalized, value);
2997
- return value;
2998
- },
2999
- delete() {
3000
- return removeListValue(node, values, normalized);
3001
- },
3002
- save() {
3003
- return serializeSlot(values[normalized]);
3004
- }
3005
- };
3006
- }
3007
- });
3008
-
3009
- class DerivedListView {
3010
- constructor(source, mapper) {
3011
- if (typeof mapper !== "function") {
3012
- throw new TypeError("List.map() expects a callback");
3013
- }
3014
- this._source = source;
3015
- this._mapper = mapper;
3016
- }
3017
- get length() {
3018
- return this._source.length;
3019
- }
3020
- keys() {
3021
- return this._source.keys();
3022
- }
3023
- get(index) {
3024
- const normalized = normalizeIndex(index);
3025
- return this._mapper(this._source.get(normalized), normalized, this._source);
3026
- }
3027
- at(index) {
3028
- const normalized = normalizeIndex(index);
3029
- return this._mapper(this._source.at(normalized), normalized, this._source);
3030
- }
3031
- toArray() {
3032
- return this.keys().map((index) => this.at(index));
3033
- }
3034
- all() {
3035
- return this.toArray();
3036
- }
3037
- each(callback) {
3038
- if (typeof callback !== "function") {
3039
- throw new TypeError("List.each() expects a callback");
3040
- }
3041
- for (const index of this.keys())
3042
- callback(this.at(index), index, this);
3043
- }
3044
- eachEffect(callback, options = {}) {
3045
- return createEachEffect({
3046
- node: this,
3047
- callback,
3048
- options,
3049
- keys: () => this.keys(),
3050
- peek: (index) => this.get(index),
3051
- read: (index) => this.at(index)
3052
- });
3053
- }
3054
- map(callback) {
3055
- return new DerivedListView(this, callback);
3056
- }
3057
- toJSON() {
3058
- return this.toArray();
3059
- }
3060
- }
3061
- function setListValue(node, values, index, value) {
3062
- const previousLength = values.length;
3063
- const previous = values[index];
3064
- if (Object.is(previous, value) && index in values)
3065
- return;
3066
- batch(() => {
3067
- values[index] = value;
3068
- if (values.length !== previousLength)
3069
- node.$.changed(LIST_LENGTH);
3070
- node.$.changed(listItemToken(index));
3071
- node.$.changed(LIST_ITEMS);
3072
- });
3073
- }
3074
- function pushListValue(node, values, value) {
3075
- batch(() => {
3076
- const index = values.length;
3077
- values.push(value);
3078
- node.$.changed(LIST_LENGTH);
3079
- node.$.changed(listItemToken(index));
3080
- node.$.changed(LIST_ITEMS);
3081
- });
3082
- return values.length;
3083
- }
3084
- function removeListValue(node, values, index) {
3085
- if (index < 0 || index >= values.length)
3086
- return;
3087
- let removed;
3088
- batch(() => {
3089
- removed = values.splice(index, 1)[0];
3090
- node.$.changed(LIST_LENGTH);
3091
- for (let i = index;i <= values.length; i += 1)
3092
- node.$.changed(listItemToken(i));
3093
- node.$.changed(LIST_ITEMS);
3094
- });
3095
- return removed;
3096
- }
3097
- function normalizeIndex(index) {
3098
- if (!Number.isInteger(index) || index < 0) {
3099
- throw new TypeError("List indexes must be non-negative integers");
3100
- }
3101
- return index;
3102
- }
3103
2
  // src/adapters/bun.js
3
+ import { batch as batch2 } from "orbz";
3104
4
  import { existsSync, readFileSync } from "fs";
3105
5
  import { mkdir, rename, writeFile } from "fs/promises";
3106
6
  import { dirname } from "path";
3107
7
  import { fileURLToPath } from "url";
3108
8
 
3109
9
  // src/core.js
10
+ import { Anchor, batch, describe } from "orbz";
3110
11
  function createProtocolCodec() {
3111
12
  return {
3112
13
  encode(message) {
@@ -3145,7 +46,7 @@ function normalizeRoutes(routes = {}, shapes = {}) {
3145
46
  shapeHash,
3146
47
  localShapeHash,
3147
48
  owner: config.owner,
3148
- initial: cloneJson2(config.initial ?? config.state ?? {}),
49
+ initial: cloneJson(config.initial ?? config.state ?? {}),
3149
50
  publicStateKeys: shape.state.filter((entry) => entry.visibility === "public").map((entry) => entry.key),
3150
51
  getterKeys: [...shape.getters],
3151
52
  methodKeys: [...shape.methods]
@@ -3173,7 +74,7 @@ function createAnchorFromRoutes({
3173
74
  });
3174
75
  const routeInfo = normalizeRoutes(routes, shapes);
3175
76
  for (const info of routeInfo.values()) {
3176
- anchor.set(info.route, info.factory(cloneJson2(info.initial)));
77
+ anchor.set(info.route, info.factory(cloneJson(info.initial)));
3177
78
  }
3178
79
  return { anchor, routeInfo };
3179
80
  }
@@ -3199,7 +100,7 @@ async function createHydratedAnchorFromRoutes({
3199
100
  for (const info of routeInfo.values()) {
3200
101
  const loaded = await anchor.load(info.route);
3201
102
  if (!loaded) {
3202
- anchor.set(info.route, info.factory(cloneJson2(info.initial)));
103
+ anchor.set(info.route, info.factory(cloneJson(info.initial)));
3203
104
  }
3204
105
  }
3205
106
  return { anchor, routeInfo };
@@ -3265,7 +166,7 @@ function createProjectionMessage(anchor, info, options = {}) {
3265
166
  };
3266
167
  }
3267
168
  function readPublicState(orb, keys) {
3268
- return Object.fromEntries(keys.map((key) => [key, cloneJson2(orb[key])]));
169
+ return Object.fromEntries(keys.map((key) => [key, cloneJson(orb[key])]));
3269
170
  }
3270
171
  function matchesRouteShape(message, info) {
3271
172
  const hash = message.shapeHash ?? message.shape;
@@ -3278,7 +179,7 @@ function createProjectionPayload(anchor, info, options = {}) {
3278
179
  const errors = {};
3279
180
  for (const key of info.getterKeys) {
3280
181
  try {
3281
- values[key] = cloneJson2(orb[key]);
182
+ values[key] = cloneJson(orb[key]);
3282
183
  statuses[key] = "ready";
3283
184
  } catch (error) {
3284
185
  statuses[key] = "error";
@@ -3301,7 +202,7 @@ function normalizeRouteConfig(config) {
3301
202
  }
3302
203
  return config;
3303
204
  }
3304
- function cloneJson2(value) {
205
+ function cloneJson(value) {
3305
206
  if (value === undefined)
3306
207
  return;
3307
208
  return JSON.parse(JSON.stringify(value));
@@ -3346,10 +247,10 @@ function createJsonFileAdapter(file, {
3346
247
  return uuid;
3347
248
  },
3348
249
  async loadOrb(uuid) {
3349
- return cloneJson3(document.orbs[uuid] ?? null);
250
+ return cloneJson2(document.orbs[uuid] ?? null);
3350
251
  },
3351
252
  async saveOrb(record) {
3352
- document.orbs[record.uuid] = cloneJson3(record);
253
+ document.orbs[record.uuid] = cloneJson2(record);
3353
254
  return persist();
3354
255
  },
3355
256
  async deleteOrb(uuid) {
@@ -3357,7 +258,7 @@ function createJsonFileAdapter(file, {
3357
258
  return persist();
3358
259
  },
3359
260
  async listOrbs() {
3360
- return Object.keys(document.orbs).sort().map((uuid) => cloneJson3(document.orbs[uuid]));
261
+ return Object.keys(document.orbs).sort().map((uuid) => cloneJson2(document.orbs[uuid]));
3361
262
  }
3362
263
  },
3363
264
  routes: {
@@ -3388,7 +289,7 @@ function createJsonFileAdapter(file, {
3388
289
  await writeQueue;
3389
290
  },
3390
291
  snapshot() {
3391
- return cloneJson3(toSerializableDocument(document));
292
+ return cloneJson2(toSerializableDocument(document));
3392
293
  }
3393
294
  };
3394
295
  function persist() {
@@ -3408,7 +309,7 @@ function createHubRuntime({
3408
309
  routeInfo
3409
310
  }, {
3410
311
  anchorId = "bun",
3411
- socketUrl = "/zhub-sync",
312
+ socketUrl = "/zocket-sync",
3412
313
  onLog,
3413
314
  onError
3414
315
  } = {}) {
@@ -3532,7 +433,7 @@ function createHubRuntime({
3532
433
  const orb = anchor.at(message.route);
3533
434
  try {
3534
435
  state.applyingRemote = true;
3535
- batch(() => {
436
+ batch2(() => {
3536
437
  orb[message.key] = message.value;
3537
438
  });
3538
439
  } finally {
@@ -3662,7 +563,7 @@ function createEmptyJsonDocument() {
3662
563
  }
3663
564
  function normalizeJsonDocument(document) {
3664
565
  if (!document || typeof document !== "object" || Array.isArray(document)) {
3665
- throw new TypeError("zhub JSON persistence file must contain an object");
566
+ throw new TypeError("zocket JSON persistence file must contain an object");
3666
567
  }
3667
568
  return {
3668
569
  version: document.version ?? 1,
@@ -3675,7 +576,7 @@ function normalizeStringRecord(record) {
3675
576
  if (!record)
3676
577
  return {};
3677
578
  if (typeof record !== "object" || Array.isArray(record)) {
3678
- throw new TypeError("zhub JSON persistence routes must be an object");
579
+ throw new TypeError("zocket JSON persistence routes must be an object");
3679
580
  }
3680
581
  return Object.fromEntries(Object.entries(record).filter(([, value]) => typeof value === "string").sort(([left], [right]) => left.localeCompare(right)));
3681
582
  }
@@ -3683,13 +584,13 @@ function normalizeOrbRecords(record) {
3683
584
  if (!record)
3684
585
  return {};
3685
586
  if (typeof record !== "object" || Array.isArray(record)) {
3686
- throw new TypeError("zhub JSON persistence orbs must be an object");
587
+ throw new TypeError("zocket JSON persistence orbs must be an object");
3687
588
  }
3688
589
  const out = {};
3689
590
  for (const [uuid, orb] of Object.entries(record).sort(([left], [right]) => left.localeCompare(right))) {
3690
591
  if (!orb || typeof orb !== "object" || Array.isArray(orb))
3691
592
  continue;
3692
- out[uuid] = cloneJson3({
593
+ out[uuid] = cloneJson2({
3693
594
  ...orb,
3694
595
  uuid: orb.uuid ?? uuid
3695
596
  });
@@ -3726,7 +627,7 @@ async function writeJsonFile(path, source) {
3726
627
  await writeFile(temporaryPath, source);
3727
628
  await rename(temporaryPath, path);
3728
629
  }
3729
- function cloneJson3(value) {
630
+ function cloneJson2(value) {
3730
631
  if (value === undefined)
3731
632
  return;
3732
633
  return JSON.parse(JSON.stringify(value));