holosphere 1.1.10 → 1.1.12

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/hologram.js ADDED
@@ -0,0 +1,156 @@
1
+ // holo_hologram.js
2
+
3
+ /**
4
+ * Creates a soul hologram object for a data item
5
+ * @param {HoloSphere} holoInstance - The HoloSphere instance.
6
+ * @param {string} holon - The holon where the original data is stored
7
+ * @param {string} lens - The lens where the original data is stored
8
+ * @param {object} data - The data to create a hologram for
9
+ * @returns {object} - A hologram object with id and soul
10
+ */
11
+ export function createHologram(holoInstance, holon, lens, data) {
12
+ // Check if the input data is already a hologram
13
+ if (isHologram(data)) {
14
+ // If it is, just return its existing ID and Soul, ignoring the provided holon/lens
15
+ console.warn('createHologram called with data that is already a hologram. Reusing existing soul:', data.soul);
16
+ return {
17
+ id: data.id,
18
+ soul: data.soul
19
+ };
20
+ }
21
+
22
+ // Original logic: Input data is not a hologram, create a new soul path
23
+ if (!holon || !lens || !data || !data.id) {
24
+ throw new Error('createHologram: Missing required parameters for non-hologram data');
25
+ }
26
+
27
+ const soul = `${holoInstance.appname}/${holon}/${lens}/${data.id}`;
28
+ return {
29
+ id: data.id,
30
+ soul: soul
31
+ };
32
+ }
33
+
34
+ /**
35
+ * Parses a soul path into its components.
36
+ * @param {string} soul - The soul path (e.g., "app/holon/lens/key").
37
+ * @returns {object|null} - An object with appname, holon, lens, key, or null if invalid.
38
+ */
39
+ export function parseSoulPath(soul) {
40
+ if (typeof soul !== 'string') return null;
41
+ const parts = soul.split('/');
42
+ if (parts.length < 4) return null; // Must have at least app/holon/lens/key
43
+
44
+ // Reconstruct key if it contained slashes (though generally disallowed by getNodeRef validation)
45
+ const key = parts.slice(3).join('/');
46
+
47
+ return {
48
+ appname: parts[0],
49
+ holon: parts[1],
50
+ lens: parts[2],
51
+ key: key
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Checks if an object is a hologram.
57
+ * This function checks for the presence and type of `id` and `soul` properties,
58
+ * suitable for identifying holograms represented as plain JavaScript objects.
59
+ * It also performs a basic check that the `soul` contains '/' as expected for a path.
60
+ * @param {object | null | undefined} data - The data to check.
61
+ * @returns {boolean} - True if the object is considered a hologram.
62
+ */
63
+ export function isHologram(data) {
64
+ if (!data || typeof data !== 'object') {
65
+ return false;
66
+ }
67
+
68
+ // Basic check: Does it have an 'id' and a 'soul' which is a non-empty string?
69
+ if (data.id && typeof data.soul === 'string' && data.soul.length > 0) {
70
+ // Optional stricter check: Does the soul look like a valid path?
71
+ // This prevents objects like { id: 1, soul: "hello" } from being counted.
72
+ // We can use a simplified check here or rely on parseSoulPath failing later.
73
+ if (data.soul.includes('/')) { // Simple check for path structure
74
+ return true;
75
+ }
76
+ }
77
+
78
+ return false;
79
+ }
80
+
81
+ /**
82
+ * Resolves a hologram to its actual data
83
+ * @param {HoloSphere} holoInstance - The HoloSphere instance.
84
+ * @param {object} hologram - The hologram to resolve
85
+ * @param {object} [options] - Optional parameters
86
+ * @param {boolean} [options.followHolograms=true] - Whether to follow nested holograms
87
+ * @param {Set<string>} [options.visited] - Internal use: Tracks visited souls to prevent loops
88
+ * @returns {Promise<object|null>} - The resolved data, null if resolution failed due to target not found, or the original hologram for circular/invalid cases.
89
+ */
90
+ export async function resolveHologram(holoInstance, hologram, options = {}) {
91
+ if (!isHologram(hologram)) {
92
+ return hologram; // Not a hologram, return as is
93
+ }
94
+
95
+ const { followHolograms = true, visited = new Set() } = options;
96
+
97
+ // Check for circular hologram FIRST
98
+ if (hologram.soul && visited.has(hologram.soul)) {
99
+ console.warn(`!!! CIRCULAR hologram detected for soul: ${hologram.soul}. Returning original hologram.`);
100
+ throw new Error(`CIRCULAR_REFERENCE:${hologram.soul}`);
101
+ } else {
102
+ try {
103
+ // Handle direct soul hologram
104
+ if (hologram.soul) {
105
+ const soulInfo = parseSoulPath(hologram.soul);
106
+ if (!soulInfo) {
107
+ console.warn(`Invalid soul format: ${hologram.soul}`);
108
+ return hologram;
109
+ }
110
+
111
+ // Add current soul to visited set for THIS resolution path
112
+ const nextVisited = new Set(visited);
113
+ nextVisited.add(hologram.soul);
114
+
115
+ console.log(`Resolving hologram with soul: ${hologram.soul}`);
116
+
117
+ // Get original data
118
+ const originalData = await holoInstance.get(
119
+ soulInfo.holon,
120
+ soulInfo.lens,
121
+ soulInfo.key,
122
+ null,
123
+ {
124
+ resolveHolograms: followHolograms,
125
+ visited: nextVisited
126
+ }
127
+ );
128
+
129
+ console.log('### resolveHologram received originalData:', originalData);
130
+
131
+ if (originalData) {
132
+ console.log(`### Returning RESOLVED data for soul: ${hologram.soul}`);
133
+ // Structure for the returned object - isHologram (top-level) is removed
134
+ return {
135
+ ...originalData,
136
+ _meta: {
137
+ ...(originalData._meta || {}), // Preserve original _meta
138
+ resolvedFromHologram: true, // This is now the primary indicator
139
+ hologramSoul: hologram.soul // Clarified meta field
140
+ }
141
+ };
142
+ } else {
143
+ console.warn(`!!! Original data NOT FOUND for soul: ${hologram.soul}. Returning null.`);
144
+ return null;
145
+ }
146
+ } else {
147
+ // Should not happen if isHologram() passed
148
+ console.warn('!!! resolveHologram called with object missing soul:', hologram);
149
+ return hologram;
150
+ }
151
+ } catch (error) {
152
+ console.error(`!!! Error resolving hologram: ${error.message}`, error);
153
+ return hologram; // Return original hologram on error
154
+ }
155
+ }
156
+ }
package/holosphere.d.ts CHANGED
@@ -2,12 +2,16 @@
2
2
  * Federation propagation options interface
3
3
  */
4
4
  interface PropagationOptions {
5
- /** Whether to use references instead of duplicating data (default: true) */
6
- useReferences?: boolean;
5
+ /** Whether to use holograms instead of duplicating data (default: true) */
6
+ useHolograms?: boolean;
7
7
  /** Specific target spaces to propagate to (default: all federated spaces) */
8
8
  targetSpaces?: string[];
9
9
  /** Password for accessing the source holon (if needed) */
10
10
  password?: string | null;
11
+ /** Whether to automatically propagate to parent hexagons (default: true) */
12
+ propagateToParents?: boolean;
13
+ /** Maximum number of parent levels to propagate to (default: 15) */
14
+ maxParentLevels?: number;
11
15
  }
12
16
 
13
17
  /**
@@ -18,14 +22,37 @@ interface PutOptions {
18
22
  autoPropagate?: boolean;
19
23
  /** Additional options to pass to propagate */
20
24
  propagationOptions?: PropagationOptions;
25
+ /** Whether to disable hologram redirection logic when putting data (default: false) */
26
+ disableHologramRedirection?: boolean;
21
27
  }
22
28
 
23
29
  /**
24
30
  * Get options interface
25
31
  */
26
32
  interface GetOptions {
27
- /** Whether to automatically resolve federation references (default: true) */
28
- resolveReferences?: boolean;
33
+ /** Whether to automatically resolve holograms (default: true) */
34
+ resolveHolograms?: boolean;
35
+ /** Options passed to the schema validator */
36
+ validationOptions?: object;
37
+ }
38
+
39
+ /**
40
+ * Resolve Hologram options interface
41
+ */
42
+ interface ResolveHologramOptions {
43
+ /** Whether to follow nested holograms (default: true) */
44
+ followHolograms?: boolean;
45
+ /** Internal use: Tracks visited souls to prevent loops */
46
+ visited?: Set<string>;
47
+ }
48
+
49
+ /**
50
+ * Represents a Hologram object, typically containing an id and a soul path.
51
+ */
52
+ interface Hologram {
53
+ id: string;
54
+ soul: string;
55
+ [key: string]: any; // Allow other properties, e.g., _federation
29
56
  }
30
57
 
31
58
  /**
@@ -90,13 +117,44 @@ interface PropagationResult {
90
117
  error?: string;
91
118
  /** Information message if applicable */
92
119
  message?: string;
120
+ /** Parent propagation results */
121
+ parentPropagation?: {
122
+ /** Number of successfully propagated items to parents */
123
+ success: number;
124
+ /** Number of errors encountered during parent propagation */
125
+ errors: number;
126
+ /** Number of parent propagations skipped */
127
+ skipped: number;
128
+ /** Messages from parent propagation */
129
+ messages: string[];
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Result from a put operation
135
+ */
136
+ interface PutResult {
137
+ /** Indicates if the put operation was successful */
138
+ success: boolean;
139
+ /** Indicates if the data ultimately put at the path was a hologram */
140
+ isHologramAtPath?: boolean;
141
+ /** The final holon where data was put (after potential redirection) */
142
+ pathHolon: string;
143
+ /** The final lens where data was put (after potential redirection) */
144
+ pathLens: string;
145
+ /** The final key under which data was put (after potential redirection) */
146
+ pathKey: string;
147
+ /** Result of any automatic propagation, if it occurred */
148
+ propagationResult?: PropagationResult | null;
149
+ /** Error message if the put operation failed at some point */
150
+ error?: string;
93
151
  }
94
152
 
95
153
  declare class HoloSphere {
96
154
  private appname;
97
155
  private strict;
98
156
  private validator;
99
- private gun;
157
+ public gun;
100
158
  private sea;
101
159
  private openai?;
102
160
  private subscriptions;
@@ -110,6 +168,12 @@ declare class HoloSphere {
110
168
  */
111
169
  constructor(appname: string, strict?: boolean, openaikey?: string | null, gunInstance?: any);
112
170
 
171
+ /**
172
+ * Gets the Gun instance.
173
+ * @returns {any} - The Gun instance.
174
+ */
175
+ getGun(): any;
176
+
113
177
  // ================================ SCHEMA FUNCTIONS ================================
114
178
 
115
179
  /**
@@ -138,7 +202,7 @@ declare class HoloSphere {
138
202
  * @param {PutOptions} [options] - Additional options
139
203
  * @returns {Promise<any>} - Returns result object if successful
140
204
  */
141
- put(holon: string, lens: string, data: object, password?: string | null, options?: PutOptions): Promise<any>;
205
+ put(holon: string, lens: string, data: object, password?: string | null, options?: PutOptions): Promise<PutResult>;
142
206
 
143
207
  /**
144
208
  * Retrieves content from the specified holon and lens.
@@ -232,6 +296,32 @@ declare class HoloSphere {
232
296
  */
233
297
  deleteNode(holon: string, lens: string, key: string): Promise<boolean>;
234
298
 
299
+ // ================================ HOLOGRAM FUNCTIONS ================================
300
+
301
+ /**
302
+ * Creates a soul hologram object for a data item.
303
+ * @param {string} holon - The holon where the original data is stored.
304
+ * @param {string} lens - The lens where the original data is stored.
305
+ * @param {object} data - The data to create a hologram for. Must have an 'id' field.
306
+ * @returns {Hologram} - A hologram object containing id and soul.
307
+ */
308
+ createHologram(holon: string, lens: string, data: { id: string, [key: string]: any }): Hologram;
309
+
310
+ /**
311
+ * Checks if an object is a hologram (has id and soul).
312
+ * @param {any} data - The data to check.
313
+ * @returns {boolean} - True if the object is considered a hologram.
314
+ */
315
+ isHologram(data: any): data is Hologram;
316
+
317
+ /**
318
+ * Resolves a hologram to its actual data by following its soul path.
319
+ * @param {Hologram} hologram - The hologram object to resolve.
320
+ * @param {ResolveHologramOptions} [options] - Options for resolution.
321
+ * @returns {Promise<object|null>} - The resolved data, null if not found, or the original hologram in case of loops/errors.
322
+ */
323
+ resolveHologram(hologram: Hologram, options?: ResolveHologramOptions): Promise<object | null>;
324
+
235
325
  // ================================ GLOBAL FUNCTIONS ================================
236
326
 
237
327
  /**
@@ -364,9 +454,12 @@ declare class HoloSphere {
364
454
  * @param {string} [password1] - Optional password for the first holon
365
455
  * @param {string} [password2] - Optional password for the second holon
366
456
  * @param {boolean} [bidirectional=true] - Whether to set up bidirectional notifications automatically
457
+ * @param {object} [lensConfig] - Optional lens-specific configuration
458
+ * @param {string[]} [lensConfig.federate] - List of lenses to federate (default: all)
459
+ * @param {string[]} [lensConfig.notify] - List of lenses to notify (default: all)
367
460
  * @returns {Promise<boolean>} - True if federation was created successfully
368
461
  */
369
- federate(holonId1: string, holonId2: string, password1?: string | null, password2?: string | null, bidirectional?: boolean): Promise<boolean>;
462
+ federate(holonId1: string, holonId2: string, password1?: string | null, password2?: string | null, bidirectional?: boolean, lensConfig?: { federate?: string[], notify?: string[] }): Promise<boolean>;
370
463
 
371
464
  /**
372
465
  * Subscribes to federation notifications for a holon
@@ -386,6 +479,15 @@ declare class HoloSphere {
386
479
  */
387
480
  getFederation(holonId: string, password?: string | null): Promise<FederationInfo | null>;
388
481
 
482
+ /**
483
+ * Retrieves the lens-specific configuration for a federation link between two holons.
484
+ * @param {string} holonId - The ID of the source holon.
485
+ * @param {string} targetHolonId - The ID of the target holon in the federation link.
486
+ * @param {string} [password] - Optional password for the source holon.
487
+ * @returns {Promise<{ federate: string[], notify: string[] } | null>} - An object with 'federate' and 'notify' arrays, or null if not found.
488
+ */
489
+ getFederatedConfig(holonId: string, targetHolonId: string, password?: string | null): Promise<{ federate: string[], notify: string[] } | null>;
490
+
389
491
  /**
390
492
  * Removes a federation relationship between holons
391
493
  * @param {string} holonId1 - The first holon ID