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 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<boolean>} - Returns true if successful, false if there was an error
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
- // Remove isHologram field before storing - NO LONGER NEEDED
146
- // if (data && data.isHologram !== undefined) {
147
- // delete data.isHologram;
148
- // }
149
- const payload = JSON.stringify(data); // The data being stored
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 put('DELETED') ack is received
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('DELETED', (ack) => { // <-- Use 'DELETED' string
734
+ targetNodeRef.get('_holograms').get(deletedHologramSoul).put(null, (ack) => { // Remove the hologram entry completely
652
735
  if (ack.err) {
653
- // Keep this warning for actual errors
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
- // Ack received log removed
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
- // Create deletion promises for each key
767
- keys.forEach(key => {
768
- deletionPromises.push(
769
- new Promise((resolveDelete) => {
770
- const deletePath = password ?
771
- user.get('private').get(lens).get(key) :
772
- holoInstance.gun.get(holoInstance.appname).get(holon).get(lens).get(key);
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
- deletePath.put(null, ack => {
775
- resolveDelete(!!ack.ok); // Convert to boolean
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)