holosphere 1.3.0-alpha0 → 1.3.0-alpha3
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/content.js +79 -62
- package/federation.js +201 -305
- package/global.js +58 -47
- package/hologram.js +38 -14
- package/holosphere-bundle.esm.js +410 -432
- package/holosphere-bundle.js +410 -432
- package/holosphere-bundle.min.js +8 -8
- package/holosphere.d.ts +50 -8
- package/holosphere.js +24 -19
- package/package.json +1 -1
package/content.js
CHANGED
|
@@ -142,11 +142,15 @@ export async function put(holoInstance, holon, lens, data, password = null, opti
|
|
|
142
142
|
|
|
143
143
|
return new Promise((resolve, reject) => {
|
|
144
144
|
try {
|
|
145
|
-
// Create a copy of data
|
|
145
|
+
// Create a copy of data, stripping read-side envelopes that
|
|
146
|
+
// must never be persisted (they're attached at resolution time).
|
|
146
147
|
let dataToStore = { ...data };
|
|
147
148
|
if (dataToStore._meta !== undefined) {
|
|
148
149
|
delete dataToStore._meta;
|
|
149
150
|
}
|
|
151
|
+
if (dataToStore._hologram !== undefined) {
|
|
152
|
+
delete dataToStore._hologram;
|
|
153
|
+
}
|
|
150
154
|
const payload = JSON.stringify(dataToStore); // The data being stored
|
|
151
155
|
|
|
152
156
|
const putCallback = async (ack) => {
|
|
@@ -514,8 +518,12 @@ export async function getAll(holoInstance, holon, lens, password = null) {
|
|
|
514
518
|
user.get('private').get(lens) :
|
|
515
519
|
holoInstance.gun.get(holoInstance.appname).get(holon).get(lens);
|
|
516
520
|
|
|
517
|
-
// PASS 1: Get shallow node to determine expected item count
|
|
518
|
-
|
|
521
|
+
// PASS 1: Get shallow node to determine expected item count.
|
|
522
|
+
// Retry once if empty — Gun's .once() reads from local cache, which
|
|
523
|
+
// may be cold immediately after startup before peers have synced.
|
|
524
|
+
const shallowOnce = () => new Promise((res) => dataPath.once((d) => res(d)));
|
|
525
|
+
|
|
526
|
+
const processShallow = (data) => {
|
|
519
527
|
if (!data) {
|
|
520
528
|
resolve([]);
|
|
521
529
|
return;
|
|
@@ -537,81 +545,90 @@ export async function getAll(holoInstance, holon, lens, password = null) {
|
|
|
537
545
|
return;
|
|
538
546
|
}
|
|
539
547
|
|
|
540
|
-
// PASS 2:
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
548
|
+
// PASS 2: iterate explicitly over the filtered keys.
|
|
549
|
+
// Using dataPath.map().once() here is unsafe when the parent
|
|
550
|
+
// node has tombstoned siblings (null values): map() fires for
|
|
551
|
+
// every child, and a null sibling's callback can satisfy
|
|
552
|
+
// receivedCount before real items are processed, resolving [].
|
|
553
|
+
const processItem = async (itemData, key) => {
|
|
554
|
+
if (!itemData) return;
|
|
555
|
+
try {
|
|
556
|
+
const parsed = await holoInstance.parse(itemData);
|
|
557
|
+
if (!parsed || !parsed.id) return;
|
|
552
558
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const resolved = await holoInstance.resolveHologram(parsed, {
|
|
561
|
-
followHolograms: true,
|
|
562
|
-
maxDepth: 10,
|
|
563
|
-
currentDepth: 0
|
|
564
|
-
});
|
|
559
|
+
if (holoInstance.isHologram(parsed)) {
|
|
560
|
+
try {
|
|
561
|
+
const resolved = await holoInstance.resolveHologram(parsed, {
|
|
562
|
+
followHolograms: true,
|
|
563
|
+
maxDepth: 10,
|
|
564
|
+
currentDepth: 0
|
|
565
|
+
});
|
|
565
566
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
}
|
|
573
|
-
return;
|
|
567
|
+
if (resolved === null) {
|
|
568
|
+
console.warn(`Broken hologram detected in getAll for key ${key}. Removing it...`);
|
|
569
|
+
try {
|
|
570
|
+
await holoInstance.delete(holon, lens, key, password);
|
|
571
|
+
} catch (cleanupError) {
|
|
572
|
+
console.error(`Failed to remove broken hologram at ${holon}/${lens}/${key}:`, cleanupError);
|
|
574
573
|
}
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
575
576
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
output.set(resolved.id, resolved);
|
|
581
|
-
}
|
|
582
|
-
} else {
|
|
577
|
+
if (resolved && resolved !== parsed) {
|
|
578
|
+
if (schema) {
|
|
579
|
+
const valid = holoInstance.validator.validate(schema, resolved);
|
|
580
|
+
if (valid || !holoInstance.strict) {
|
|
583
581
|
output.set(resolved.id, resolved);
|
|
584
582
|
}
|
|
585
|
-
|
|
583
|
+
} else {
|
|
584
|
+
output.set(resolved.id, resolved);
|
|
586
585
|
}
|
|
587
|
-
} catch (hologramError) {
|
|
588
|
-
console.error(`Error resolving hologram for key ${key}:`, hologramError);
|
|
589
586
|
return;
|
|
590
587
|
}
|
|
588
|
+
} catch (hologramError) {
|
|
589
|
+
console.error(`Error resolving hologram for key ${key}:`, hologramError);
|
|
590
|
+
return;
|
|
591
591
|
}
|
|
592
|
+
}
|
|
592
593
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
output.set(parsed.id, parsed);
|
|
597
|
-
}
|
|
598
|
-
} else {
|
|
594
|
+
if (schema) {
|
|
595
|
+
const valid = holoInstance.validator.validate(schema, parsed);
|
|
596
|
+
if (valid || !holoInstance.strict) {
|
|
599
597
|
output.set(parsed.id, parsed);
|
|
600
598
|
}
|
|
601
|
-
}
|
|
602
|
-
|
|
599
|
+
} else {
|
|
600
|
+
output.set(parsed.id, parsed);
|
|
603
601
|
}
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
602
|
+
} catch (error) {
|
|
603
|
+
console.error('Error processing data:', error);
|
|
604
|
+
}
|
|
605
|
+
};
|
|
608
606
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
607
|
+
Promise.all(keys.map((key) => {
|
|
608
|
+
const inline = data[key];
|
|
609
|
+
// If shallow already inlined the leaf (holosphere stores
|
|
610
|
+
// payloads as JSON strings), process it directly. This
|
|
611
|
+
// avoids a redundant round-trip and the map() race.
|
|
612
|
+
if (typeof inline !== 'object' || inline === null) {
|
|
613
|
+
return processItem(inline, key);
|
|
612
614
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
+
// Otherwise fetch the leaf — sub-graph reference path.
|
|
616
|
+
return new Promise((resolveItem) => {
|
|
617
|
+
dataPath.get(key).once((itemData) => {
|
|
618
|
+
processItem(itemData, key).then(resolveItem, resolveItem);
|
|
619
|
+
});
|
|
620
|
+
});
|
|
621
|
+
})).then(() => resolve(Array.from(output.values())));
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
(async () => {
|
|
625
|
+
let data = await shallowOnce();
|
|
626
|
+
if (!data) {
|
|
627
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
628
|
+
data = await shallowOnce();
|
|
629
|
+
}
|
|
630
|
+
processShallow(data);
|
|
631
|
+
})();
|
|
615
632
|
});
|
|
616
633
|
} catch (error) {
|
|
617
634
|
console.error('Error in getAll:', error);
|