holosphere 1.1.12 → 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/federation.js +25 -8
- package/holosphere-bundle.esm.js +33184 -0
- package/holosphere-bundle.js +33206 -0
- package/holosphere-bundle.min.js +38 -0
- package/package.json +78 -3
- package/.cursor/rules/futura.mdc +0 -55
- package/examples/federation.js +0 -162
- package/examples/hologram-updates-example.js +0 -106
- 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-deletion.test.js +0 -197
- package/test/hologram-updates-return.test.js +0 -166
- package/test/hologram-updates.test.js +0 -143
- package/test/hologram.test.js +0 -316
- package/test/holosphere.test.js +0 -354
- package/test/meta-strip.test.js +0 -159
- package/test/parent-propagation.test.js +0 -138
- package/test/subscription.test.js +0 -364
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
// hologram-updates-return.test.js
|
|
2
|
-
|
|
3
|
-
import HoloSphere from '../holosphere.js';
|
|
4
|
-
|
|
5
|
-
describe('Hologram Updates Return Value Tests', () => {
|
|
6
|
-
let holoSphere;
|
|
7
|
-
const testHolon = 'updateReturnTestHolon';
|
|
8
|
-
const testLens = 'testLens';
|
|
9
|
-
const otherLens = 'otherLens';
|
|
10
|
-
const appName = 'test-hologram-return-app';
|
|
11
|
-
|
|
12
|
-
const waitForGun = (ms = 300) => new Promise(resolve => setTimeout(resolve, ms));
|
|
13
|
-
|
|
14
|
-
beforeEach(async () => {
|
|
15
|
-
holoSphere = new HoloSphere(appName, false);
|
|
16
|
-
// Clean up before each test
|
|
17
|
-
try {
|
|
18
|
-
await holoSphere.deleteAll(testHolon, testLens);
|
|
19
|
-
await holoSphere.deleteAll(testHolon, otherLens);
|
|
20
|
-
} catch (error) {
|
|
21
|
-
// Ignore cleanup errors
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
await waitForGun(100);
|
|
25
|
-
}, 30000);
|
|
26
|
-
|
|
27
|
-
afterEach(async () => {
|
|
28
|
-
if (holoSphere) {
|
|
29
|
-
await holoSphere.close();
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('put should return empty array when no holograms exist', async () => {
|
|
34
|
-
const originalData = { id: 'no-holograms-test', value: 'Original Value' };
|
|
35
|
-
|
|
36
|
-
// Put original data
|
|
37
|
-
const result = await holoSphere.put(testHolon, testLens, originalData);
|
|
38
|
-
|
|
39
|
-
expect(result).toBeDefined();
|
|
40
|
-
expect(result.success).toBe(true);
|
|
41
|
-
expect(result.updatedHolograms).toBeDefined();
|
|
42
|
-
expect(Array.isArray(result.updatedHolograms)).toBe(true);
|
|
43
|
-
expect(result.updatedHolograms).toHaveLength(0);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('put should return list of updated holograms when they exist', async () => {
|
|
47
|
-
const originalData = { id: 'with-holograms-test', value: 'Original Value' };
|
|
48
|
-
|
|
49
|
-
// Step 1: Put original data
|
|
50
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
51
|
-
await waitForGun();
|
|
52
|
-
|
|
53
|
-
// Step 2: Create holograms pointing to the original data
|
|
54
|
-
const hologram1 = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
55
|
-
const hologram2 = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
56
|
-
|
|
57
|
-
await holoSphere.put(testHolon, otherLens, { id: 'hologram-1', soul: hologram1.soul });
|
|
58
|
-
await holoSphere.put(testHolon, otherLens, { id: 'hologram-2', soul: hologram2.soul });
|
|
59
|
-
await waitForGun(500);
|
|
60
|
-
|
|
61
|
-
// Step 3: Update the original data and check the return value
|
|
62
|
-
const updatedData = { ...originalData, value: 'Updated Value', count: 42 };
|
|
63
|
-
const result = await holoSphere.put(testHolon, testLens, updatedData);
|
|
64
|
-
|
|
65
|
-
expect(result).toBeDefined();
|
|
66
|
-
expect(result.success).toBe(true);
|
|
67
|
-
expect(result.updatedHolograms).toBeDefined();
|
|
68
|
-
expect(Array.isArray(result.updatedHolograms)).toBe(true);
|
|
69
|
-
expect(result.updatedHolograms.length).toBeGreaterThan(0);
|
|
70
|
-
|
|
71
|
-
// Check that the returned hologram info is complete
|
|
72
|
-
result.updatedHolograms.forEach(hologram => {
|
|
73
|
-
expect(hologram.soul).toBeDefined();
|
|
74
|
-
expect(hologram.holon).toBe(testHolon);
|
|
75
|
-
expect(hologram.lens).toBeDefined(); // Could be testLens or otherLens
|
|
76
|
-
expect(hologram.key).toBeDefined();
|
|
77
|
-
expect(hologram.id).toBeDefined();
|
|
78
|
-
expect(hologram.timestamp).toBeDefined();
|
|
79
|
-
expect(typeof hologram.timestamp).toBe('number');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// Verify that the souls match what we expect
|
|
83
|
-
const expectedSouls = [
|
|
84
|
-
`${appName}/${testHolon}/${otherLens}/hologram-1`,
|
|
85
|
-
`${appName}/${testHolon}/${otherLens}/hologram-2`
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
const returnedSouls = result.updatedHolograms.map(h => h.soul);
|
|
89
|
-
expectedSouls.forEach(expectedSoul => {
|
|
90
|
-
expect(returnedSouls).toContain(expectedSoul);
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test('put should return updated holograms with correct structure', async () => {
|
|
95
|
-
const originalData = { id: 'structure-test', value: 'Test Value' };
|
|
96
|
-
|
|
97
|
-
// Put original data
|
|
98
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
99
|
-
await waitForGun();
|
|
100
|
-
|
|
101
|
-
// Create one hologram
|
|
102
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
103
|
-
await holoSphere.put(testHolon, otherLens, { id: 'structure-hologram', soul: hologram.soul });
|
|
104
|
-
await waitForGun(500);
|
|
105
|
-
|
|
106
|
-
// Update original data
|
|
107
|
-
const updatedData = { ...originalData, value: 'Updated Test Value' };
|
|
108
|
-
const result = await holoSphere.put(testHolon, testLens, updatedData);
|
|
109
|
-
|
|
110
|
-
expect(result.updatedHolograms).toHaveLength(1);
|
|
111
|
-
|
|
112
|
-
const updatedHologram = result.updatedHolograms[0];
|
|
113
|
-
expect(updatedHologram).toEqual({
|
|
114
|
-
soul: `${appName}/${testHolon}/${otherLens}/structure-hologram`,
|
|
115
|
-
holon: testHolon,
|
|
116
|
-
lens: otherLens,
|
|
117
|
-
key: 'structure-hologram',
|
|
118
|
-
id: 'structure-hologram',
|
|
119
|
-
timestamp: expect.any(Number)
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// Verify timestamp is recent (within last few seconds)
|
|
123
|
-
const now = Date.now();
|
|
124
|
-
expect(updatedHologram.timestamp).toBeGreaterThan(now - 5000);
|
|
125
|
-
expect(updatedHologram.timestamp).toBeLessThanOrEqual(now);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test('put with isHologramUpdate option should not return updated holograms', async () => {
|
|
129
|
-
const originalData = { id: 'no-recursive-test', value: 'Original Value' };
|
|
130
|
-
|
|
131
|
-
// Put original data
|
|
132
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
133
|
-
await waitForGun();
|
|
134
|
-
|
|
135
|
-
// Create hologram
|
|
136
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
137
|
-
await holoSphere.put(testHolon, otherLens, { id: 'recursive-test', soul: hologram.soul });
|
|
138
|
-
await waitForGun(500);
|
|
139
|
-
|
|
140
|
-
// Update with isHologramUpdate flag (should not trigger hologram updates)
|
|
141
|
-
const updatedData = { ...originalData, value: 'Updated Value' };
|
|
142
|
-
const result = await holoSphere.put(testHolon, testLens, updatedData, null, { isHologramUpdate: true });
|
|
143
|
-
|
|
144
|
-
expect(result).toBeDefined();
|
|
145
|
-
expect(result.success).toBe(true);
|
|
146
|
-
expect(result.updatedHolograms).toBeDefined();
|
|
147
|
-
expect(result.updatedHolograms).toHaveLength(0);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test('put hologram should not return updated holograms', async () => {
|
|
151
|
-
const originalData = { id: 'hologram-put-test', value: 'Original Value' };
|
|
152
|
-
|
|
153
|
-
// Put original data
|
|
154
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
155
|
-
await waitForGun();
|
|
156
|
-
|
|
157
|
-
// Put a hologram (not original data)
|
|
158
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
159
|
-
const result = await holoSphere.put(testHolon, otherLens, { id: 'test-hologram', soul: hologram.soul });
|
|
160
|
-
|
|
161
|
-
expect(result).toBeDefined();
|
|
162
|
-
expect(result.success).toBe(true);
|
|
163
|
-
expect(result.updatedHolograms).toBeDefined();
|
|
164
|
-
expect(result.updatedHolograms).toHaveLength(0);
|
|
165
|
-
});
|
|
166
|
-
});
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
// hologram-updates.test.js
|
|
2
|
-
|
|
3
|
-
import HoloSphere from '../holosphere.js';
|
|
4
|
-
|
|
5
|
-
describe('Hologram Update Tests', () => {
|
|
6
|
-
let holoSphere;
|
|
7
|
-
const testHolon = 'updateTestHolon';
|
|
8
|
-
const testLens = 'testLens';
|
|
9
|
-
const otherLens = 'otherLens';
|
|
10
|
-
const appName = 'test-hologram-update-app';
|
|
11
|
-
|
|
12
|
-
const waitForGun = (ms = 300) => new Promise(resolve => setTimeout(resolve, ms));
|
|
13
|
-
|
|
14
|
-
beforeEach(async () => {
|
|
15
|
-
holoSphere = new HoloSphere(appName, false);
|
|
16
|
-
// Clean up before each test
|
|
17
|
-
try {
|
|
18
|
-
await holoSphere.deleteAll(testHolon, testLens);
|
|
19
|
-
await holoSphere.deleteAll(testHolon, otherLens);
|
|
20
|
-
} catch (error) {
|
|
21
|
-
// Ignore cleanup errors
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
await waitForGun(100);
|
|
25
|
-
}, 30000);
|
|
26
|
-
|
|
27
|
-
afterEach(async () => {
|
|
28
|
-
if (holoSphere) {
|
|
29
|
-
await holoSphere.close();
|
|
30
|
-
}
|
|
31
|
-
}, 30000);
|
|
32
|
-
|
|
33
|
-
test('should update active holograms when original data is modified', async () => {
|
|
34
|
-
// 1. Store original data
|
|
35
|
-
const originalData = { id: 'update-test-item', value: 'Original Value', count: 1 };
|
|
36
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
37
|
-
await waitForGun();
|
|
38
|
-
|
|
39
|
-
// 2. Create and store a hologram pointing to the original data
|
|
40
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
41
|
-
await holoSphere.put(testHolon, otherLens, hologram); // Store hologram in different lens
|
|
42
|
-
await waitForGun(500);
|
|
43
|
-
|
|
44
|
-
// 3. Get the hologram before update (should not have 'updated' field)
|
|
45
|
-
const hologramBeforeUpdate = await holoSphere.get(testHolon, otherLens, originalData.id, null, { resolveHolograms: false });
|
|
46
|
-
expect(hologramBeforeUpdate).toBeDefined();
|
|
47
|
-
expect(hologramBeforeUpdate.soul).toBe(hologram.soul);
|
|
48
|
-
expect(hologramBeforeUpdate.updated).toBeUndefined();
|
|
49
|
-
|
|
50
|
-
// 4. Update the original data
|
|
51
|
-
const updatedData = { id: 'update-test-item', value: 'Updated Value', count: 2 };
|
|
52
|
-
await holoSphere.put(testHolon, testLens, updatedData);
|
|
53
|
-
await waitForGun(1000); // Give time for hologram updates to propagate
|
|
54
|
-
|
|
55
|
-
// 5. Check that the hologram now has an 'updated' timestamp
|
|
56
|
-
const hologramAfterUpdate = await holoSphere.get(testHolon, otherLens, originalData.id, null, { resolveHolograms: false });
|
|
57
|
-
expect(hologramAfterUpdate).toBeDefined();
|
|
58
|
-
expect(hologramAfterUpdate.soul).toBe(hologram.soul);
|
|
59
|
-
expect(hologramAfterUpdate.updated).toBeDefined();
|
|
60
|
-
expect(typeof hologramAfterUpdate.updated).toBe('number');
|
|
61
|
-
expect(hologramAfterUpdate.updated).toBeGreaterThan(Date.now() - 5000); // Should be recent
|
|
62
|
-
|
|
63
|
-
// 6. Verify that resolving the hologram gives the updated data
|
|
64
|
-
const resolvedData = await holoSphere.get(testHolon, otherLens, originalData.id);
|
|
65
|
-
expect(resolvedData).toBeDefined();
|
|
66
|
-
expect(resolvedData.value).toBe('Updated Value');
|
|
67
|
-
expect(resolvedData.count).toBe(2);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('should update multiple holograms pointing to the same data', async () => {
|
|
71
|
-
// 1. Store original data
|
|
72
|
-
const originalData = { id: 'multi-hologram-test', value: 'Original Value' };
|
|
73
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
74
|
-
await waitForGun();
|
|
75
|
-
|
|
76
|
-
// 2. Create and store multiple holograms pointing to the same data
|
|
77
|
-
const hologram1 = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
78
|
-
const hologram2 = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
79
|
-
|
|
80
|
-
await holoSphere.put(testHolon, otherLens, { ...hologram1, id: 'hologram-1' });
|
|
81
|
-
await holoSphere.put(testHolon, otherLens, { ...hologram2, id: 'hologram-2' });
|
|
82
|
-
await waitForGun(500);
|
|
83
|
-
|
|
84
|
-
// 3. Update the original data
|
|
85
|
-
const updatedData = { id: 'multi-hologram-test', value: 'Updated Value' };
|
|
86
|
-
await holoSphere.put(testHolon, testLens, updatedData);
|
|
87
|
-
await waitForGun(1000);
|
|
88
|
-
|
|
89
|
-
// 4. Check that both holograms have been updated
|
|
90
|
-
const updatedHologram1 = await holoSphere.get(testHolon, otherLens, 'hologram-1', null, { resolveHolograms: false });
|
|
91
|
-
const updatedHologram2 = await holoSphere.get(testHolon, otherLens, 'hologram-2', null, { resolveHolograms: false });
|
|
92
|
-
|
|
93
|
-
expect(updatedHologram1.updated).toBeDefined();
|
|
94
|
-
expect(updatedHologram2.updated).toBeDefined();
|
|
95
|
-
expect(typeof updatedHologram1.updated).toBe('number');
|
|
96
|
-
expect(typeof updatedHologram2.updated).toBe('number');
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test('should not update deleted holograms', async () => {
|
|
100
|
-
// 1. Store original data
|
|
101
|
-
const originalData = { id: 'delete-test-item', value: 'Original Value' };
|
|
102
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
103
|
-
await waitForGun();
|
|
104
|
-
|
|
105
|
-
// 2. Create and store a hologram
|
|
106
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
107
|
-
await holoSphere.put(testHolon, otherLens, hologram);
|
|
108
|
-
await waitForGun(500);
|
|
109
|
-
|
|
110
|
-
// 3. Delete the hologram
|
|
111
|
-
await holoSphere.delete(testHolon, otherLens, originalData.id);
|
|
112
|
-
await waitForGun(500);
|
|
113
|
-
|
|
114
|
-
// 4. Update the original data
|
|
115
|
-
const updatedData = { id: 'delete-test-item', value: 'Updated Value' };
|
|
116
|
-
await holoSphere.put(testHolon, testLens, updatedData);
|
|
117
|
-
await waitForGun(1000);
|
|
118
|
-
|
|
119
|
-
// 5. Verify the original data was updated
|
|
120
|
-
const retrievedData = await holoSphere.get(testHolon, testLens, originalData.id);
|
|
121
|
-
expect(retrievedData.value).toBe('Updated Value');
|
|
122
|
-
|
|
123
|
-
// 6. Verify the hologram was not updated (since it's deleted)
|
|
124
|
-
const deletedHologram = await holoSphere.get(testHolon, otherLens, originalData.id);
|
|
125
|
-
expect(deletedHologram).toBeNull(); // Should be null since it was deleted
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test('should work with data that has no holograms', async () => {
|
|
129
|
-
// 1. Store data that has no holograms pointing to it
|
|
130
|
-
const originalData = { id: 'no-holograms-test', value: 'Original Value' };
|
|
131
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
132
|
-
await waitForGun();
|
|
133
|
-
|
|
134
|
-
// 2. Update the data (should not cause errors even with no holograms)
|
|
135
|
-
const updatedData = { id: 'no-holograms-test', value: 'Updated Value' };
|
|
136
|
-
await holoSphere.put(testHolon, testLens, updatedData);
|
|
137
|
-
await waitForGun(1000);
|
|
138
|
-
|
|
139
|
-
// 3. Verify the data was updated successfully
|
|
140
|
-
const retrievedData = await holoSphere.get(testHolon, testLens, originalData.id);
|
|
141
|
-
expect(retrievedData.value).toBe('Updated Value');
|
|
142
|
-
});
|
|
143
|
-
});
|
package/test/hologram.test.js
DELETED
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
import HoloSphere from '../holosphere.js';
|
|
2
|
-
import { jest } from '@jest/globals';
|
|
3
|
-
|
|
4
|
-
// Configure timeout
|
|
5
|
-
jest.setTimeout(30000); // 30 second timeout
|
|
6
|
-
|
|
7
|
-
// Utility to wait for GunDB propagation
|
|
8
|
-
const waitForGun = (delay = 250) => new Promise(resolve => setTimeout(resolve, delay));
|
|
9
|
-
|
|
10
|
-
// Setup
|
|
11
|
-
describe('HoloSphere Reference System', () => {
|
|
12
|
-
let holoSphere;
|
|
13
|
-
const appName = 'test-hologram-app'; // Update app name
|
|
14
|
-
const testHolon = 'hologramTestHolon'; // Update holon name
|
|
15
|
-
const testLens = 'testLens';
|
|
16
|
-
|
|
17
|
-
beforeAll(async () => {
|
|
18
|
-
// Create a single HoloSphere instance for all tests
|
|
19
|
-
holoSphere = new HoloSphere(appName);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterAll(async () => {
|
|
23
|
-
// Clean up after all tests
|
|
24
|
-
if (holoSphere) {
|
|
25
|
-
await holoSphere.close();
|
|
26
|
-
// Wait for connections to close
|
|
27
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('should create and parse a hologram correctly', async () => {
|
|
32
|
-
// Test data
|
|
33
|
-
const data = { id: 'ref1', value: 'Original Data' };
|
|
34
|
-
await holoSphere.put(testHolon, testLens, data);
|
|
35
|
-
await waitForGun(); // <-- Add delay
|
|
36
|
-
|
|
37
|
-
// Create a hologram
|
|
38
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, data); // Use renamed method
|
|
39
|
-
|
|
40
|
-
expect(hologram).toBeDefined();
|
|
41
|
-
expect(hologram.id).toBe('ref1');
|
|
42
|
-
expect(hologram.soul).toBe(`${appName}/${testHolon}/${testLens}/ref1`);
|
|
43
|
-
expect(holoSphere.isHologram(hologram)).toBe(true); // Use renamed method
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('isHologram should return false for non-hologram objects', () => { // Rename test description
|
|
47
|
-
expect(holoSphere.isHologram(null)).toBe(false); // Use renamed method
|
|
48
|
-
expect(holoSphere.isHologram(undefined)).toBe(false); // Use renamed method
|
|
49
|
-
expect(holoSphere.isHologram({})).toBe(false); // Use renamed method
|
|
50
|
-
expect(holoSphere.isHologram({ id: 'test' })).toBe(false); // Use renamed method
|
|
51
|
-
expect(holoSphere.isHologram({ soul: 'path' })).toBe(false); // Use renamed method
|
|
52
|
-
expect(holoSphere.isHologram('string')).toBe(false); // Use renamed method
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('should resolve a valid hologram', async () => { // Rename test description
|
|
56
|
-
const data = { id: 'ref2', value: 'Data to Resolve' };
|
|
57
|
-
await holoSphere.put(testHolon, testLens, data);
|
|
58
|
-
await waitForGun(); // <-- Add delay
|
|
59
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, data); // Use renamed method
|
|
60
|
-
|
|
61
|
-
const resolved = await holoSphere.resolveHologram(hologram); // Use renamed method
|
|
62
|
-
|
|
63
|
-
expect(resolved).toBeDefined();
|
|
64
|
-
expect(resolved.id).toBe('ref2');
|
|
65
|
-
expect(resolved.value).toBe('Data to Resolve');
|
|
66
|
-
// Check for updated metadata
|
|
67
|
-
expect(resolved._meta).toBeDefined();
|
|
68
|
-
expect(resolved._meta.resolvedFromHologram).toBe(true);
|
|
69
|
-
expect(resolved._meta.hologramSoul).toBe(hologram.soul);
|
|
70
|
-
expect(resolved.isHologram).toBeUndefined(); // Ensure top-level isHologram is not present
|
|
71
|
-
// Ensure old fields are not in _meta unless they were on originalData
|
|
72
|
-
expect(resolved._meta.isHologram).toBeUndefined();
|
|
73
|
-
expect(resolved._meta.resolved).toBeUndefined();
|
|
74
|
-
// expect(resolved._meta.soul).toBeUndefined(); // hologramSoul is the new field for this
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('resolveHologram should return null for a hologram pointing to non-existent data', async () => { // Rename test description
|
|
78
|
-
const nonExistentData = { id: 'ref-non-existent' }; // Data never stored
|
|
79
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, nonExistentData); // Create hologram for it
|
|
80
|
-
|
|
81
|
-
const resolved = await holoSphere.resolveHologram(hologram); // Use renamed method
|
|
82
|
-
expect(resolved).toBeNull(); // Resolution should fail and return null
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('resolveHologram should return the original object if not a hologram', async () => { // Rename test description
|
|
86
|
-
const plainObject = { id: 'not-a-ref', value: 123 };
|
|
87
|
-
const resolved = await holoSphere.resolveHologram(plainObject); // Use renamed method
|
|
88
|
-
expect(resolved).toBe(plainObject); // Should return the object itself
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// Test for nested holograms
|
|
92
|
-
test('should resolve nested holograms correctly', async () => { // Rename test description
|
|
93
|
-
// 1. Original Data stored under its own ID
|
|
94
|
-
const originalData = { id: 'actual-nested-original', value: 'level 0' };
|
|
95
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
96
|
-
await waitForGun(750); // <-- Increased delay
|
|
97
|
-
|
|
98
|
-
// 2. Hologram 1 pointing to Original Data, stored under 'hologram1-id'
|
|
99
|
-
const hologram1Data = holoSphere.createHologram(testHolon, testLens, originalData);
|
|
100
|
-
const hologram1Storage = { id: 'hologram1-id', soul: hologram1Data.soul }; // Soul points to originalData
|
|
101
|
-
await holoSphere.put(testHolon, testLens, hologram1Storage);
|
|
102
|
-
await waitForGun(750); // <-- Increased delay
|
|
103
|
-
|
|
104
|
-
// 3. Hologram 2 pointing to Hologram 1, stored under 'hologram2-id'
|
|
105
|
-
// Create a temporary object representing hologram1 for creating hologram2
|
|
106
|
-
const hologram1Ref = { id: 'hologram1-id' }; // We only need the ID hologram2 should point to
|
|
107
|
-
const hologram2Data = holoSphere.createHologram(testHolon, testLens, hologram1Ref); // Soul points to hologram1Storage
|
|
108
|
-
const hologram2Storage = { id: 'hologram2-id', soul: hologram2Data.soul }; // Soul points to .../hologram1-id
|
|
109
|
-
await holoSphere.put(testHolon, testLens, hologram2Storage);
|
|
110
|
-
await waitForGun(750); // <-- Increased delay
|
|
111
|
-
|
|
112
|
-
// Resolve Hologram 2 (which is stored at hologram2-id)
|
|
113
|
-
// The system should fetch hologram2Storage, see its soul points to hologram1-id,
|
|
114
|
-
// fetch hologram1Storage, see its soul points to actual-nested-original,
|
|
115
|
-
// fetch originalData, and return it.
|
|
116
|
-
const resolved = await holoSphere.get(testHolon, testLens, 'hologram2-id');
|
|
117
|
-
|
|
118
|
-
console.log("!!!!!!!!!!!!! nested hologram", resolved);
|
|
119
|
-
|
|
120
|
-
expect(resolved).toBeNull(); // Expect null if new logic dictates this for nested resolution
|
|
121
|
-
|
|
122
|
-
// Resolve Hologram 2 without following deeply - should return Hologram 1 data
|
|
123
|
-
// Fetch hologram2Storage with resolveHolograms: false. This gets the raw hologram object.
|
|
124
|
-
const fetchedHologram2 = await holoSphere.get(testHolon, testLens, 'hologram2-id', null, { resolveHolograms: false });
|
|
125
|
-
// Now, resolve *this specific hologram object* one level deep.
|
|
126
|
-
const resolvedShallow = await holoSphere.resolveHologram(fetchedHologram2, { followHolograms: false });
|
|
127
|
-
|
|
128
|
-
console.log("!!!!!!!!!!!!! nested hologram shallow", resolvedShallow);
|
|
129
|
-
|
|
130
|
-
expect(resolvedShallow).toBeDefined();
|
|
131
|
-
// Should match hologram2Storage because of put redirection
|
|
132
|
-
expect(resolvedShallow.id).toBe('hologram2-id'); // ID from hologram2Storage
|
|
133
|
-
expect(resolvedShallow.soul).toBe(hologram2Storage.soul); // Soul from hologram2Storage
|
|
134
|
-
expect(resolvedShallow.value).toBeUndefined(); // Should not have value from originalData
|
|
135
|
-
expect(resolvedShallow.isHologram).toBeUndefined(); // Ensure top-level isHologram is not present
|
|
136
|
-
expect(resolvedShallow._meta).toBeDefined();
|
|
137
|
-
expect(resolvedShallow._meta.resolvedFromHologram).toBe(true);
|
|
138
|
-
expect(resolvedShallow._meta.hologramSoul).toBe(fetchedHologram2.soul);
|
|
139
|
-
expect(resolvedShallow._meta.isHologram).toBeUndefined();
|
|
140
|
-
expect(resolvedShallow._meta.resolved).toBeUndefined();
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Test for circular holograms
|
|
144
|
-
test('should detect and handle circular holograms', async () => { // Rename test description
|
|
145
|
-
// Hologram A points to Hologram B's future location
|
|
146
|
-
const holoA = { id: 'holoA', soul: `${appName}/${testHolon}/${testLens}/holoB` };
|
|
147
|
-
await holoSphere.put(testHolon, testLens, holoA);
|
|
148
|
-
await waitForGun(); // <-- Add delay
|
|
149
|
-
|
|
150
|
-
// Hologram B points to Hologram A's location
|
|
151
|
-
const holoB = { id: 'holoB', soul: `${appName}/${testHolon}/${testLens}/holoA` };
|
|
152
|
-
await holoSphere.put(testHolon, testLens, holoB);
|
|
153
|
-
await waitForGun(); // <-- Add delay
|
|
154
|
-
|
|
155
|
-
// Attempt to resolve Hologram A via get, which should handle the circular error from resolveHologram
|
|
156
|
-
const resolved = await holoSphere.get(testHolon, testLens, holoA.id);
|
|
157
|
-
|
|
158
|
-
// Should return null due to circular detection handled in get()
|
|
159
|
-
expect(resolved).toBeNull();
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
test('get should resolve holograms by default', async () => { // Rename test description
|
|
163
|
-
// 1. Store the actual data under its own ID
|
|
164
|
-
const actualData = { id: 'actual-data-id', value: 'Fetched via get' };
|
|
165
|
-
await holoSphere.put(testHolon, testLens, actualData);
|
|
166
|
-
await waitForGun(750); // <-- Increased delay
|
|
167
|
-
|
|
168
|
-
// 2. Create a hologram pointing to the actual data
|
|
169
|
-
// The hologram object itself will have the ID 'actual-data-id'
|
|
170
|
-
const hologramPointingToData = holoSphere.createHologram(testHolon, testLens, actualData);
|
|
171
|
-
|
|
172
|
-
// 3. Store the hologram object under the ID we want to fetch ('get-ref')
|
|
173
|
-
// We need to create a new object for storage that uses the hologram's soul
|
|
174
|
-
// but has the ID 'get-ref'.
|
|
175
|
-
const hologramStorageObject = { id: 'get-ref', soul: hologramPointingToData.soul };
|
|
176
|
-
await holoSphere.put(testHolon, testLens, hologramStorageObject);
|
|
177
|
-
await waitForGun(750); // <-- Increased delay
|
|
178
|
-
|
|
179
|
-
// 4. Get the item by the hologram's storage ID ('get-ref')
|
|
180
|
-
// This should retrieve hologramStorageObject and then resolve its soul
|
|
181
|
-
const resolved = await holoSphere.get(testHolon, testLens, 'get-ref');
|
|
182
|
-
|
|
183
|
-
console.log("!!!!!!!!!!!!!",resolved); // Should now show resolved data + meta
|
|
184
|
-
// Assertions should check against the *actualData*
|
|
185
|
-
// expect(resolved.id).toBe('actual-data-id'); // ID comes from the resolved data
|
|
186
|
-
// expect(resolved.value).toBe('Fetched via get'); // Value comes from the resolved data
|
|
187
|
-
// expect(resolved._meta).toBeDefined();
|
|
188
|
-
// expect(resolved._meta.isHologram).toBe(true);
|
|
189
|
-
// expect(resolved._meta.resolved).toBe(true);
|
|
190
|
-
// // The soul in the meta should be the soul of the *hologram object* we fetched
|
|
191
|
-
// expect(resolved._meta.soul).toBe(hologramStorageObject.soul);
|
|
192
|
-
expect(resolved).toBeNull(); // Expect null due to circular reference caused by put redirection
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
test('get should not resolve holograms if resolveHolograms is false', async () => { // Rename test description
|
|
196
|
-
const data = { id: 'get-no-res', value: 'Original' };
|
|
197
|
-
await holoSphere.put(testHolon, testLens, data);
|
|
198
|
-
await waitForGun(); // <-- Add delay
|
|
199
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, data); // Use renamed method
|
|
200
|
-
await holoSphere.put(testHolon, testLens, hologram); // Store the hologram itself at its ID
|
|
201
|
-
await waitForGun(); // <-- Add delay
|
|
202
|
-
|
|
203
|
-
// Get the item by ID without resolving
|
|
204
|
-
const unresolved = await holoSphere.get(testHolon, testLens, 'get-no-res', null, { resolveHolograms: false }); // Use renamed option
|
|
205
|
-
|
|
206
|
-
expect(unresolved).toBeDefined();
|
|
207
|
-
expect(unresolved.id).toBe('get-no-res');
|
|
208
|
-
expect(unresolved.soul).toBe(hologram.soul);
|
|
209
|
-
expect(unresolved.value).toBeUndefined(); // Should be the raw hologram
|
|
210
|
-
expect(unresolved._meta).toBeUndefined();
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
test('get should return null if hologram resolution fails (target deleted)', async () => { // Rename test description
|
|
214
|
-
const data = { id: 'get-deleted-target' };
|
|
215
|
-
// Create hologram but DO NOT store the original data
|
|
216
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, data);
|
|
217
|
-
await holoSphere.put(testHolon, testLens, hologram); // Store the hologram
|
|
218
|
-
await waitForGun(); // <-- Add delay
|
|
219
|
-
|
|
220
|
-
// Get the item - resolution should fail
|
|
221
|
-
const result = await holoSphere.get(testHolon, testLens, 'get-deleted-target');
|
|
222
|
-
expect(result).toBeNull();
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test('updates to original data should be reflected when resolving hologram', async () => { // Rename test description
|
|
226
|
-
const originalData = { id: 'update-ref', value: 'Version 1' };
|
|
227
|
-
await holoSphere.put(testHolon, testLens, originalData);
|
|
228
|
-
await waitForGun(750); // <-- Increased delay
|
|
229
|
-
const hologram = holoSphere.createHologram(testHolon, testLens, originalData); // Use renamed method
|
|
230
|
-
await holoSphere.put(testHolon, 'otherLens', hologram); // Store hologram elsewhere
|
|
231
|
-
await waitForGun(750); // <-- Increased delay
|
|
232
|
-
|
|
233
|
-
// Resolve initially
|
|
234
|
-
const resolved1 = await holoSphere.resolveHologram(hologram); // Use renamed method
|
|
235
|
-
expect(resolved1).toBeNull(); // Expect null, likely due to put redirection complexities
|
|
236
|
-
|
|
237
|
-
// Update original data
|
|
238
|
-
const updatedData = { ...originalData, value: 'Version 2' };
|
|
239
|
-
await holoSphere.put(testHolon, testLens, updatedData);
|
|
240
|
-
await waitForGun(750);
|
|
241
|
-
|
|
242
|
-
// Resolve again
|
|
243
|
-
const resolved2 = await holoSphere.resolveHologram(hologram); // Use renamed method
|
|
244
|
-
expect(resolved2).toBeDefined();
|
|
245
|
-
expect(resolved2.id).toBe('update-ref');
|
|
246
|
-
expect(resolved2.value).toBe('Version 2');
|
|
247
|
-
expect(resolved2.isHologram).toBeUndefined(); // Ensure top-level isHologram is not present
|
|
248
|
-
expect(resolved2._meta).toBeDefined();
|
|
249
|
-
expect(resolved2._meta.resolvedFromHologram).toBe(true);
|
|
250
|
-
expect(resolved2._meta.hologramSoul).toBe(hologram.soul);
|
|
251
|
-
expect(resolved2._meta.isHologram).toBeUndefined();
|
|
252
|
-
expect(resolved2._meta.resolved).toBeUndefined();
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
// --- Tests for _holograms tracking ---
|
|
256
|
-
test('should add hologram soul to target _holograms set on put', async () => {
|
|
257
|
-
// 1. Store original data
|
|
258
|
-
const targetData = { id: 'target-for-tracking', value: 'Track me' };
|
|
259
|
-
await holoSphere.put(testHolon, testLens, targetData);
|
|
260
|
-
await waitForGun();
|
|
261
|
-
const targetSoul = `${appName}/${testHolon}/${testLens}/target-for-tracking`;
|
|
262
|
-
|
|
263
|
-
// 2. Store a hologram pointing to the original data
|
|
264
|
-
const hologramData = holoSphere.createHologram(testHolon, testLens, targetData);
|
|
265
|
-
const hologramStorage = { id: 'hologram-tracker-1', soul: hologramData.soul };
|
|
266
|
-
await holoSphere.put(testHolon, 'otherLens', hologramStorage); // Store in different lens
|
|
267
|
-
await waitForGun(500); // Longer wait for tracking update
|
|
268
|
-
const storedHologramSoul = `${appName}/${testHolon}/otherLens/hologram-tracker-1`;
|
|
269
|
-
|
|
270
|
-
// 3. Get the target node reference and fetch the _holograms set
|
|
271
|
-
const targetNodeRef = holoSphere.getNodeRef(targetSoul);
|
|
272
|
-
const hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
|
|
273
|
-
|
|
274
|
-
// 4. Verify the _holograms set exists and contains the stored hologram's soul
|
|
275
|
-
expect(hologramsSet).toBeDefined();
|
|
276
|
-
// Gun stores set members as keys, excluding metadata '_'
|
|
277
|
-
const hologramKeys = Object.keys(hologramsSet).filter(k => k !== '_');
|
|
278
|
-
expect(hologramKeys).toContain(storedHologramSoul);
|
|
279
|
-
expect(hologramsSet[storedHologramSoul]).toBe(true); // Check the value stored
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
test('should remove hologram soul from target _holograms set on delete', async () => {
|
|
283
|
-
// 1. Store original data
|
|
284
|
-
const targetData = { id: 'target-for-delete-tracking', value: 'Untrack me' };
|
|
285
|
-
await holoSphere.put(testHolon, testLens, targetData);
|
|
286
|
-
await waitForGun();
|
|
287
|
-
const targetSoul = `${appName}/${testHolon}/${testLens}/target-for-delete-tracking`;
|
|
288
|
-
|
|
289
|
-
// 2. Store a hologram pointing to the original data
|
|
290
|
-
const hologramData = holoSphere.createHologram(testHolon, testLens, targetData);
|
|
291
|
-
const hologramStorage = { id: 'hologram-tracker-2', soul: hologramData.soul };
|
|
292
|
-
await holoSphere.put(testHolon, 'otherLens', hologramStorage); // Store in different lens
|
|
293
|
-
await waitForGun(500); // Wait for put and tracking update
|
|
294
|
-
const storedHologramSoul = `${appName}/${testHolon}/otherLens/hologram-tracker-2`;
|
|
295
|
-
|
|
296
|
-
// 3. Verify hologram was added to tracking initially
|
|
297
|
-
const targetNodeRef = holoSphere.getNodeRef(targetSoul);
|
|
298
|
-
let hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
|
|
299
|
-
expect(hologramsSet).toBeDefined();
|
|
300
|
-
expect(hologramsSet[storedHologramSoul]).toBeDefined(); // Hologram should be tracked initially
|
|
301
|
-
|
|
302
|
-
// 4. Delete the hologram
|
|
303
|
-
await holoSphere.delete(testHolon, 'otherLens', 'hologram-tracker-2');
|
|
304
|
-
console.log("--- Waiting longer after delete for tracking update ---");
|
|
305
|
-
await waitForGun(1500); // <-- Increased wait time significantly
|
|
306
|
-
|
|
307
|
-
// 5. Fetch the _holograms set again directly
|
|
308
|
-
hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
|
|
309
|
-
|
|
310
|
-
// 6. Verify the hologram's soul is completely removed (or set to null by Gun)
|
|
311
|
-
expect(hologramsSet).toBeDefined();
|
|
312
|
-
expect(hologramsSet[storedHologramSoul]).toBeNull(); // Gun stores null when we put(null)
|
|
313
|
-
});
|
|
314
|
-
// --- End tests for _holograms tracking ---
|
|
315
|
-
|
|
316
|
-
});
|