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/holosphere.d.ts CHANGED
@@ -8,6 +8,10 @@ interface PropagationOptions {
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
  /**
@@ -113,6 +117,17 @@ interface PropagationResult {
113
117
  error?: string;
114
118
  /** Information message if applicable */
115
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
+ };
116
131
  }
117
132
 
118
133
  /**
package/holosphere.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module holosphere
3
- * @version 1.1.11
3
+ * @version 1.1.12
4
4
  * @description Holonic Geospatial Communication Infrastructure
5
5
  * @author Roberto Valenti
6
6
  * @license GPL-3.0-or-later
@@ -20,7 +20,7 @@ import * as ComputeOps from './compute.js';
20
20
  import * as Utils from './utils.js';
21
21
 
22
22
  // Define the version constant
23
- const HOLOSPHERE_VERSION = '1.1.11';
23
+ const HOLOSPHERE_VERSION = '1.1.12';
24
24
 
25
25
  class HoloSphere {
26
26
  /**
package/node.js CHANGED
@@ -18,6 +18,10 @@ export async function putNode(holoInstance, holon, lens, data) {
18
18
  // if (data && data.isHologram !== undefined) {
19
19
  // delete data.isHologram;
20
20
  // }
21
+
22
+ // Check if the data being stored is a hologram
23
+ const isHologram = data.value && holoInstance.isHologram(data.value);
24
+
21
25
  holoInstance.gun.get(holoInstance.appname)
22
26
  .get(holon)
23
27
  .get(lens)
@@ -26,6 +30,27 @@ export async function putNode(holoInstance, holon, lens, data) {
26
30
  if (ack.err) {
27
31
  reject(new Error(ack.err));
28
32
  } else {
33
+ // --- Start: Hologram Tracking Logic (for data *being put*, if it's a hologram) ---
34
+ if (isHologram) {
35
+ try {
36
+ const storedDataSoulInfo = holoInstance.parseSoulPath(data.value.soul);
37
+ if (storedDataSoulInfo) {
38
+ const targetNodeRef = holoInstance.getNodeRef(data.value.soul); // Target of the data *being put*
39
+ // Soul of the hologram that was *actually stored* at holon/lens/value
40
+ const storedHologramInstanceSoul = `${holoInstance.appname}/${holon}/${lens}/value`;
41
+
42
+ targetNodeRef.get('_holograms').get(storedHologramInstanceSoul).put(true);
43
+
44
+ console.log(`Data (ID: ${data.id}) being put is a hologram. Added its instance soul ${storedHologramInstanceSoul} to its target ${data.value.soul}'s _holograms set.`);
45
+ } else {
46
+ console.warn(`Data (ID: ${data.id}) being put is a hologram, but could not parse its soul ${data.value.soul} for tracking.`);
47
+ }
48
+ } catch (trackingError) {
49
+ console.warn(`Error updating _holograms set for the target of the data being put (data ID: ${data.id}, soul: ${data.value.soul}):`, trackingError);
50
+ }
51
+ }
52
+ // --- End: Hologram Tracking Logic ---
53
+
29
54
  resolve(true);
30
55
  }
31
56
  });
@@ -139,17 +164,77 @@ export async function deleteNode(holoInstance, holon, lens, key) {
139
164
  if (!holon || !lens || !key) {
140
165
  throw new Error('deleteNode: Missing required parameters');
141
166
  }
142
- return new Promise((resolve, reject) => {
143
- holoInstance.gun.get(holoInstance.appname)
144
- .get(holon)
145
- .get(lens)
146
- .get(key)
147
- .put(null, ack => {
167
+
168
+ try {
169
+ const dataPath = holoInstance.gun.get(holoInstance.appname).get(holon).get(lens).get(key);
170
+
171
+ // --- Start: Hologram Tracking Removal ---
172
+ let trackingRemovalPromise = Promise.resolve(); // Default to resolved promise
173
+
174
+ // 1. Get the data first to check if it's a hologram
175
+ const rawDataToDelete = await new Promise((resolve) => dataPath.once(resolve));
176
+ let dataToDelete = null;
177
+ try {
178
+ if (typeof rawDataToDelete === 'string') {
179
+ dataToDelete = JSON.parse(rawDataToDelete);
180
+ } else {
181
+ // Handle cases where it might already be an object (though likely string)
182
+ dataToDelete = rawDataToDelete;
183
+ }
184
+ } catch(e) {
185
+ console.warn("[deleteNode] Could not JSON parse data for deletion check:", rawDataToDelete, e);
186
+ dataToDelete = null; // Ensure it's null if parsing fails
187
+ }
188
+
189
+ // 2. If it is a hologram, try to remove its reference from the target
190
+ const isDataHologram = dataToDelete && holoInstance.isHologram(dataToDelete);
191
+
192
+ if (isDataHologram) {
193
+ try {
194
+ const targetSoul = dataToDelete.soul;
195
+ const targetSoulInfo = holoInstance.parseSoulPath(targetSoul);
196
+
197
+ if (targetSoulInfo) {
198
+ const targetNodeRef = holoInstance.getNodeRef(targetSoul);
199
+ // putNode stores at the 'value' key, not at the data.id key
200
+ const deletedHologramSoul = `${holoInstance.appname}/${holon}/${lens}/value`;
201
+
202
+ // Create a promise that resolves when the hologram is removed from the list
203
+ trackingRemovalPromise = new Promise((resolveTrack) => { // No reject needed, just warn on error
204
+ targetNodeRef.get('_holograms').get(deletedHologramSoul).put(null, (ack) => { // Remove the hologram entry completely
205
+ if (ack.err) {
206
+ console.warn(`[deleteNode] Error removing hologram ${deletedHologramSoul} from target ${targetSoul}:`, ack.err);
207
+ }
208
+ console.log(`Removed hologram ${deletedHologramSoul} from target ${targetSoul}'s _holograms list`);
209
+ resolveTrack(); // Resolve regardless of ack error to not block main delete
210
+ });
211
+ });
212
+ } else {
213
+ console.warn(`Could not parse target soul ${targetSoul} for hologram tracking removal during deleteNode.`);
214
+ }
215
+ } catch (trackingError) {
216
+ console.warn(`Error initiating hologram reference removal from target ${dataToDelete.soul} during deleteNode:`, trackingError);
217
+ // Ensure trackingRemovalPromise remains resolved if setup fails
218
+ trackingRemovalPromise = Promise.resolve();
219
+ }
220
+ }
221
+ // --- End: Hologram Tracking Removal ---
222
+
223
+ // 3. Wait for the tracking removal attempt to be acknowledged
224
+ await trackingRemovalPromise;
225
+
226
+ // 4. Proceed with the actual deletion of the hologram node itself
227
+ return new Promise((resolve, reject) => {
228
+ dataPath.put(null, ack => {
148
229
  if (ack.err) {
149
230
  reject(new Error(ack.err));
150
231
  } else {
151
232
  resolve(true);
152
233
  }
153
234
  });
154
- });
235
+ });
236
+ } catch (error) {
237
+ console.error('Error in deleteNode:', error);
238
+ throw error;
239
+ }
155
240
  }
package/package.json CHANGED
@@ -1,14 +1,20 @@
1
1
  {
2
2
  "name": "holosphere",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "description": "Holonic Geospatial Communication Infrastructure",
5
5
  "main": "holosphere.js",
6
6
  "types": "holosphere.d.ts",
7
7
  "type": "module",
8
8
  "scripts": {
9
9
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
10
- "build": "",
11
- "prepare": "npm run build"
10
+ "build": "npm run build:browser",
11
+ "prepare": "npm run build",
12
+ "build:browser": "node build.js",
13
+ "build:bundle": "node build.js",
14
+ "prepublishOnly.disabled": "npm test && npm run build",
15
+ "publish:cdn": "npm publish && echo 'Package published to npm and will be available on CDNs within minutes'",
16
+ "publish:force": "npm publish --force && echo 'Package force published to npm and will be available on CDNs within minutes'",
17
+ "prepublish:skip-tests": "npm run build"
12
18
  },
13
19
  "author": "Roberto Valenti",
14
20
  "license": "GPL-3.0-or-later",
@@ -19,11 +25,80 @@
19
25
  "openai": "^4.85.1"
20
26
  },
21
27
  "devDependencies": {
28
+ "esbuild": "^0.25.5",
22
29
  "jest": "^29.7.0",
23
30
  "jest-environment-node": "^29.7.0"
24
31
  },
25
32
  "jest": {
26
33
  "testEnvironment": "node",
27
34
  "transform": {}
35
+ },
36
+ "browser": "holosphere-bundle.js",
37
+ "unpkg": "holosphere-bundle.js",
38
+ "jsdelivr": "holosphere-bundle.js",
39
+ "cdn": "holosphere-bundle.js",
40
+ "files": [
41
+ "holosphere.js",
42
+ "holosphere-bundle.js",
43
+ "holosphere-bundle.min.js",
44
+ "holosphere-bundle.esm.js",
45
+ "holosphere.d.ts",
46
+ "federation.js",
47
+ "schema.js",
48
+ "content.js",
49
+ "node.js",
50
+ "global.js",
51
+ "hologram.js",
52
+ "compute.js",
53
+ "utils.js",
54
+ "hexlib.js",
55
+ "README.md",
56
+ "LICENSE",
57
+ "FEDERATION.md"
58
+ ],
59
+ "exports": {
60
+ ".": {
61
+ "browser": "./holosphere-bundle.js",
62
+ "import": "./holosphere.js",
63
+ "require": "./holosphere.js",
64
+ "default": "./holosphere.js"
65
+ },
66
+ "./bundle": "./holosphere-bundle.js",
67
+ "./bundle/esm": "./holosphere-bundle.esm.js",
68
+ "./bundle/min": "./holosphere-bundle.min.js",
69
+ "./browser": "./holosphere-bundle.js",
70
+ "./node": "./holosphere.js"
71
+ },
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "git+https://github.com/rvalenti/holosphere.git"
75
+ },
76
+ "keywords": [
77
+ "holonic",
78
+ "geospatial",
79
+ "h3",
80
+ "hexagon",
81
+ "p2p",
82
+ "decentralized",
83
+ "gun",
84
+ "spatial",
85
+ "mapping",
86
+ "cdn",
87
+ "browser",
88
+ "realtime",
89
+ "webrtc"
90
+ ],
91
+ "bugs": {
92
+ "url": "https://github.com/rvalenti/holosphere/issues"
93
+ },
94
+ "homepage": "https://github.com/rvalenti/holosphere#readme",
95
+ "peerDependencies": {
96
+ "gun": "^0.2020.1240",
97
+ "h3-js": "^4.1.0"
98
+ },
99
+ "peerDependenciesMeta": {
100
+ "openai": {
101
+ "optional": true
102
+ }
28
103
  }
29
104
  }
@@ -1,55 +0,0 @@
1
- ---
2
- description:
3
- globs:
4
- alwaysApply: true
5
- ---
6
- ## 1. Collaboration with PRD Development
7
- - Do not start coding until the PRD is provided.
8
- - Once I send the completed PRD, use it as the definitive guide for all tasks, referring to it before starting any work.
9
- - Treat the PRD as a living document that may evolve; check for updates before each task and adjust plans accordingly.
10
- - Reference the PRD’s user stories, acceptance criteria, and priority levels (Must-have, Should-have, Could-have, Won’t-have) to guide coding and testing decisions.
11
- - Never use React, libraries are outdated and gives too many problems of compatibility and stability, go for Python in doubt
12
- - Do not build frontend and backend in separate folders and instaces as it seems that you will have a lot of trouble in managing the connections between the 2 sides
13
-
14
- ## 2. Project Setup and Tracking
15
- - After receiving the PRD, create a README.md file with:
16
- - A section listing all patterns and technologies used in the project (e.g., frameworks, libraries, tools).
17
- - A brief project overview based on the PRD.
18
- - Create a checklist.md file with:
19
- - A task list derived from the PRD, broken into actionable steps (e.g., "Implement login endpoint", "Write tests for user authentication").
20
- - A status column (e.g., "Not Started", "In Progress", "Completed") to track progress.
21
- - Update checklist.md after completing each task by marking it as "Completed" and noting the git commit hash.
22
- - Incorporate the PRD’s feature breakdown table into checklist.md, including Priority and Dependencies columns to sequence tasks logically.
23
- - If the PRD includes a release plan (e.g., MVP, v1.1), group tasks by release milestones in checklist.md.
24
-
25
- ## 3. Task Execution Workflow
26
- ### Step 1: Identify the Next Task
27
- - Grep the codebase, review the PRD, and check checklist.md to determine the next task in sequence.
28
- - Focus only on the code areas relevant to the current task.
29
- - Use the PRD’s priority levels and technical dependencies to select the next task, starting with Must-haves and respecting dependency order.
30
-
31
- ### Step 2: Write the Code
32
- - Iterate on existing code if possible, avoiding new solutions unless necessary.
33
- - Follow naming conventions and keep files under 500-700 lines, refactoring if needed.
34
- - Add comments for complex logic.
35
- - Avoid duplication by checking for similar functionality elsewhere in the codebase.
36
- - Ensure code meets the PRD’s acceptance criteria for the task’s feature or user story.
37
- - Adhere to non-functional requirements (e.g., performance, scalability) from the PRD when applicable.
38
-
39
- ### Step 3: Write Tests
40
- - Write unit tests for individual functions and integration tests for workflows.
41
- - Name tests clearly (e.g., testLoginSuccess, testUserCreationWorkflow).
42
- - Ensure tests cover major functionality and edge cases outlined in the PRD.
43
- - Make tests specific, measurable, and traceable to the PRD’s acceptance criteria (e.g., "User can log in with email/password" passes if the API returns a 200 status).
44
- - Include tests for edge cases and error states documented in the PRD’s User Flows or AI-generated insights.
45
-
46
- ### Step 4: Run the Server and Tests
47
- - Run all tests and verify they pass.
48
-
49
- ### Step 5: Handle Test Failures
50
- - If tests fail, first review the test for accuracy (e.g., correct assertions, realistic mocks). Edit the test if it’s incorrect.
51
- - If the test is valid and still fails, debug the code:
52
- - Add logs/console messages to trace the issue.
53
- - Fix the underlying problem rather than masking it.
54
- - Re-run the server and tests after each change.
55
- - Repeat until all tests pass. For persistent issues, check the fixes folder for prior solutions or use firecrawl to research fixes.
@@ -1,162 +0,0 @@
1
- /**
2
- * Organization Federation Example for HoloSphere (Updated API)
3
- *
4
- * This example demonstrates a real-world use case where a tech team creates tasks
5
- * that are automatically federated to the parent organization for visibility using
6
- * the latest HoloSphere federation features.
7
- */
8
-
9
- import HoloSphere from '../holosphere.js';
10
-
11
- async function organizationFederationExample() {
12
- const holoSphere = new HoloSphere('organization-example-updated');
13
-
14
- try {
15
- console.log('Starting Organization Federation Example (Updated API)...');
16
-
17
- // Define unique names for this run to avoid conflicts
18
- const runId = Date.now();
19
- const orgHolon = `acme-org-${runId}`;
20
- const techTeamHolon = `acme-tech-${runId}`;
21
-
22
- // Step 1: Create federation relationship (bidirectional by default)
23
- console.log('\nStep 1: Creating federation relationship...');
24
- // The `federate` method automatically sets up bidirectional notifications when `bidirectional` is true (default).
25
- const federateResult = await holoSphere.federate(techTeamHolon, orgHolon);
26
- if (!federateResult) {
27
- throw new Error('Federation setup failed.');
28
- }
29
- console.log(`Federation created between ${techTeamHolon} and ${orgHolon}`);
30
-
31
- // Allow a moment for GunDB propagation of federation settings
32
- await new Promise(resolve => setTimeout(resolve, 1500));
33
-
34
- // Step 2: Verify federation is set up properly
35
- console.log('\nStep 2: Verifying federation setup...');
36
- const techTeamFedInfo = await holoSphere.getFederation(techTeamHolon);
37
- console.log(`Tech team (${techTeamHolon}) federation info:`, techTeamFedInfo);
38
- if (!techTeamFedInfo?.federation?.includes(orgHolon)) {
39
- console.warn('Warning: Organization holon not found in tech team federation list.');
40
- }
41
-
42
- const orgFedInfo = await holoSphere.getFederation(orgHolon);
43
- console.log(`Organization (${orgHolon}) federation info:`, orgFedInfo);
44
- if (!orgFedInfo?.notify?.includes(techTeamHolon)) {
45
- console.warn('Warning: Tech team holon not found in organization notify list.');
46
- }
47
-
48
- // Step 3: Create a task in the tech team holon
49
- // The `put` method automatically propagates data to federated holons by default (`autoPropagate: true`).
50
- console.log('\nStep 3: Creating a task in the tech team holon (will auto-propagate)...');
51
-
52
- const task = {
53
- id: `task-${runId}-123`,
54
- title: 'Implement new authentication system',
55
- description: 'Replace the current auth system with OAuth2',
56
- assignee: 'dev@example.com',
57
- status: 'in_progress',
58
- priority: 'high',
59
- dueDate: '2024-12-31',
60
- createdAt: new Date().toISOString(),
61
- tags: ['security', 'infrastructure']
62
- };
63
-
64
- // Store the task - it will be automatically propagated to orgHolon due to federation
65
- const putResult = await holoSphere.put(techTeamHolon, 'tasks', task);
66
- console.log(`Task created in ${techTeamHolon}: ${task.id}. Propagation result:`, putResult.propagationResult);
67
- if (putResult.propagationResult?.errors > 0) {
68
- console.warn('Warning: Auto-propagation reported errors.');
69
- }
70
-
71
- // Step 4: Allow time for propagation via put
72
- console.log('\nStep 4: Waiting for auto-propagation to complete...');
73
- await new Promise(resolve => setTimeout(resolve, 1500));
74
-
75
- // Step 5: Verify task in both holons
76
- console.log('\nStep 5: Verifying task is in both holons...');
77
-
78
- // Check tech team holon directly (original data)
79
- const techTeamTask = await holoSphere.get(techTeamHolon, 'tasks', task.id);
80
- console.log(`Task in tech team holon (${techTeamHolon}):`, techTeamTask ? 'Found' : 'Not found');
81
- if (techTeamTask) console.log('Tech team task status:', techTeamTask.status);
82
-
83
- // Check organization holon directly (should have a resolved reference)
84
- const orgTask = await holoSphere.get(orgHolon, 'tasks', task.id);
85
- console.log(`Task in organization holon (${orgHolon}):`, orgTask ? 'Found' : 'Not found');
86
- if (orgTask) {
87
- console.log('Organization task status:', orgTask.status);
88
- // Check if it's a resolved reference
89
- console.log('Is resolved reference:', !!orgTask._federation?.resolved);
90
- } else {
91
- console.warn(`Task ${task.id} not found in organization holon ${orgHolon}. Propagation might have failed or is slow.`);
92
- }
93
-
94
- // Step 6: Use getFederated to view all tasks from the organization's perspective
95
- console.log('\nStep 6: Using getFederated to view all tasks...');
96
-
97
- const allOrgTasks = await holoSphere.getFederated(orgHolon, 'tasks');
98
- console.log(`Organization holon (${orgHolon}) has access to ${allOrgTasks.length} tasks (via getFederated):`);
99
- // console.log(allOrgTasks); // Uncomment to see the full list
100
-
101
- const allTechTasks = await holoSphere.getFederated(techTeamHolon, 'tasks');
102
- console.log(`Tech team holon (${techTeamHolon}) has access to ${allTechTasks.length} tasks (via getFederated):`);
103
- // console.log(allTechTasks); // Uncomment to see the full list
104
-
105
- // Step 7: Update the task in tech team holon (will also auto-propagate)
106
- console.log('\nStep 7: Updating task in tech team holon (will auto-propagate)...');
107
-
108
- const updatedTask = {
109
- ...task,
110
- status: 'completed',
111
- completedAt: new Date().toISOString()
112
- };
113
-
114
- // Update the task - the change will be automatically propagated
115
- const updateResult = await holoSphere.put(techTeamHolon, 'tasks', updatedTask);
116
- console.log(`Task updated in ${techTeamHolon}. Propagation result:`, updateResult.propagationResult);
117
- if (updateResult.propagationResult?.errors > 0) {
118
- console.warn('Warning: Auto-propagation of update reported errors.');
119
- }
120
-
121
- // Step 8: Allow time for update propagation
122
- console.log('\nStep 8: Waiting for update propagation...');
123
- await new Promise(resolve => setTimeout(resolve, 1500));
124
-
125
- // Step 9: Verify updates in both holons
126
- console.log('\nStep 9: Verifying updated task in both holons...');
127
-
128
- const updatedTechTeamTask = await holoSphere.get(techTeamHolon, 'tasks', task.id);
129
- console.log(`Updated task status in tech team holon (${techTeamHolon}):`, updatedTechTeamTask?.status);
130
-
131
- // Get the potentially updated reference in the organization holon
132
- const updatedOrgTask = await holoSphere.get(orgHolon, 'tasks', task.id);
133
- console.log(`Updated task status in organization holon (${orgHolon}):`, updatedOrgTask?.status);
134
- if (!updatedOrgTask || updatedOrgTask.status !== 'completed') {
135
- console.warn(`Updated task status not reflected in organization holon ${orgHolon}. Propagation might have failed or is slow.`);
136
- }
137
-
138
- // Step 10: Clean up - remove federation
139
- console.log('\nStep 10: Cleaning up - removing federation...');
140
- await holoSphere.unfederate(techTeamHolon, orgHolon);
141
- console.log(`Federation removed between ${techTeamHolon} and ${orgHolon}`);
142
-
143
- // Optional: Clean up data (can be slow and sometimes unreliable in Gun)
144
- // console.log('Cleaning up task data...');
145
- // await holoSphere.delete(techTeamHolon, 'tasks', task.id);
146
- // await holoSphere.delete(orgHolon, 'tasks', task.id); // Delete the reference
147
- // await holoSphere.deleteGlobal('federation', techTeamHolon);
148
- // await holoSphere.deleteGlobal('federation', orgHolon);
149
-
150
- console.log('\nOrganization federation example completed successfully!');
151
-
152
- } catch (error) {
153
- console.error('Error in organization federation example:', error);
154
- } finally {
155
- // Always close the HoloSphere instance
156
- await holoSphere.close();
157
- console.log('HoloSphere instance closed');
158
- }
159
- }
160
-
161
- // Run the example
162
- organizationFederationExample().catch(console.error);
@@ -1,175 +0,0 @@
1
- import HoloSphere from '../holosphere.js';
2
-
3
- async function testHologramFederation() {
4
- console.log('Starting hologram federation test...');
5
- const holoSphere = new HoloSphere('test-holograms');
6
-
7
- try {
8
- const space1 = 'holo-test-space1';
9
- const space2 = 'holo-test-space2';
10
-
11
- // Step 1: Create federation with bidirectional notify settings
12
- console.log('Step 1: Creating federation between spaces...');
13
- await holoSphere.federate(space1, space2);
14
-
15
- // Also federate from space2 to space1 for testing getFederated
16
- await holoSphere.federate(space2, space1);
17
-
18
- // Step 2: Verify federation is set up properly
19
- const fedInfo = await holoSphere.getFederation(space1);
20
- console.log('Federation info for space1:', fedInfo);
21
-
22
- const fedInfo2 = await holoSphere.getFederation(space2);
23
- console.log('Federation info for space2:', fedInfo2);
24
-
25
- // Step 3: Create test data
26
- console.log('Step 3: Creating test data...');
27
- const testData = {
28
- id: 'holo-test-item',
29
- title: 'Hologram Test',
30
- value: 200,
31
- tags: ['test', 'hologram']
32
- };
33
-
34
- // Store data in space1
35
- await holoSphere.put(space1, 'items', testData);
36
-
37
- // Step 4: Propagate using holograms
38
- console.log('Step 4: Propagating with soul holograms...');
39
- const propResult = await holoSphere.propagate(space1, 'items', testData, {
40
- useHolograms: true
41
- });
42
- console.log('Propagation result:', propResult);
43
-
44
- // Allow time for propagation
45
- console.log('Waiting for propagation...');
46
- await new Promise(resolve => setTimeout(resolve, 1000));
47
-
48
- // Step 5: Verify that the data in space2 is a soul hologram
49
- console.log('Step 5: Verifying soul hologram was created...');
50
- const rawHolo = await holoSphere.get(space2, 'items', 'holo-test-item', null, {
51
- resolveHolograms: false
52
- });
53
-
54
- console.log('Raw hologram data:', rawHolo);
55
- console.log('Is soul hologram:', holoSphere.isHologram(rawHolo));
56
-
57
- if (rawHolo?.soul) {
58
- const soulParts = rawHolo.soul.split('/');
59
- console.log('Soul parts:', soulParts);
60
- console.log('Soul refers to:', {
61
- app: soulParts[0],
62
- holon: soulParts[1],
63
- lens: soulParts[2],
64
- key: soulParts[3]
65
- });
66
- }
67
-
68
- // Step 6: Verify hologram resolution works
69
- console.log('Step 6: Verifying hologram resolution...');
70
- const resolvedData = await holoSphere.get(space2, 'items', 'holo-test-item');
71
- console.log('Resolved data:', resolvedData);
72
-
73
- // Step 7: Update the original data
74
- console.log('Step 7: Updating original data...');
75
- const updatedData = {
76
- ...testData,
77
- value: 300,
78
- updated: true
79
- };
80
-
81
- await holoSphere.put(space1, 'items', updatedData);
82
-
83
- // Allow time for update to propagate
84
- console.log('Waiting for update...');
85
- await new Promise(resolve => setTimeout(resolve, 500));
86
-
87
- // Step 8: Verify update is reflected through the hologram
88
- console.log('Step 8: Verifying update is reflected in hologram...');
89
- const reResolvedData = await holoSphere.get(space2, 'items', 'holo-test-item');
90
- console.log('Re-resolved data after update:', reResolvedData);
91
-
92
- // Step 9: Update directly through origin holon
93
- console.log('Step 9: Updating through the origin holon...');
94
- const originData = await holoSphere.get(space1, 'items', 'holo-test-item');
95
-
96
- const finalUpdate = {
97
- ...originData,
98
- value: 400,
99
- finalUpdate: true
100
- };
101
-
102
- await holoSphere.put(space1, 'items', finalUpdate);
103
-
104
- // Allow time for update to propagate
105
- console.log('Waiting for final update...');
106
- await new Promise(resolve => setTimeout(resolve, 500));
107
-
108
- // Step 10: Verify final update through the hologram in space2
109
- console.log('Step 10: Verifying final update is reflected...');
110
- const finalResolvedData = await holoSphere.get(space2, 'items', 'holo-test-item');
111
- console.log('Final resolved data:', finalResolvedData);
112
-
113
- // Step 11: Test manual soul hologram resolution
114
- console.log('Step 11: Testing manual soul hologram resolution...');
115
-
116
- // Check what getAll returns
117
- console.log('Raw holograms from getAll in space2:');
118
- const allItems = await holoSphere.getAll(space2, 'items');
119
- console.log('getAll results:', allItems);
120
-
121
- if (allItems.length > 0 && allItems[0].soul) {
122
- console.log('Found a soul hologram, resolving it manually:');
123
- const soulParts = allItems[0].soul.split('/');
124
-
125
- const originHolon = soulParts[1];
126
- const originLens = soulParts[2];
127
- const originKey = soulParts[3];
128
-
129
- console.log(`Soul path components: holon=${originHolon}, lens=${originLens}, key=${originKey}`);
130
-
131
- const originalData = await holoSphere.get(
132
- originHolon,
133
- originLens,
134
- originKey,
135
- null,
136
- { resolveHolograms: false }
137
- );
138
- console.log('Manually resolved hologram data:', originalData);
139
- }
140
-
141
- // Test getFederated with holograms
142
- console.log('\nTesting getFederated with holograms:');
143
- const federatedData = await holoSphere.getFederated(space2, 'items', {
144
- resolveHolograms: true,
145
- idField: 'id'
146
- });
147
-
148
- console.log('getFederated results length:', federatedData.length);
149
-
150
- // Find the item by ID
151
- const federatedItem = federatedData.find(item => item.id === 'holo-test-item');
152
- console.log('Found federated item by ID:', federatedItem);
153
-
154
- // Check if federated data correctly resolves soul holograms
155
- if (federatedItem && federatedItem.value === 400 && federatedItem.finalUpdate) {
156
- console.log('SUCCESS: getFederated correctly resolved the soul hologram!');
157
- } else {
158
- console.log('WARNING: getFederated may not be resolving soul holograms properly');
159
- }
160
-
161
- // Step 12: Clean up
162
- console.log('Step 12: Cleaning up...');
163
- await holoSphere.unfederate(space1, space2);
164
- await holoSphere.unfederate(space2, space1);
165
-
166
- console.log('Hologram federation test completed successfully!');
167
- } catch (error) {
168
- console.error('Hologram federation test failed:', error);
169
- } finally {
170
- await holoSphere.close();
171
- console.log('HoloSphere connection closed.');
172
- }
173
- }
174
-
175
- testHologramFederation();