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/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.
|
|
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.
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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.
|
|
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
|
}
|
package/.cursor/rules/futura.mdc
DELETED
|
@@ -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.
|
package/examples/federation.js
DELETED
|
@@ -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);
|
package/examples/holograms.js
DELETED
|
@@ -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();
|