holosphere 2.0.0-alpha1 → 2.0.0-alpha4

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.
Files changed (154) hide show
  1. package/dist/2019-D2OG2idw.js +6680 -0
  2. package/dist/2019-D2OG2idw.js.map +1 -0
  3. package/dist/2019-EION3wKo.cjs +8 -0
  4. package/dist/2019-EION3wKo.cjs.map +1 -0
  5. package/dist/_commonjsHelpers-C37NGDzP.cjs +2 -0
  6. package/dist/_commonjsHelpers-C37NGDzP.cjs.map +1 -0
  7. package/dist/_commonjsHelpers-CUmg6egw.js +7 -0
  8. package/dist/_commonjsHelpers-CUmg6egw.js.map +1 -0
  9. package/dist/browser-BSniCNqO.js +3058 -0
  10. package/dist/browser-BSniCNqO.js.map +1 -0
  11. package/dist/browser-Cq59Ij19.cjs +2 -0
  12. package/dist/browser-Cq59Ij19.cjs.map +1 -0
  13. package/dist/cjs/holosphere.cjs +2 -0
  14. package/dist/cjs/holosphere.cjs.map +1 -0
  15. package/dist/esm/holosphere.js +53 -0
  16. package/dist/esm/holosphere.js.map +1 -0
  17. package/dist/index-BB_vVJgv.cjs +5 -0
  18. package/dist/index-BB_vVJgv.cjs.map +1 -0
  19. package/dist/index-CBitK71M.cjs +12 -0
  20. package/dist/index-CBitK71M.cjs.map +1 -0
  21. package/dist/index-CV0eOogK.js +37423 -0
  22. package/dist/index-CV0eOogK.js.map +1 -0
  23. package/dist/index-Cz-PLCUR.js +15104 -0
  24. package/dist/index-Cz-PLCUR.js.map +1 -0
  25. package/dist/indexeddb-storage-CRsZyB2f.cjs +2 -0
  26. package/dist/indexeddb-storage-CRsZyB2f.cjs.map +1 -0
  27. package/dist/indexeddb-storage-DZaGlY_a.js +132 -0
  28. package/dist/indexeddb-storage-DZaGlY_a.js.map +1 -0
  29. package/dist/memory-storage-BkUi6sZG.js +51 -0
  30. package/dist/memory-storage-BkUi6sZG.js.map +1 -0
  31. package/dist/memory-storage-C0DuUsdY.cjs +2 -0
  32. package/dist/memory-storage-C0DuUsdY.cjs.map +1 -0
  33. package/dist/secp256k1-0kPdAVkK.cjs +12 -0
  34. package/dist/secp256k1-0kPdAVkK.cjs.map +1 -0
  35. package/dist/secp256k1-DN4FVXcv.js +1890 -0
  36. package/dist/secp256k1-DN4FVXcv.js.map +1 -0
  37. package/docs/CONTRACTS.md +797 -0
  38. package/docs/FOSDEM_PROPOSAL.md +388 -0
  39. package/docs/LOCALFIRST.md +266 -0
  40. package/docs/contracts/api-interface.md +793 -0
  41. package/docs/data-model.md +476 -0
  42. package/docs/gun-async-usage.md +338 -0
  43. package/docs/plan.md +349 -0
  44. package/docs/quickstart.md +674 -0
  45. package/docs/research.md +362 -0
  46. package/docs/spec.md +244 -0
  47. package/docs/storage-backends.md +326 -0
  48. package/docs/tasks.md +947 -0
  49. package/examples/demo.html +47 -0
  50. package/package.json +10 -5
  51. package/src/contracts/abis/Appreciative.json +1280 -0
  52. package/src/contracts/abis/AppreciativeFactory.json +101 -0
  53. package/src/contracts/abis/Bundle.json +1435 -0
  54. package/src/contracts/abis/BundleFactory.json +106 -0
  55. package/src/contracts/abis/Holon.json +881 -0
  56. package/src/contracts/abis/Holons.json +330 -0
  57. package/src/contracts/abis/Managed.json +1262 -0
  58. package/src/contracts/abis/ManagedFactory.json +149 -0
  59. package/src/contracts/abis/Membrane.json +261 -0
  60. package/src/contracts/abis/Splitter.json +1624 -0
  61. package/src/contracts/abis/SplitterFactory.json +220 -0
  62. package/src/contracts/abis/TestToken.json +321 -0
  63. package/src/contracts/abis/Zoned.json +1461 -0
  64. package/src/contracts/abis/ZonedFactory.json +154 -0
  65. package/src/contracts/chain-manager.js +375 -0
  66. package/src/contracts/deployer.js +443 -0
  67. package/src/contracts/event-listener.js +507 -0
  68. package/src/contracts/holon-contracts.js +344 -0
  69. package/src/contracts/index.js +83 -0
  70. package/src/contracts/networks.js +224 -0
  71. package/src/contracts/operations.js +670 -0
  72. package/src/contracts/queries.js +589 -0
  73. package/src/core/holosphere.js +453 -1
  74. package/src/crypto/nostr-utils.js +263 -0
  75. package/src/federation/handshake.js +455 -0
  76. package/src/federation/hologram.js +1 -1
  77. package/src/hierarchical/upcast.js +6 -5
  78. package/src/index.js +463 -1939
  79. package/src/lib/ai-methods.js +308 -0
  80. package/src/lib/contract-methods.js +293 -0
  81. package/src/lib/errors.js +23 -0
  82. package/src/lib/federation-methods.js +238 -0
  83. package/src/lib/index.js +26 -0
  84. package/src/spatial/h3-operations.js +2 -2
  85. package/src/storage/backends/gundb-backend.js +377 -46
  86. package/src/storage/global-tables.js +28 -1
  87. package/src/storage/gun-auth.js +303 -0
  88. package/src/storage/gun-federation.js +776 -0
  89. package/src/storage/gun-references.js +198 -0
  90. package/src/storage/gun-schema.js +291 -0
  91. package/src/storage/gun-wrapper.js +347 -31
  92. package/src/storage/indexeddb-storage.js +49 -11
  93. package/src/storage/memory-storage.js +5 -0
  94. package/src/storage/nostr-async.js +45 -23
  95. package/src/storage/nostr-client.js +11 -5
  96. package/src/storage/persistent-storage.js +6 -1
  97. package/src/storage/unified-storage.js +119 -0
  98. package/src/subscriptions/manager.js +1 -1
  99. package/types/index.d.ts +133 -0
  100. package/tests/unit/ai/aggregation.test.js +0 -295
  101. package/tests/unit/ai/breakdown.test.js +0 -446
  102. package/tests/unit/ai/classifier.test.js +0 -294
  103. package/tests/unit/ai/council.test.js +0 -262
  104. package/tests/unit/ai/embeddings.test.js +0 -384
  105. package/tests/unit/ai/federation-ai.test.js +0 -344
  106. package/tests/unit/ai/h3-ai.test.js +0 -458
  107. package/tests/unit/ai/index.test.js +0 -304
  108. package/tests/unit/ai/json-ops.test.js +0 -307
  109. package/tests/unit/ai/llm-service.test.js +0 -390
  110. package/tests/unit/ai/nl-query.test.js +0 -383
  111. package/tests/unit/ai/relationships.test.js +0 -311
  112. package/tests/unit/ai/schema-extractor.test.js +0 -384
  113. package/tests/unit/ai/spatial.test.js +0 -279
  114. package/tests/unit/ai/tts.test.js +0 -279
  115. package/tests/unit/content.test.js +0 -332
  116. package/tests/unit/contract/core.test.js +0 -88
  117. package/tests/unit/contract/crypto.test.js +0 -198
  118. package/tests/unit/contract/data.test.js +0 -223
  119. package/tests/unit/contract/federation.test.js +0 -181
  120. package/tests/unit/contract/hierarchical.test.js +0 -113
  121. package/tests/unit/contract/schema.test.js +0 -114
  122. package/tests/unit/contract/social.test.js +0 -217
  123. package/tests/unit/contract/spatial.test.js +0 -110
  124. package/tests/unit/contract/subscriptions.test.js +0 -128
  125. package/tests/unit/contract/utils.test.js +0 -159
  126. package/tests/unit/core.test.js +0 -152
  127. package/tests/unit/crypto.test.js +0 -328
  128. package/tests/unit/federation.test.js +0 -234
  129. package/tests/unit/gun-async.test.js +0 -252
  130. package/tests/unit/hierarchical.test.js +0 -399
  131. package/tests/unit/integration/scenario-01-geographic-storage.test.js +0 -74
  132. package/tests/unit/integration/scenario-02-federation.test.js +0 -76
  133. package/tests/unit/integration/scenario-03-subscriptions.test.js +0 -102
  134. package/tests/unit/integration/scenario-04-validation.test.js +0 -129
  135. package/tests/unit/integration/scenario-05-hierarchy.test.js +0 -125
  136. package/tests/unit/integration/scenario-06-social.test.js +0 -135
  137. package/tests/unit/integration/scenario-07-persistence.test.js +0 -130
  138. package/tests/unit/integration/scenario-08-authorization.test.js +0 -161
  139. package/tests/unit/integration/scenario-09-cross-dimensional.test.js +0 -139
  140. package/tests/unit/integration/scenario-10-cross-holosphere-capabilities.test.js +0 -357
  141. package/tests/unit/integration/scenario-11-cross-holosphere-federation.test.js +0 -410
  142. package/tests/unit/integration/scenario-12-capability-federated-read.test.js +0 -719
  143. package/tests/unit/performance/benchmark.test.js +0 -85
  144. package/tests/unit/schema.test.js +0 -213
  145. package/tests/unit/spatial.test.js +0 -158
  146. package/tests/unit/storage.test.js +0 -195
  147. package/tests/unit/subscriptions.test.js +0 -328
  148. package/tests/unit/test-data-permanence-debug.js +0 -197
  149. package/tests/unit/test-data-permanence.js +0 -340
  150. package/tests/unit/test-key-persistence-fixed.js +0 -148
  151. package/tests/unit/test-key-persistence.js +0 -172
  152. package/tests/unit/test-relay-permanence.js +0 -376
  153. package/tests/unit/test-second-node.js +0 -95
  154. package/tests/unit/test-simple-write.js +0 -89
@@ -1,7 +1,30 @@
1
1
  import { createClient } from '../storage/nostr-client.js';
2
2
  import { BackendFactory } from '../storage/backend-factory.js';
3
+ import * as gunWrapper from '../storage/gun-wrapper.js';
4
+ import * as gunFederation from '../storage/gun-federation.js';
5
+ import { GunDBBackend } from '../storage/backends/gundb-backend.js';
3
6
  import pkg from '../../package.json' with { type: 'json' };
4
7
 
8
+ // Gun will be loaded dynamically when needed
9
+ let Gun = null;
10
+ let gunLoadPromise = null;
11
+
12
+ /**
13
+ * Load Gun module dynamically
14
+ * @returns {Promise<Function>} Gun constructor
15
+ */
16
+ async function loadGun() {
17
+ if (Gun) return Gun;
18
+ if (gunLoadPromise) return gunLoadPromise;
19
+
20
+ gunLoadPromise = import('gun').then(module => {
21
+ Gun = module.default || module;
22
+ return Gun;
23
+ });
24
+
25
+ return gunLoadPromise;
26
+ }
27
+
5
28
  /**
6
29
  * Get environment variable (works in Node.js, returns undefined in browser)
7
30
  * @param {string} name - Environment variable name
@@ -89,9 +112,12 @@ export class HoloSphere {
89
112
  this._backend = null;
90
113
 
91
114
  // For backward compatibility with Nostr, initialize synchronously
92
- // Other backends use async initialization via _backendReady
115
+ // GunDB and other backends use async initialization via _backendReady
93
116
  if (this.config.backend === 'nostr') {
94
117
  this._initNostrSync(config);
118
+ } else if (this.config.backend === 'gundb') {
119
+ // GunDB uses async init due to dynamic import
120
+ this._backendReady = this._initGunDBAsync(config);
95
121
  } else {
96
122
  // Async initialization for other backends
97
123
  this._backendReady = this._initBackendAsync(config);
@@ -143,6 +169,68 @@ export class HoloSphere {
143
169
  }
144
170
  }
145
171
 
172
+ /**
173
+ * Initialize GunDB backend asynchronously (for browser compatibility with dynamic import)
174
+ * @private
175
+ */
176
+ async _initGunDBAsync(config) {
177
+ try {
178
+ const gundbConfig = config.gundb || {};
179
+
180
+ // Create the full-featured GunDB backend
181
+ this._backend = new GunDBBackend({
182
+ appName: this.config.appName,
183
+ peers: gundbConfig.peers || [],
184
+ radisk: gundbConfig.radisk !== false,
185
+ localStorage: gundbConfig.localStorage !== false,
186
+ dataDir: config.dataDir,
187
+ privateKey: this.config.privateKey,
188
+ strict: gundbConfig.strict || false,
189
+ schemaCacheMaxAge: gundbConfig.schemaCacheMaxAge || 3600000,
190
+ });
191
+
192
+ // Initialize the backend
193
+ await this._backend.init();
194
+
195
+ // Set public key from backend
196
+ this.publicKey = this._backend.publicKey;
197
+
198
+ // Store Gun instance for direct access
199
+ this._gun = this._backend.gun;
200
+
201
+ // Create a client-like interface for compatibility
202
+ this.client = {
203
+ publicKey: this.publicKey,
204
+ gun: this._gun,
205
+ write: (path, data) => this._backend.write(path, data),
206
+ read: (path, options) => this._backend.read(path, options),
207
+ readAll: (path, options) => this._backend.readAll(path, options),
208
+ update: (path, updates) => this._backend.update(path, updates),
209
+ delete: (path) => this._backend.delete(path),
210
+ subscribe: (path, callback, options) => this._backend.subscribe(path, callback, options),
211
+ buildPath: gunWrapper.buildPath,
212
+ };
213
+
214
+ // Store Gun wrapper functions for direct access
215
+ this._gunWrapper = gunWrapper;
216
+
217
+ // Log startup information
218
+ this._logStartup({
219
+ version: pkg.version,
220
+ appName: this.config.appName,
221
+ backend: 'gundb',
222
+ peers: gundbConfig.peers || [],
223
+ publicKey: this.publicKey,
224
+ logLevel: this.config.logLevel,
225
+ persistence: gundbConfig.radisk !== false,
226
+ dataDir: config.dataDir,
227
+ });
228
+ } catch (error) {
229
+ this._log('ERROR', 'GunDB client initialization failed', { error: error.message });
230
+ throw new Error(`GunDB client initialization failed: ${error.message}`);
231
+ }
232
+ }
233
+
146
234
  /**
147
235
  * Initialize non-Nostr backends asynchronously
148
236
  * @private
@@ -270,4 +358,368 @@ export class HoloSphere {
270
358
  metrics() {
271
359
  return { ...this._metrics };
272
360
  }
361
+
362
+ // ============================================================================
363
+ // GUNDB-SPECIFIC METHODS
364
+ // These methods are only available when using the 'gundb' backend
365
+ // ============================================================================
366
+
367
+ /**
368
+ * Check if using GunDB backend
369
+ * @private
370
+ */
371
+ _requireGunDB() {
372
+ if (this.config.backend !== 'gundb') {
373
+ throw new Error('This method requires the GunDB backend');
374
+ }
375
+ if (!this._backend) {
376
+ throw new Error('Backend not initialized. Call ready() first.');
377
+ }
378
+ }
379
+
380
+ // ============================================================================
381
+ // GLOBAL TABLE OPERATIONS
382
+ // ============================================================================
383
+
384
+ /**
385
+ * Write data to a global table
386
+ * @param {string} tableName - Global table name (e.g., 'federation', 'schemas')
387
+ * @param {Object} data - Data to write (must have 'id' field)
388
+ * @returns {Promise<boolean>} Success indicator
389
+ */
390
+ async putGlobal(tableName, data) {
391
+ await this.ready();
392
+ this._requireGunDB();
393
+ return this._backend.writeGlobal(tableName, data);
394
+ }
395
+
396
+ /**
397
+ * Read data from a global table
398
+ * @param {string} tableName - Global table name
399
+ * @param {string} key - Data key
400
+ * @returns {Promise<Object|null>} Data or null if not found
401
+ */
402
+ async getGlobal(tableName, key) {
403
+ await this.ready();
404
+ this._requireGunDB();
405
+ return this._backend.readGlobal(tableName, key);
406
+ }
407
+
408
+ /**
409
+ * Read all data from a global table
410
+ * @param {string} tableName - Global table name
411
+ * @returns {Promise<Object[]>} Array of data objects
412
+ */
413
+ async getAllGlobal(tableName) {
414
+ await this.ready();
415
+ this._requireGunDB();
416
+ return this._backend.readAllGlobal(tableName);
417
+ }
418
+
419
+ /**
420
+ * Delete data from a global table
421
+ * @param {string} tableName - Global table name
422
+ * @param {string} key - Data key
423
+ * @returns {Promise<boolean>} Success indicator
424
+ */
425
+ async deleteGlobal(tableName, key) {
426
+ await this.ready();
427
+ this._requireGunDB();
428
+ return this._backend.deleteGlobal(tableName, key);
429
+ }
430
+
431
+ // ============================================================================
432
+ // REFERENCE OPERATIONS
433
+ // ============================================================================
434
+
435
+ /**
436
+ * Create a reference to data
437
+ * @param {string} holon - Holon ID
438
+ * @param {string} lens - Lens name
439
+ * @param {Object} data - Data object (must have 'id' field)
440
+ * @returns {Object} Reference object with id and soul
441
+ */
442
+ createReference(holon, lens, data) {
443
+ this._requireGunDB();
444
+ return this._backend.createReference(holon, lens, data);
445
+ }
446
+
447
+ /**
448
+ * Check if data is a reference
449
+ * @param {Object} data - Data to check
450
+ * @returns {boolean} True if data is a reference
451
+ */
452
+ isReference(data) {
453
+ this._requireGunDB();
454
+ return this._backend.isReference(data);
455
+ }
456
+
457
+ /**
458
+ * Resolve a reference to get actual data
459
+ * @param {Object} reference - Reference object
460
+ * @param {Object} options - Resolution options
461
+ * @returns {Promise<Object|null>} Resolved data or null
462
+ */
463
+ async resolveReference(reference, options = {}) {
464
+ await this.ready();
465
+ this._requireGunDB();
466
+ return this._backend.resolveReference(reference, options);
467
+ }
468
+
469
+ // ============================================================================
470
+ // AUTHENTICATION OPERATIONS
471
+ // ============================================================================
472
+
473
+ /**
474
+ * Authenticate for a holon
475
+ * @param {string} holonId - Holon ID
476
+ * @param {string} password - Password
477
+ * @returns {Promise<Object>} Authenticated user object
478
+ */
479
+ async authenticate(holonId, password) {
480
+ await this.ready();
481
+ this._requireGunDB();
482
+ return this._backend.authenticate(holonId, password);
483
+ }
484
+
485
+ /**
486
+ * Create a new user for a holon
487
+ * @param {string} holonId - Holon ID
488
+ * @param {string} password - Password
489
+ * @returns {Promise<Object>} Created user object
490
+ */
491
+ async createUser(holonId, password) {
492
+ await this.ready();
493
+ this._requireGunDB();
494
+ return this._backend.createUser(holonId, password);
495
+ }
496
+
497
+ /**
498
+ * Logout current user
499
+ */
500
+ logout() {
501
+ this._requireGunDB();
502
+ this._backend.logout();
503
+ }
504
+
505
+ /**
506
+ * Check if authenticated
507
+ * @returns {boolean} True if authenticated
508
+ */
509
+ isAuthenticated() {
510
+ this._requireGunDB();
511
+ return this._backend.isAuthenticated();
512
+ }
513
+
514
+ /**
515
+ * Write to private storage (requires authentication)
516
+ * @param {string} lens - Lens name
517
+ * @param {string} key - Data key
518
+ * @param {Object} data - Data to write
519
+ * @returns {Promise<boolean>} Success indicator
520
+ */
521
+ async writePrivate(lens, key, data) {
522
+ await this.ready();
523
+ this._requireGunDB();
524
+ return this._backend.writePrivate(lens, key, data);
525
+ }
526
+
527
+ /**
528
+ * Read from private storage (requires authentication)
529
+ * @param {string} lens - Lens name
530
+ * @param {string} key - Data key
531
+ * @returns {Promise<Object|null>} Data or null
532
+ */
533
+ async readPrivate(lens, key) {
534
+ await this.ready();
535
+ this._requireGunDB();
536
+ return this._backend.readPrivate(lens, key);
537
+ }
538
+
539
+ // ============================================================================
540
+ // SCHEMA OPERATIONS
541
+ // ============================================================================
542
+
543
+ /**
544
+ * Set a schema for a lens
545
+ * @param {string} lens - Lens name
546
+ * @param {Object} schema - JSON Schema definition
547
+ * @returns {Promise<boolean>} Success indicator
548
+ */
549
+ async setSchema(lens, schema) {
550
+ await this.ready();
551
+ this._requireGunDB();
552
+ return this._backend.setSchema(lens, schema);
553
+ }
554
+
555
+ /**
556
+ * Get a schema for a lens
557
+ * @param {string} lens - Lens name
558
+ * @returns {Promise<Object|null>} Schema or null
559
+ */
560
+ async getSchema(lens) {
561
+ await this.ready();
562
+ this._requireGunDB();
563
+ return this._backend.getSchema(lens);
564
+ }
565
+
566
+ /**
567
+ * Validate data against a lens schema
568
+ * @param {string} lens - Lens name
569
+ * @param {Object} data - Data to validate
570
+ * @returns {Promise<Object>} Validation result { valid: boolean, errors: Array }
571
+ */
572
+ async validateData(lens, data) {
573
+ await this.ready();
574
+ this._requireGunDB();
575
+ return this._backend.validateData(lens, data);
576
+ }
577
+
578
+ // ============================================================================
579
+ // FEDERATION OPERATIONS
580
+ // ============================================================================
581
+
582
+ /**
583
+ * Create a federation relationship between two spaces
584
+ * @param {string} spaceId1 - First space ID
585
+ * @param {string} spaceId2 - Second space ID
586
+ * @param {boolean} bidirectional - Whether to set up bidirectional notifications (default: true)
587
+ * @returns {Promise<boolean>} True if federation was created
588
+ */
589
+ async federate(spaceId1, spaceId2, bidirectional = true) {
590
+ await this.ready();
591
+ this._requireGunDB();
592
+ return gunFederation.federate(this._backend, spaceId1, spaceId2, bidirectional);
593
+ }
594
+
595
+ /**
596
+ * Remove a federation relationship
597
+ * @param {string} spaceId1 - First space ID
598
+ * @param {string} spaceId2 - Second space ID
599
+ * @returns {Promise<boolean>} True if federation was removed
600
+ */
601
+ async unfederate(spaceId1, spaceId2) {
602
+ await this.ready();
603
+ this._requireGunDB();
604
+ return gunFederation.unfederate(this._backend, spaceId1, spaceId2);
605
+ }
606
+
607
+ /**
608
+ * Get federation info for a space
609
+ * @param {string} spaceId - Space ID
610
+ * @returns {Promise<Object|null>} Federation info or null
611
+ */
612
+ async getFederation(spaceId) {
613
+ await this.ready();
614
+ this._requireGunDB();
615
+ return gunFederation.getFederation(this._backend, spaceId);
616
+ }
617
+
618
+ /**
619
+ * Reset all federation relationships for a space
620
+ * @param {string} spaceId - Space ID
621
+ * @param {Object} options - Reset options
622
+ * @returns {Promise<Object>} Result object
623
+ */
624
+ async resetFederation(spaceId, options = {}) {
625
+ await this.ready();
626
+ this._requireGunDB();
627
+ return gunFederation.resetFederation(this._backend, spaceId, options);
628
+ }
629
+
630
+ /**
631
+ * Propagate data to federated spaces
632
+ * @param {string} holon - Holon identifier
633
+ * @param {string} lens - Lens identifier
634
+ * @param {Object} data - Data to propagate
635
+ * @param {Object} options - Propagation options
636
+ * @returns {Promise<Object>} Result with success count and errors
637
+ */
638
+ async propagate(holon, lens, data, options = {}) {
639
+ await this.ready();
640
+ this._requireGunDB();
641
+ return gunFederation.propagate(this._backend, holon, lens, data, options);
642
+ }
643
+
644
+ /**
645
+ * Get combined data from local and federated sources
646
+ * @param {string} holon - Local holon name
647
+ * @param {string} lens - Lens to query
648
+ * @param {Object} options - Options for data retrieval and aggregation
649
+ * @returns {Promise<Array>} Combined array of local and federated data
650
+ */
651
+ async getFederated(holon, lens, options = {}) {
652
+ await this.ready();
653
+ this._requireGunDB();
654
+ return gunFederation.getFederated(this._backend, holon, lens, options);
655
+ }
656
+
657
+ /**
658
+ * Subscribe to federation notifications for a space
659
+ * @param {string} spaceId - Space ID to subscribe to
660
+ * @param {Function} callback - Callback to execute on notifications
661
+ * @param {Object} options - Subscription options
662
+ * @returns {Promise<Object>} Subscription object with unsubscribe() method
663
+ */
664
+ async subscribeFederation(spaceId, callback, options = {}) {
665
+ await this.ready();
666
+ this._requireGunDB();
667
+ return gunFederation.subscribeFederation(this._backend, spaceId, callback, options);
668
+ }
669
+
670
+ /**
671
+ * Track a federated message across different chats
672
+ * @param {string} originalChatId - Original chat ID
673
+ * @param {string} messageId - Original message ID
674
+ * @param {string} federatedChatId - Federated chat ID
675
+ * @param {string} federatedMessageId - Federated message ID
676
+ * @param {string} type - Message type
677
+ * @returns {Promise<void>}
678
+ */
679
+ async federateMessage(originalChatId, messageId, federatedChatId, federatedMessageId, type = 'generic') {
680
+ await this.ready();
681
+ this._requireGunDB();
682
+ return gunFederation.federateMessage(this._backend, originalChatId, messageId, federatedChatId, federatedMessageId, type);
683
+ }
684
+
685
+ /**
686
+ * Get all federated messages for a given original message
687
+ * @param {string} originalChatId - Original chat ID
688
+ * @param {string} messageId - Original message ID
689
+ * @returns {Promise<Object|null>} Tracking information for the message
690
+ */
691
+ async getFederatedMessages(originalChatId, messageId) {
692
+ await this.ready();
693
+ this._requireGunDB();
694
+ return gunFederation.getFederatedMessages(this._backend, originalChatId, messageId);
695
+ }
696
+
697
+ /**
698
+ * Update a federated message across all federated chats
699
+ * @param {string} originalChatId - Original chat ID
700
+ * @param {string} messageId - Original message ID
701
+ * @param {Function} updateCallback - Function to update the message in each chat
702
+ * @returns {Promise<void>}
703
+ */
704
+ async updateFederatedMessages(originalChatId, messageId, updateCallback) {
705
+ await this.ready();
706
+ this._requireGunDB();
707
+ return gunFederation.updateFederatedMessages(this._backend, originalChatId, messageId, updateCallback);
708
+ }
709
+
710
+ // ============================================================================
711
+ // LIFECYCLE
712
+ // ============================================================================
713
+
714
+ /**
715
+ * Close the backend and clean up resources
716
+ */
717
+ close() {
718
+ if (this._backend) {
719
+ this._backend.close();
720
+ }
721
+ if (this.client && typeof this.client.close === 'function') {
722
+ this.client.close();
723
+ }
724
+ }
273
725
  }