holosphere 2.0.0-alpha0 → 2.0.0-alpha2
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/LICENSE +162 -38
- package/dist/cjs/holosphere.cjs +2 -0
- package/dist/cjs/holosphere.cjs.map +1 -0
- package/dist/esm/holosphere.js +56 -0
- package/dist/esm/holosphere.js.map +1 -0
- package/dist/index-CDfIuXew.js +15974 -0
- package/dist/index-CDfIuXew.js.map +1 -0
- package/dist/index-ifOgtDvd.cjs +3 -0
- package/dist/index-ifOgtDvd.cjs.map +1 -0
- package/dist/indexeddb-storage-CMW4qRQS.js +96 -0
- package/dist/indexeddb-storage-CMW4qRQS.js.map +1 -0
- package/dist/indexeddb-storage-DLZOgetM.cjs +2 -0
- package/dist/indexeddb-storage-DLZOgetM.cjs.map +1 -0
- package/dist/memory-storage-DQzcAZlf.js +47 -0
- package/dist/memory-storage-DQzcAZlf.js.map +1 -0
- package/dist/memory-storage-DmePEP2q.cjs +2 -0
- package/dist/memory-storage-DmePEP2q.cjs.map +1 -0
- package/dist/secp256k1-CP0ZkpAx.cjs +13 -0
- package/dist/secp256k1-CP0ZkpAx.cjs.map +1 -0
- package/dist/secp256k1-vOXp40Fx.js +2281 -0
- package/dist/secp256k1-vOXp40Fx.js.map +1 -0
- package/docs/FOSDEM_PROPOSAL.md +388 -0
- package/docs/LOCALFIRST.md +266 -0
- package/docs/contracts/api-interface.md +793 -0
- package/docs/data-model.md +476 -0
- package/docs/gun-async-usage.md +338 -0
- package/docs/plan.md +349 -0
- package/docs/quickstart.md +674 -0
- package/docs/research.md +362 -0
- package/docs/spec.md +244 -0
- package/docs/storage-backends.md +326 -0
- package/docs/tasks.md +947 -0
- package/package.json +1 -1
- package/tests/unit/ai/aggregation.test.js +0 -295
- package/tests/unit/ai/breakdown.test.js +0 -446
- package/tests/unit/ai/classifier.test.js +0 -294
- package/tests/unit/ai/council.test.js +0 -262
- package/tests/unit/ai/embeddings.test.js +0 -384
- package/tests/unit/ai/federation-ai.test.js +0 -344
- package/tests/unit/ai/h3-ai.test.js +0 -458
- package/tests/unit/ai/index.test.js +0 -304
- package/tests/unit/ai/json-ops.test.js +0 -307
- package/tests/unit/ai/llm-service.test.js +0 -390
- package/tests/unit/ai/nl-query.test.js +0 -383
- package/tests/unit/ai/relationships.test.js +0 -311
- package/tests/unit/ai/schema-extractor.test.js +0 -384
- package/tests/unit/ai/spatial.test.js +0 -279
- package/tests/unit/ai/tts.test.js +0 -279
- package/tests/unit/content.test.js +0 -332
- package/tests/unit/contract/core.test.js +0 -88
- package/tests/unit/contract/crypto.test.js +0 -198
- package/tests/unit/contract/data.test.js +0 -223
- package/tests/unit/contract/federation.test.js +0 -181
- package/tests/unit/contract/hierarchical.test.js +0 -113
- package/tests/unit/contract/schema.test.js +0 -114
- package/tests/unit/contract/social.test.js +0 -217
- package/tests/unit/contract/spatial.test.js +0 -110
- package/tests/unit/contract/subscriptions.test.js +0 -128
- package/tests/unit/contract/utils.test.js +0 -159
- package/tests/unit/core.test.js +0 -152
- package/tests/unit/crypto.test.js +0 -328
- package/tests/unit/federation.test.js +0 -234
- package/tests/unit/gun-async.test.js +0 -252
- package/tests/unit/hierarchical.test.js +0 -399
- package/tests/unit/integration/scenario-01-geographic-storage.test.js +0 -74
- package/tests/unit/integration/scenario-02-federation.test.js +0 -76
- package/tests/unit/integration/scenario-03-subscriptions.test.js +0 -102
- package/tests/unit/integration/scenario-04-validation.test.js +0 -129
- package/tests/unit/integration/scenario-05-hierarchy.test.js +0 -125
- package/tests/unit/integration/scenario-06-social.test.js +0 -135
- package/tests/unit/integration/scenario-07-persistence.test.js +0 -130
- package/tests/unit/integration/scenario-08-authorization.test.js +0 -161
- package/tests/unit/integration/scenario-09-cross-dimensional.test.js +0 -139
- package/tests/unit/integration/scenario-10-cross-holosphere-capabilities.test.js +0 -357
- package/tests/unit/integration/scenario-11-cross-holosphere-federation.test.js +0 -410
- package/tests/unit/integration/scenario-12-capability-federated-read.test.js +0 -719
- package/tests/unit/performance/benchmark.test.js +0 -85
- package/tests/unit/schema.test.js +0 -213
- package/tests/unit/spatial.test.js +0 -158
- package/tests/unit/storage.test.js +0 -195
- package/tests/unit/subscriptions.test.js +0 -328
- package/tests/unit/test-data-permanence-debug.js +0 -197
- package/tests/unit/test-data-permanence.js +0 -340
- package/tests/unit/test-key-persistence-fixed.js +0 -148
- package/tests/unit/test-key-persistence.js +0 -172
- package/tests/unit/test-relay-permanence.js +0 -376
- package/tests/unit/test-second-node.js +0 -95
- package/tests/unit/test-simple-write.js +0 -89
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
-
import HoloSphere from '../../src/index.js';
|
|
3
|
-
|
|
4
|
-
describe('Unit: Subscriptions Module', () => {
|
|
5
|
-
let hs;
|
|
6
|
-
let testHolonId;
|
|
7
|
-
|
|
8
|
-
beforeEach(async () => {
|
|
9
|
-
hs = new HoloSphere({ relays: [], appName: 'test-subscriptions-unit' });
|
|
10
|
-
testHolonId = await hs.toHolon(37.7749, -122.4194, 9);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
describe('Gun .on() listener attachment', () => {
|
|
14
|
-
it('should attach Gun listener on subscribe', () => {
|
|
15
|
-
const callback = vi.fn();
|
|
16
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
17
|
-
|
|
18
|
-
expect(subscription).toHaveProperty('unsubscribe');
|
|
19
|
-
expect(typeof subscription.unsubscribe).toBe('function');
|
|
20
|
-
|
|
21
|
-
subscription.unsubscribe();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should attach listener for specific holon and lens', () => {
|
|
25
|
-
const callback = vi.fn();
|
|
26
|
-
const subscription = hs.subscribe(testHolonId, 'specific-lens', callback);
|
|
27
|
-
|
|
28
|
-
expect(subscription).toBeDefined();
|
|
29
|
-
subscription.unsubscribe();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should support multiple subscriptions to same holon/lens', () => {
|
|
33
|
-
const callback1 = vi.fn();
|
|
34
|
-
const callback2 = vi.fn();
|
|
35
|
-
|
|
36
|
-
const sub1 = hs.subscribe(testHolonId, 'test', callback1);
|
|
37
|
-
const sub2 = hs.subscribe(testHolonId, 'test', callback2);
|
|
38
|
-
|
|
39
|
-
expect(sub1).toBeDefined();
|
|
40
|
-
expect(sub2).toBeDefined();
|
|
41
|
-
|
|
42
|
-
sub1.unsubscribe();
|
|
43
|
-
sub2.unsubscribe();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('should support subscriptions to different lenses', () => {
|
|
47
|
-
const callback1 = vi.fn();
|
|
48
|
-
const callback2 = vi.fn();
|
|
49
|
-
|
|
50
|
-
const sub1 = hs.subscribe(testHolonId, 'lens1', callback1);
|
|
51
|
-
const sub2 = hs.subscribe(testHolonId, 'lens2', callback2);
|
|
52
|
-
|
|
53
|
-
expect(sub1).toBeDefined();
|
|
54
|
-
expect(sub2).toBeDefined();
|
|
55
|
-
|
|
56
|
-
sub1.unsubscribe();
|
|
57
|
-
sub2.unsubscribe();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('Callback invocation on data changes', () => {
|
|
62
|
-
it('should invoke callback on write', async () => {
|
|
63
|
-
const callback = vi.fn();
|
|
64
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
65
|
-
|
|
66
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'data' });
|
|
67
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
68
|
-
|
|
69
|
-
expect(callback).toHaveBeenCalled();
|
|
70
|
-
subscription.unsubscribe();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should invoke callback on update', async () => {
|
|
74
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'original' });
|
|
75
|
-
|
|
76
|
-
const callback = vi.fn();
|
|
77
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
78
|
-
|
|
79
|
-
await hs.update(testHolonId, 'test', 'item-1', { value: 'updated' });
|
|
80
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
81
|
-
|
|
82
|
-
expect(callback).toHaveBeenCalled();
|
|
83
|
-
subscription.unsubscribe();
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should pass data to callback', async () => {
|
|
87
|
-
const callback = vi.fn();
|
|
88
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
89
|
-
|
|
90
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'test-data' });
|
|
91
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
92
|
-
|
|
93
|
-
expect(callback).toHaveBeenCalledWith(
|
|
94
|
-
expect.objectContaining({ id: 'item-1', value: 'test-data' }),
|
|
95
|
-
expect.any(String)
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
subscription.unsubscribe();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should pass key to callback', async () => {
|
|
102
|
-
const callback = vi.fn();
|
|
103
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
104
|
-
|
|
105
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'data' });
|
|
106
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
107
|
-
|
|
108
|
-
expect(callback).toHaveBeenCalledWith(
|
|
109
|
-
expect.any(Object),
|
|
110
|
-
expect.any(String)
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
subscription.unsubscribe();
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('should not invoke callback on other lens changes', async () => {
|
|
117
|
-
const callback = vi.fn();
|
|
118
|
-
const subscription = hs.subscribe(testHolonId, 'lens-a', callback);
|
|
119
|
-
|
|
120
|
-
await hs.write(testHolonId, 'lens-b', { id: 'item-1', value: 'data' });
|
|
121
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
122
|
-
|
|
123
|
-
expect(callback).not.toHaveBeenCalled();
|
|
124
|
-
subscription.unsubscribe();
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe('Throttling mechanism', () => {
|
|
129
|
-
it('should throttle callbacks when throttle option provided', async () => {
|
|
130
|
-
const callback = vi.fn();
|
|
131
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback, {
|
|
132
|
-
throttle: 500 // 500ms throttle
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// Rapid writes
|
|
136
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'v1' });
|
|
137
|
-
await hs.write(testHolonId, 'test', { id: 'item-2', value: 'v2' });
|
|
138
|
-
await hs.write(testHolonId, 'test', { id: 'item-3', value: 'v3' });
|
|
139
|
-
|
|
140
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
141
|
-
|
|
142
|
-
// Should be throttled (fewer calls than writes)
|
|
143
|
-
const callCount = callback.mock.calls.length;
|
|
144
|
-
expect(callCount).toBeLessThan(3);
|
|
145
|
-
|
|
146
|
-
subscription.unsubscribe();
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('should not throttle when throttle is 0', async () => {
|
|
150
|
-
const callback = vi.fn();
|
|
151
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback, {
|
|
152
|
-
throttle: 0
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'v1' });
|
|
156
|
-
await hs.write(testHolonId, 'test', { id: 'item-2', value: 'v2' });
|
|
157
|
-
|
|
158
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
159
|
-
|
|
160
|
-
expect(callback.mock.calls.length).toBeGreaterThanOrEqual(2);
|
|
161
|
-
subscription.unsubscribe();
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('should respect throttle interval', async () => {
|
|
165
|
-
const callback = vi.fn();
|
|
166
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback, {
|
|
167
|
-
throttle: 200
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'v1' });
|
|
171
|
-
await new Promise(resolve => setTimeout(resolve, 50));
|
|
172
|
-
await hs.write(testHolonId, 'test', { id: 'item-2', value: 'v2' });
|
|
173
|
-
await new Promise(resolve => setTimeout(resolve, 250));
|
|
174
|
-
|
|
175
|
-
// After throttle period, should allow next callback
|
|
176
|
-
expect(callback.mock.calls.length).toBeGreaterThan(0);
|
|
177
|
-
subscription.unsubscribe();
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
describe('Filter predicate application', () => {
|
|
182
|
-
it('should apply filter function', async () => {
|
|
183
|
-
const callback = vi.fn();
|
|
184
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback, {
|
|
185
|
-
filter: (data) => data.value > 10
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 5 });
|
|
189
|
-
await hs.write(testHolonId, 'test', { id: 'item-2', value: 15 });
|
|
190
|
-
|
|
191
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
192
|
-
|
|
193
|
-
// Only item-2 should pass filter
|
|
194
|
-
const calls = callback.mock.calls;
|
|
195
|
-
const passedFilter = calls.some(call => call[0].value === 15);
|
|
196
|
-
const failedFilter = calls.some(call => call[0].value === 5);
|
|
197
|
-
|
|
198
|
-
expect(passedFilter).toBe(true);
|
|
199
|
-
expect(failedFilter).toBe(false);
|
|
200
|
-
|
|
201
|
-
subscription.unsubscribe();
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it('should invoke callback only for data matching filter', async () => {
|
|
205
|
-
const callback = vi.fn();
|
|
206
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback, {
|
|
207
|
-
filter: (data) => data.priority === 'high'
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', priority: 'low' });
|
|
211
|
-
await hs.write(testHolonId, 'test', { id: 'item-2', priority: 'high' });
|
|
212
|
-
await hs.write(testHolonId, 'test', { id: 'item-3', priority: 'medium' });
|
|
213
|
-
|
|
214
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
215
|
-
|
|
216
|
-
const highPriorityCalls = callback.mock.calls.filter(
|
|
217
|
-
call => call[0].priority === 'high'
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
expect(highPriorityCalls.length).toBeGreaterThan(0);
|
|
221
|
-
subscription.unsubscribe();
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('should pass all data when no filter provided', async () => {
|
|
225
|
-
const callback = vi.fn();
|
|
226
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
227
|
-
|
|
228
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'a' });
|
|
229
|
-
await hs.write(testHolonId, 'test', { id: 'item-2', value: 'b' });
|
|
230
|
-
|
|
231
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
232
|
-
|
|
233
|
-
expect(callback.mock.calls.length).toBeGreaterThanOrEqual(2);
|
|
234
|
-
subscription.unsubscribe();
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
describe('Unsubscribe cleanup', () => {
|
|
239
|
-
it('should stop callbacks after unsubscribe', async () => {
|
|
240
|
-
const callback = vi.fn();
|
|
241
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
242
|
-
|
|
243
|
-
subscription.unsubscribe();
|
|
244
|
-
|
|
245
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'data' });
|
|
246
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
247
|
-
|
|
248
|
-
expect(callback).not.toHaveBeenCalled();
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it('should remove Gun listener on unsubscribe', async () => {
|
|
252
|
-
const callback = vi.fn();
|
|
253
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
254
|
-
|
|
255
|
-
await hs.write(testHolonId, 'test', { id: 'before', value: 'before' });
|
|
256
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
257
|
-
|
|
258
|
-
const beforeCount = callback.mock.calls.length;
|
|
259
|
-
|
|
260
|
-
subscription.unsubscribe();
|
|
261
|
-
|
|
262
|
-
await hs.write(testHolonId, 'test', { id: 'after', value: 'after' });
|
|
263
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
264
|
-
|
|
265
|
-
expect(callback.mock.calls.length).toBe(beforeCount);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('should handle multiple unsubscribe calls gracefully', () => {
|
|
269
|
-
const callback = vi.fn();
|
|
270
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback);
|
|
271
|
-
|
|
272
|
-
subscription.unsubscribe();
|
|
273
|
-
subscription.unsubscribe();
|
|
274
|
-
subscription.unsubscribe();
|
|
275
|
-
|
|
276
|
-
// Should not throw error
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it('should cleanup individual subscriptions independently', async () => {
|
|
280
|
-
const callback1 = vi.fn();
|
|
281
|
-
const callback2 = vi.fn();
|
|
282
|
-
|
|
283
|
-
const sub1 = hs.subscribe(testHolonId, 'test', callback1);
|
|
284
|
-
const sub2 = hs.subscribe(testHolonId, 'test', callback2);
|
|
285
|
-
|
|
286
|
-
sub1.unsubscribe();
|
|
287
|
-
|
|
288
|
-
// Small delay to ensure unsubscribe is fully processed
|
|
289
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
290
|
-
|
|
291
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 'data' });
|
|
292
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
293
|
-
|
|
294
|
-
expect(callback1).not.toHaveBeenCalled();
|
|
295
|
-
expect(callback2).toHaveBeenCalled();
|
|
296
|
-
|
|
297
|
-
sub2.unsubscribe();
|
|
298
|
-
});
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
describe('Subscription options', () => {
|
|
302
|
-
it('should accept includeFederated option', () => {
|
|
303
|
-
const callback = vi.fn();
|
|
304
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback, {
|
|
305
|
-
includeFederated: true
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
expect(subscription).toBeDefined();
|
|
309
|
-
subscription.unsubscribe();
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
it('should combine throttle and filter options', async () => {
|
|
313
|
-
const callback = vi.fn();
|
|
314
|
-
const subscription = hs.subscribe(testHolonId, 'test', callback, {
|
|
315
|
-
throttle: 100,
|
|
316
|
-
filter: (data) => data.value > 5
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
await hs.write(testHolonId, 'test', { id: 'item-1', value: 3 });
|
|
320
|
-
await hs.write(testHolonId, 'test', { id: 'item-2', value: 10 });
|
|
321
|
-
|
|
322
|
-
await new Promise(resolve => setTimeout(resolve, 200));
|
|
323
|
-
|
|
324
|
-
expect(callback.mock.calls.length).toBeGreaterThan(0);
|
|
325
|
-
subscription.unsubscribe();
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
});
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Debug Data Permanence Test
|
|
3
|
-
* Helps identify where in the stack data flow is breaking
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { HoloSphere } from './dist/esm/holosphere.js';
|
|
7
|
-
|
|
8
|
-
// Relay configuration - use env vars or these defaults
|
|
9
|
-
const RELAYS = process.env.HOLOSPHERE_RELAYS?.split(',') || [
|
|
10
|
-
'wss://relay.holons.io',
|
|
11
|
-
'wss://relay.nostr.band',
|
|
12
|
-
];
|
|
13
|
-
|
|
14
|
-
console.log('\n=== DATA PERMANENCE DEBUG TEST ===\n');
|
|
15
|
-
|
|
16
|
-
const config = {
|
|
17
|
-
appName: 'debug-test',
|
|
18
|
-
relays: RELAYS,
|
|
19
|
-
logLevel: 'DEBUG' // More verbose logging
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
console.log('Configuration:', JSON.stringify(config, null, 2));
|
|
23
|
-
|
|
24
|
-
const hs = new HoloSphere(config);
|
|
25
|
-
|
|
26
|
-
console.log(`\nInitialized HoloSphere`);
|
|
27
|
-
console.log(`Public Key: ${hs.client.publicKey}`);
|
|
28
|
-
console.log(`Private Key (first 8 chars): ${hs.client.privateKey.substring(0, 8)}...`);
|
|
29
|
-
console.log(`Relays: ${config.relays.join(', ')}`);
|
|
30
|
-
|
|
31
|
-
// Wait for initialization
|
|
32
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
33
|
-
|
|
34
|
-
console.log('\n--- TEST 1: Write and immediate read ---');
|
|
35
|
-
|
|
36
|
-
const testData = {
|
|
37
|
-
id: 'test-123',
|
|
38
|
-
message: 'Hello, world!',
|
|
39
|
-
timestamp: Date.now()
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const holonId = 'global://test';
|
|
43
|
-
const lensName = 'data';
|
|
44
|
-
|
|
45
|
-
console.log(`\nWriting data:`);
|
|
46
|
-
console.log(` Holon: ${holonId}`);
|
|
47
|
-
console.log(` Lens: ${lensName}`);
|
|
48
|
-
console.log(` Data:`, JSON.stringify(testData, null, 2));
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
const writeResult = await hs.write(holonId, lensName, testData);
|
|
52
|
-
console.log(`\nWrite result: ${writeResult}`);
|
|
53
|
-
|
|
54
|
-
if (!writeResult) {
|
|
55
|
-
console.log('\n❌ Write failed - checking client state...');
|
|
56
|
-
console.log(`Client has ${hs.client._eventCache.size} cached events`);
|
|
57
|
-
}
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error('\n❌ Write error:', error);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
console.log('\n--- Checking client cache ---');
|
|
63
|
-
console.log(`Cache size: ${hs.client._eventCache.size}`);
|
|
64
|
-
|
|
65
|
-
// Print cache contents
|
|
66
|
-
let cacheIndex = 0;
|
|
67
|
-
for (const [key, value] of hs.client._eventCache.entries()) {
|
|
68
|
-
console.log(`\nCache entry ${++cacheIndex}:`);
|
|
69
|
-
console.log(` Key: ${key}`);
|
|
70
|
-
console.log(` Value:`, JSON.stringify(value, null, 2));
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
console.log('\n--- Checking persistent storage ---');
|
|
74
|
-
if (hs.client.persistentStorage) {
|
|
75
|
-
try {
|
|
76
|
-
const allEvents = await hs.client.persistentStorage.getAll('');
|
|
77
|
-
console.log(`Persistent storage has ${allEvents.length} events`);
|
|
78
|
-
|
|
79
|
-
for (let i = 0; i < allEvents.length; i++) {
|
|
80
|
-
const event = allEvents[i];
|
|
81
|
-
console.log(`\nEvent ${i + 1}:`);
|
|
82
|
-
console.log(` ID: ${event.id}`);
|
|
83
|
-
console.log(` Kind: ${event.kind}`);
|
|
84
|
-
console.log(` Created: ${new Date(event.created_at * 1000).toISOString()}`);
|
|
85
|
-
const dTag = event.tags.find(t => t[0] === 'd');
|
|
86
|
-
if (dTag) console.log(` D-tag: ${dTag[1]}`);
|
|
87
|
-
console.log(` Content preview: ${event.content.substring(0, 100)}...`);
|
|
88
|
-
}
|
|
89
|
-
} catch (error) {
|
|
90
|
-
console.log('Error reading persistent storage:', error);
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
console.log('No persistent storage initialized');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
console.log('\n--- TEST 2: Read data back ---');
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
console.log(`\nReading from:`);
|
|
100
|
-
console.log(` Holon: ${holonId}`);
|
|
101
|
-
console.log(` Lens: ${lensName}`);
|
|
102
|
-
|
|
103
|
-
const readData = await hs.read(holonId, lensName);
|
|
104
|
-
|
|
105
|
-
console.log(`\nRead result:`, JSON.stringify(readData, null, 2));
|
|
106
|
-
|
|
107
|
-
if (!readData || readData.length === 0) {
|
|
108
|
-
console.log('\n❌ No data returned');
|
|
109
|
-
|
|
110
|
-
// Try to understand why
|
|
111
|
-
console.log('\n--- Debugging read operation ---');
|
|
112
|
-
|
|
113
|
-
// Build the path manually
|
|
114
|
-
const path = `${config.appName}/${encodeURIComponent(holonId)}/${encodeURIComponent(lensName)}`;
|
|
115
|
-
console.log(`Expected path: ${path}`);
|
|
116
|
-
|
|
117
|
-
// Check what the filter would be
|
|
118
|
-
console.log(`\nFilter that would be used:`);
|
|
119
|
-
console.log(` kinds: [30000]`);
|
|
120
|
-
console.log(` limit: 100`);
|
|
121
|
-
|
|
122
|
-
// Check if we can find matching events in cache
|
|
123
|
-
console.log(`\nSearching cache for matching events...`);
|
|
124
|
-
let foundInCache = false;
|
|
125
|
-
for (const [key, value] of hs.client._eventCache.entries()) {
|
|
126
|
-
if (value.events) {
|
|
127
|
-
for (const event of value.events) {
|
|
128
|
-
const dTag = event.tags.find(t => t[0] === 'd');
|
|
129
|
-
if (dTag && dTag[1].startsWith(path)) {
|
|
130
|
-
console.log(`\n✓ Found matching event in cache!`);
|
|
131
|
-
console.log(` D-tag: ${dTag[1]}`);
|
|
132
|
-
console.log(` Content: ${event.content}`);
|
|
133
|
-
foundInCache = true;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (!foundInCache) {
|
|
140
|
-
console.log('No matching events found in cache');
|
|
141
|
-
}
|
|
142
|
-
} else {
|
|
143
|
-
console.log(`\n✅ Found ${readData.length} record(s)`);
|
|
144
|
-
const match = readData.find(d => d.id === testData.id);
|
|
145
|
-
if (match) {
|
|
146
|
-
console.log('✅ Test data found in results!');
|
|
147
|
-
} else {
|
|
148
|
-
console.log('❌ Test data NOT in results');
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
} catch (error) {
|
|
152
|
-
console.error('\n❌ Read error:', error);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
console.log('\n--- TEST 3: Direct client query ---');
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
const path = `${config.appName}/${encodeURIComponent(holonId)}/${encodeURIComponent(lensName)}`;
|
|
159
|
-
console.log(`\nQuerying with filter:`);
|
|
160
|
-
|
|
161
|
-
const filter = {
|
|
162
|
-
kinds: [30000],
|
|
163
|
-
limit: 100
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
console.log(JSON.stringify(filter, null, 2));
|
|
167
|
-
|
|
168
|
-
const events = await hs.client.query(filter, { timeout: 5000 });
|
|
169
|
-
|
|
170
|
-
console.log(`\nQuery returned ${events.length} events`);
|
|
171
|
-
|
|
172
|
-
for (let i = 0; i < events.length; i++) {
|
|
173
|
-
const event = events[i];
|
|
174
|
-
console.log(`\nEvent ${i + 1}:`);
|
|
175
|
-
console.log(` ID: ${event.id.substring(0, 16)}...`);
|
|
176
|
-
console.log(` Kind: ${event.kind}`);
|
|
177
|
-
console.log(` Pubkey: ${event.pubkey.substring(0, 16)}...`);
|
|
178
|
-
const dTag = event.tags.find(t => t[0] === 'd');
|
|
179
|
-
if (dTag) console.log(` D-tag: ${dTag[1]}`);
|
|
180
|
-
console.log(` Content: ${event.content.substring(0, 100)}...`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Filter by path prefix
|
|
184
|
-
const matching = events.filter(event => {
|
|
185
|
-
const dTag = event.tags.find(t => t[0] === 'd');
|
|
186
|
-
return dTag && dTag[1] && dTag[1].startsWith(path);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
console.log(`\n${matching.length} events match our path prefix`);
|
|
190
|
-
|
|
191
|
-
} catch (error) {
|
|
192
|
-
console.error('\n❌ Query error:', error);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
console.log('\n\n=== DEBUG TEST COMPLETE ===\n');
|
|
196
|
-
|
|
197
|
-
setTimeout(() => process.exit(0), 1000);
|