holosphere 1.1.11 → 1.1.13
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 +175 -26
- package/federation.js +252 -117
- package/global.js +174 -9
- package/holosphere-bundle.esm.js +33184 -0
- package/holosphere-bundle.js +33206 -0
- package/holosphere-bundle.min.js +38 -0
- package/holosphere.d.ts +15 -0
- package/holosphere.js +2 -2
- package/node.js +92 -7
- package/package.json +78 -3
- package/.cursor/rules/futura.mdc +0 -55
- package/examples/federation.js +0 -162
- package/examples/holograms.js +0 -175
- package/test/auth.test.js +0 -275
- package/test/delete.test.js +0 -229
- package/test/federation.test.js +0 -349
- package/test/hologram.test.js +0 -316
- package/test/holosphere.test.js +0 -354
- package/test/subscription.test.js +0 -364
package/content.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* @param {object} [options.propagationOptions] - Options to pass to propagate
|
|
18
18
|
* @param {boolean} [options.propagationOptions.useHolograms=true] - Whether to use holograms instead of duplicating data
|
|
19
19
|
* @param {boolean} [options.disableHologramRedirection=false] - Whether to disable hologram redirection
|
|
20
|
-
* @returns {Promise<
|
|
20
|
+
* @returns {Promise<object>} - Returns an object with success status, path info, propagation result, and list of updated holograms
|
|
21
21
|
*/
|
|
22
22
|
export async function put(holoInstance, holon, lens, data, password = null, options = {}) {
|
|
23
23
|
if (!data) { // Check data first as it's used for id generation
|
|
@@ -142,11 +142,12 @@ export async function put(holoInstance, holon, lens, data, password = null, opti
|
|
|
142
142
|
|
|
143
143
|
return new Promise((resolve, reject) => {
|
|
144
144
|
try {
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
// Create a copy of data without the _meta field if it exists
|
|
146
|
+
let dataToStore = { ...data };
|
|
147
|
+
if (dataToStore._meta !== undefined) {
|
|
148
|
+
delete dataToStore._meta;
|
|
149
|
+
}
|
|
150
|
+
const payload = JSON.stringify(dataToStore); // The data being stored
|
|
150
151
|
|
|
151
152
|
const putCallback = async (ack) => {
|
|
152
153
|
if (ack.err) {
|
|
@@ -173,6 +174,87 @@ export async function put(holoInstance, holon, lens, data, password = null, opti
|
|
|
173
174
|
}
|
|
174
175
|
// --- End: Hologram Tracking Logic ---
|
|
175
176
|
|
|
177
|
+
// --- Start: Active Hologram Update Logic (for actual data being stored) ---
|
|
178
|
+
let updatedHolograms = [];
|
|
179
|
+
if (!isHologram && !options.isHologramUpdate) {
|
|
180
|
+
try {
|
|
181
|
+
const currentDataSoul = `${holoInstance.appname}/${targetHolon}/${targetLens}/${targetKey}`;
|
|
182
|
+
const currentNodeRef = holoInstance.getNodeRef(currentDataSoul);
|
|
183
|
+
|
|
184
|
+
// Get the _holograms set for this data
|
|
185
|
+
await new Promise((resolveHologramUpdate) => {
|
|
186
|
+
currentNodeRef.get('_holograms').once(async (hologramsSet) => {
|
|
187
|
+
if (hologramsSet) {
|
|
188
|
+
const hologramSouls = Object.keys(hologramsSet).filter(k =>
|
|
189
|
+
k !== '_' && hologramsSet[k] === true // Only active holograms (deleted ones are null/removed)
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
if (hologramSouls.length > 0) {
|
|
193
|
+
console.log(`Updating ${hologramSouls.length} active holograms for data ${data.id}`);
|
|
194
|
+
|
|
195
|
+
// Update each active hologram with an 'updated' timestamp
|
|
196
|
+
const updatePromises = hologramSouls.map(async (hologramSoul) => {
|
|
197
|
+
try {
|
|
198
|
+
const hologramSoulInfo = holoInstance.parseSoulPath(hologramSoul);
|
|
199
|
+
if (hologramSoulInfo) {
|
|
200
|
+
// Get the current hologram data
|
|
201
|
+
const currentHologram = await holoInstance.get(
|
|
202
|
+
hologramSoulInfo.holon,
|
|
203
|
+
hologramSoulInfo.lens,
|
|
204
|
+
hologramSoulInfo.key,
|
|
205
|
+
null,
|
|
206
|
+
{ resolveHolograms: false }
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
if (currentHologram) {
|
|
210
|
+
// Update the hologram with an 'updated' timestamp
|
|
211
|
+
const updatedHologram = {
|
|
212
|
+
...currentHologram,
|
|
213
|
+
updated: Date.now()
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
await holoInstance.put(
|
|
217
|
+
hologramSoulInfo.holon,
|
|
218
|
+
hologramSoulInfo.lens,
|
|
219
|
+
updatedHologram,
|
|
220
|
+
null,
|
|
221
|
+
{
|
|
222
|
+
autoPropagate: false, // Don't auto-propagate hologram updates
|
|
223
|
+
disableHologramRedirection: true, // Prevent redirection when updating holograms
|
|
224
|
+
isHologramUpdate: true // Prevent recursive hologram updates
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
console.log(`Updated hologram at ${hologramSoul} with timestamp`);
|
|
229
|
+
|
|
230
|
+
// Add to the list of updated holograms
|
|
231
|
+
updatedHolograms.push({
|
|
232
|
+
soul: hologramSoul,
|
|
233
|
+
holon: hologramSoulInfo.holon,
|
|
234
|
+
lens: hologramSoulInfo.lens,
|
|
235
|
+
key: hologramSoulInfo.key,
|
|
236
|
+
id: hologramSoulInfo.key,
|
|
237
|
+
timestamp: updatedHologram.updated
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
} catch (hologramUpdateError) {
|
|
242
|
+
console.warn(`Error updating hologram ${hologramSoul}:`, hologramUpdateError);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
await Promise.all(updatePromises);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
resolveHologramUpdate(); // Resolve the promise to continue with the main put logic
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
} catch (hologramUpdateError) {
|
|
253
|
+
console.warn(`Error checking for active holograms to update:`, hologramUpdateError);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// --- End: Active Hologram Update Logic ---
|
|
257
|
+
|
|
176
258
|
// Only notify subscribers for actual data, not holograms
|
|
177
259
|
if (!isHologram) {
|
|
178
260
|
holoInstance.notifySubscribers({
|
|
@@ -214,7 +296,8 @@ export async function put(holoInstance, holon, lens, data, password = null, opti
|
|
|
214
296
|
pathHolon: targetHolon,
|
|
215
297
|
pathLens: targetLens,
|
|
216
298
|
pathKey: targetKey,
|
|
217
|
-
propagationResult
|
|
299
|
+
propagationResult,
|
|
300
|
+
updatedHolograms: updatedHolograms // List of holograms that were updated
|
|
218
301
|
});
|
|
219
302
|
}
|
|
220
303
|
};
|
|
@@ -646,14 +729,13 @@ export async function deleteFunc(holoInstance, holon, lens, key, password = null
|
|
|
646
729
|
const targetNodeRef = holoInstance.getNodeRef(targetSoul);
|
|
647
730
|
const deletedHologramSoul = `${holoInstance.appname}/${holon}/${lens}/${key}`;
|
|
648
731
|
|
|
649
|
-
// Create a promise that resolves when the
|
|
732
|
+
// Create a promise that resolves when the hologram is removed from the list
|
|
650
733
|
trackingRemovalPromise = new Promise((resolveTrack) => { // No reject needed, just warn on error
|
|
651
|
-
targetNodeRef.get('_holograms').get(deletedHologramSoul).put(
|
|
734
|
+
targetNodeRef.get('_holograms').get(deletedHologramSoul).put(null, (ack) => { // Remove the hologram entry completely
|
|
652
735
|
if (ack.err) {
|
|
653
|
-
|
|
654
|
-
console.warn(`[deleteFunc] Error ack for marking hologram ${deletedHologramSoul} as DELETED in target ${targetSoul}:`, ack.err);
|
|
736
|
+
console.warn(`[deleteFunc] Error removing hologram ${deletedHologramSoul} from target ${targetSoul}:`, ack.err);
|
|
655
737
|
}
|
|
656
|
-
|
|
738
|
+
console.log(`Removed hologram ${deletedHologramSoul} from target ${targetSoul}'s _holograms list`);
|
|
657
739
|
resolveTrack(); // Resolve regardless of ack error to not block main delete
|
|
658
740
|
});
|
|
659
741
|
});
|
|
@@ -754,7 +836,7 @@ export async function deleteAll(holoInstance, holon, lens, password = null) {
|
|
|
754
836
|
holoInstance.gun.get(holoInstance.appname).get(holon).get(lens);
|
|
755
837
|
|
|
756
838
|
// First get all the data to find keys to delete
|
|
757
|
-
dataPath.once((data) => {
|
|
839
|
+
dataPath.once(async (data) => {
|
|
758
840
|
if (!data) {
|
|
759
841
|
resolve(true); // Nothing to delete
|
|
760
842
|
return;
|
|
@@ -763,20 +845,87 @@ export async function deleteAll(holoInstance, holon, lens, password = null) {
|
|
|
763
845
|
// Get all keys except Gun's metadata key '_'
|
|
764
846
|
const keys = Object.keys(data).filter(key => key !== '_');
|
|
765
847
|
|
|
766
|
-
//
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
848
|
+
// Process each key to handle holograms properly
|
|
849
|
+
for (const key of keys) {
|
|
850
|
+
try {
|
|
851
|
+
// Get the data to check if it's a hologram
|
|
852
|
+
const itemPath = password ?
|
|
853
|
+
user.get('private').get(lens).get(key) :
|
|
854
|
+
holoInstance.gun.get(holoInstance.appname).get(holon).get(lens).get(key);
|
|
773
855
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
856
|
+
const rawDataToDelete = await new Promise((resolveItem) => itemPath.once(resolveItem));
|
|
857
|
+
let dataToDelete = null;
|
|
858
|
+
|
|
859
|
+
try {
|
|
860
|
+
if (typeof rawDataToDelete === 'string') {
|
|
861
|
+
dataToDelete = JSON.parse(rawDataToDelete);
|
|
862
|
+
} else {
|
|
863
|
+
dataToDelete = rawDataToDelete;
|
|
864
|
+
}
|
|
865
|
+
} catch(e) {
|
|
866
|
+
console.warn("[deleteAll] Could not JSON parse data for deletion check:", rawDataToDelete, e);
|
|
867
|
+
dataToDelete = null;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// Check if it's a hologram and handle accordingly
|
|
871
|
+
const isDataHologram = dataToDelete && holoInstance.isHologram(dataToDelete);
|
|
872
|
+
|
|
873
|
+
if (isDataHologram) {
|
|
874
|
+
// Handle hologram deletion - remove from target's _holograms list
|
|
875
|
+
try {
|
|
876
|
+
const targetSoul = dataToDelete.soul;
|
|
877
|
+
const targetSoulInfo = holoInstance.parseSoulPath(targetSoul);
|
|
878
|
+
|
|
879
|
+
if (targetSoulInfo) {
|
|
880
|
+
const targetNodeRef = holoInstance.getNodeRef(targetSoul);
|
|
881
|
+
const deletedHologramSoul = `${holoInstance.appname}/${holon}/${lens}/${key}`;
|
|
882
|
+
|
|
883
|
+
// Remove the hologram from target's _holograms list
|
|
884
|
+
await new Promise((resolveTrack) => {
|
|
885
|
+
targetNodeRef.get('_holograms').get(deletedHologramSoul).put(null, (ack) => {
|
|
886
|
+
if (ack.err) {
|
|
887
|
+
console.warn(`[deleteAll] Error removing hologram ${deletedHologramSoul} from target ${targetSoul}:`, ack.err);
|
|
888
|
+
}
|
|
889
|
+
console.log(`Removed hologram ${deletedHologramSoul} from target ${targetSoul}'s _holograms list`);
|
|
890
|
+
resolveTrack();
|
|
891
|
+
});
|
|
892
|
+
});
|
|
893
|
+
} else {
|
|
894
|
+
console.warn(`Could not parse target soul ${targetSoul} for hologram tracking removal during deleteAll.`);
|
|
895
|
+
}
|
|
896
|
+
} catch (trackingError) {
|
|
897
|
+
console.warn(`Error removing hologram reference from target ${dataToDelete.soul} during deleteAll:`, trackingError);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// Create deletion promise for this key (whether it's a hologram or not)
|
|
902
|
+
deletionPromises.push(
|
|
903
|
+
new Promise((resolveDelete) => {
|
|
904
|
+
const deletePath = password ?
|
|
905
|
+
user.get('private').get(lens).get(key) :
|
|
906
|
+
holoInstance.gun.get(holoInstance.appname).get(holon).get(lens).get(key);
|
|
907
|
+
|
|
908
|
+
deletePath.put(null, ack => {
|
|
909
|
+
resolveDelete(!!ack.ok); // Convert to boolean
|
|
910
|
+
});
|
|
911
|
+
})
|
|
912
|
+
);
|
|
913
|
+
} catch (error) {
|
|
914
|
+
console.warn(`Error processing key ${key} during deleteAll:`, error);
|
|
915
|
+
// Still try to delete the item even if hologram processing failed
|
|
916
|
+
deletionPromises.push(
|
|
917
|
+
new Promise((resolveDelete) => {
|
|
918
|
+
const deletePath = password ?
|
|
919
|
+
user.get('private').get(lens).get(key) :
|
|
920
|
+
holoInstance.gun.get(holoInstance.appname).get(holon).get(lens).get(key);
|
|
921
|
+
|
|
922
|
+
deletePath.put(null, ack => {
|
|
923
|
+
resolveDelete(!!ack.ok);
|
|
924
|
+
});
|
|
925
|
+
})
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
780
929
|
|
|
781
930
|
// Wait for all deletions to complete
|
|
782
931
|
Promise.all(deletionPromises)
|