holosphere 2.0.0-alpha7 → 2.0.0-alpha9
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/CHANGELOG.md +446 -0
- package/FEATURES.md +431 -0
- package/LICENSE +29 -166
- package/LICENSE-AGPL.md +180 -0
- package/dist/cdn/holosphere.min.js +55 -0
- package/dist/cdn/holosphere.min.js.map +1 -0
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +1 -1
- package/dist/{index-C-IlLYlk.cjs → index-DDGt_V9o.cjs} +2 -2
- package/dist/{index-C-IlLYlk.cjs.map → index-DDGt_V9o.cjs.map} +1 -1
- package/dist/{index-d6f4RJBM.js → index-DJXftyvB.js} +2253 -387
- package/dist/index-DJXftyvB.js.map +1 -0
- package/dist/index-DMbdcMtK.cjs +18 -0
- package/dist/index-DMbdcMtK.cjs.map +1 -0
- package/dist/{index-jmTHEbR2.js → index-DeZ1xz_s.js} +2 -2
- package/dist/{index-jmTHEbR2.js.map → index-DeZ1xz_s.js.map} +1 -1
- package/dist/{indexeddb-storage-D8kOl0oK.js → indexeddb-storage-BFt6hMeF.js} +48 -4
- package/dist/indexeddb-storage-BFt6hMeF.js.map +1 -0
- package/dist/{indexeddb-storage-a8GipaDr.cjs → indexeddb-storage-BK5tv4Sh.cjs} +2 -2
- package/dist/indexeddb-storage-BK5tv4Sh.cjs.map +1 -0
- package/dist/{memory-storage-DBQK622V.js → memory-storage-C9HuoL2E.js} +44 -4
- package/dist/memory-storage-C9HuoL2E.js.map +1 -0
- package/dist/{memory-storage-gfRovk2O.cjs → memory-storage-Dao7jfYG.cjs} +2 -2
- package/dist/memory-storage-Dao7jfYG.cjs.map +1 -0
- package/dist/{secp256k1-BCAPF45D.cjs → secp256k1-BbKzbLtD.cjs} +2 -2
- package/dist/{secp256k1-BCAPF45D.cjs.map → secp256k1-BbKzbLtD.cjs.map} +1 -1
- package/dist/{secp256k1-DYm_CMqW.js → secp256k1-CreY7Pcl.js} +2 -2
- package/dist/{secp256k1-DYm_CMqW.js.map → secp256k1-CreY7Pcl.js.map} +1 -1
- package/docs/api/ai_aggregation.js.html +333 -0
- package/docs/api/ai_breakdown.js.html +524 -0
- package/docs/api/ai_classifier.js.html +231 -0
- package/docs/api/ai_council.js.html +246 -0
- package/docs/api/ai_embeddings.js.html +304 -0
- package/docs/api/ai_federation-ai.js.html +338 -0
- package/docs/api/ai_h3-ai.js.html +970 -0
- package/docs/api/ai_index.js.html +124 -0
- package/docs/api/ai_json-ops.js.html +241 -0
- package/docs/api/ai_llm-service.js.html +239 -0
- package/docs/api/ai_nl-query.js.html +236 -0
- package/docs/api/ai_relationships.js.html +367 -0
- package/docs/api/ai_schema-extractor.js.html +235 -0
- package/docs/api/ai_spatial.js.html +307 -0
- package/docs/api/ai_tts.js.html +214 -0
- package/docs/api/content_social-protocols.js.html +180 -0
- package/docs/api/core_holosphere.js.html +757 -0
- package/docs/api/crypto_nostr-utils.js.html +306 -0
- package/docs/api/crypto_secp256k1.js.html +267 -0
- package/docs/api/data/search.json +1 -0
- package/docs/api/federation_discovery.js.html +337 -0
- package/docs/api/federation_handshake.js.html +478 -0
- package/docs/api/federation_hologram.js.html +1053 -0
- package/docs/api/federation_registry.js.html +389 -0
- package/docs/api/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/api/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/api/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/api/global.html +3 -0
- package/docs/api/hierarchical_upcast.js.html +128 -0
- package/docs/api/index.html +265 -0
- package/docs/api/index.js.html +1868 -0
- package/docs/api/lib_ai-methods.js.html +660 -0
- package/docs/api/lib_contract-methods.js.html +445 -0
- package/docs/api/lib_errors.js.html +56 -0
- package/docs/api/lib_federation-methods.js.html +348 -0
- package/docs/api/lib_index.js.html +33 -0
- package/docs/api/module-ai.html +5 -0
- package/docs/api/module-ai_aggregation-SmartAggregation.html +6 -0
- package/docs/api/module-ai_aggregation.SmartAggregation.html +3 -0
- package/docs/api/module-ai_aggregation.html +3 -0
- package/docs/api/module-ai_breakdown-TaskBreakdown.html +5 -0
- package/docs/api/module-ai_breakdown.TaskBreakdown.html +3 -0
- package/docs/api/module-ai_breakdown.html +3 -0
- package/docs/api/module-ai_classifier-Classifier.html +6 -0
- package/docs/api/module-ai_classifier.Classifier.html +3 -0
- package/docs/api/module-ai_classifier.html +3 -0
- package/docs/api/module-ai_council-Council.html +6 -0
- package/docs/api/module-ai_council.Council.html +3 -0
- package/docs/api/module-ai_council.html +3 -0
- package/docs/api/module-ai_embeddings-Embeddings.html +5 -0
- package/docs/api/module-ai_embeddings.Embeddings.html +3 -0
- package/docs/api/module-ai_embeddings.html +3 -0
- package/docs/api/module-ai_federation-ai-FederationAdvisor.html +6 -0
- package/docs/api/module-ai_federation-ai.FederationAdvisor.html +3 -0
- package/docs/api/module-ai_federation-ai.html +3 -0
- package/docs/api/module-ai_h3-ai-H3AI.html +6 -0
- package/docs/api/module-ai_h3-ai.H3AI.html +3 -0
- package/docs/api/module-ai_h3-ai.html +3 -0
- package/docs/api/module-ai_json-ops-JSONOps.html +5 -0
- package/docs/api/module-ai_json-ops.JSONOps.html +3 -0
- package/docs/api/module-ai_json-ops.html +3 -0
- package/docs/api/module-ai_llm-service-LLMService.html +5 -0
- package/docs/api/module-ai_llm-service.LLMService.html +3 -0
- package/docs/api/module-ai_llm-service.html +3 -0
- package/docs/api/module-ai_nl-query-NLQuery.html +5 -0
- package/docs/api/module-ai_nl-query.NLQuery.html +3 -0
- package/docs/api/module-ai_nl-query.html +3 -0
- package/docs/api/module-ai_relationships-RelationshipDiscovery.html +6 -0
- package/docs/api/module-ai_relationships.RelationshipDiscovery.html +3 -0
- package/docs/api/module-ai_relationships.html +3 -0
- package/docs/api/module-ai_schema-extractor-SchemaExtractor.html +5 -0
- package/docs/api/module-ai_schema-extractor.SchemaExtractor.html +3 -0
- package/docs/api/module-ai_schema-extractor.html +3 -0
- package/docs/api/module-ai_spatial-SpatialAnalysis.html +6 -0
- package/docs/api/module-ai_spatial.SpatialAnalysis.html +3 -0
- package/docs/api/module-ai_spatial.html +3 -0
- package/docs/api/module-ai_tts-TTS.html +5 -0
- package/docs/api/module-ai_tts.TTS.html +3 -0
- package/docs/api/module-ai_tts.html +3 -0
- package/docs/api/module-content_social-protocols.html +3 -0
- package/docs/api/module-core_holosphere-HoloSphere.html +6 -0
- package/docs/api/module-core_holosphere.HoloSphere.html +3 -0
- package/docs/api/module-core_holosphere.html +3 -0
- package/docs/api/module-crypto_nostr-utils.html +3 -0
- package/docs/api/module-crypto_secp256k1.html +3 -0
- package/docs/api/module-federation_hologram.html +3 -0
- package/docs/api/module-hierarchical_upcast.html +3 -0
- package/docs/api/module-holosphere-HoloSphereBase.html +3 -0
- package/docs/api/module-holosphere.html +3 -0
- package/docs/api/module-lib_ai-methods.html +3 -0
- package/docs/api/module-lib_contract-methods.html +3 -0
- package/docs/api/module-lib_errors-AuthorizationError.html +3 -0
- package/docs/api/module-lib_errors-ValidationError.html +3 -0
- package/docs/api/module-lib_errors.AuthorizationError.html +3 -0
- package/docs/api/module-lib_errors.ValidationError.html +3 -0
- package/docs/api/module-lib_errors.html +3 -0
- package/docs/api/module-lib_federation-methods.html +3 -0
- package/docs/api/module-lib_index.html +3 -0
- package/docs/api/module-schema_validator-ValidationError.html +3 -0
- package/docs/api/module-schema_validator.ValidationError.html +3 -0
- package/docs/api/module-schema_validator.html +3 -0
- package/docs/api/module-spatial_h3-operations.html +4 -0
- package/docs/api/module-storage_backend-factory.BackendFactory.html +3 -0
- package/docs/api/module-storage_backend-factory.html +3 -0
- package/docs/api/module-storage_backend-interface-StorageBackend.html +3 -0
- package/docs/api/module-storage_backend-interface.StorageBackend.html +3 -0
- package/docs/api/module-storage_backend-interface.html +3 -0
- package/docs/api/module-storage_backends_activitypub-backend-ActivityPubBackend.html +7 -0
- package/docs/api/module-storage_backends_activitypub-backend.ActivityPubBackend.html +3 -0
- package/docs/api/module-storage_backends_activitypub-backend.html +3 -0
- package/docs/api/module-storage_backends_activitypub_server-ActivityPubServer.html +8 -0
- package/docs/api/module-storage_backends_activitypub_server.ActivityPubServer.html +3 -0
- package/docs/api/module-storage_backends_activitypub_server.html +3 -0
- package/docs/api/module-storage_backends_gundb-backend-GunDBBackend.html +7 -0
- package/docs/api/module-storage_backends_gundb-backend.GunDBBackend.html +3 -0
- package/docs/api/module-storage_backends_gundb-backend.html +3 -0
- package/docs/api/module-storage_backends_nostr-backend-NostrBackend.html +8 -0
- package/docs/api/module-storage_backends_nostr-backend.NostrBackend.html +3 -0
- package/docs/api/module-storage_backends_nostr-backend.html +3 -0
- package/docs/api/module-storage_filesystem-storage-FileSystemStorage.html +5 -0
- package/docs/api/module-storage_filesystem-storage-browser-FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage-browser.FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage-browser.html +3 -0
- package/docs/api/module-storage_filesystem-storage.FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage.html +3 -0
- package/docs/api/module-storage_global-tables.html +3 -0
- package/docs/api/module-storage_gun-async.html +3 -0
- package/docs/api/module-storage_gun-auth-GunAuth.html +5 -0
- package/docs/api/module-storage_gun-auth.GunAuth.html +3 -0
- package/docs/api/module-storage_gun-auth.html +3 -0
- package/docs/api/module-storage_gun-federation.html +3 -0
- package/docs/api/module-storage_gun-references-GunReferenceHandler.html +5 -0
- package/docs/api/module-storage_gun-references.GunReferenceHandler.html +3 -0
- package/docs/api/module-storage_gun-references.html +3 -0
- package/docs/api/module-storage_gun-schema-GunSchemaValidator.html +5 -0
- package/docs/api/module-storage_gun-schema.GunSchemaValidator.html +3 -0
- package/docs/api/module-storage_gun-schema.html +3 -0
- package/docs/api/module-storage_gun-wrapper.html +11 -0
- package/docs/api/module-storage_indexeddb-storage-IndexedDBStorage.html +5 -0
- package/docs/api/module-storage_indexeddb-storage.IndexedDBStorage.html +3 -0
- package/docs/api/module-storage_indexeddb-storage.html +3 -0
- package/docs/api/module-storage_key-storage-simple.html +3 -0
- package/docs/api/module-storage_key-storage.html +4 -0
- package/docs/api/module-storage_memory-storage-MemoryStorage.html +5 -0
- package/docs/api/module-storage_memory-storage.MemoryStorage.html +3 -0
- package/docs/api/module-storage_memory-storage.html +3 -0
- package/docs/api/module-storage_migration-MigrationTool.html +6 -0
- package/docs/api/module-storage_migration.MigrationTool.html +3 -0
- package/docs/api/module-storage_migration.html +3 -0
- package/docs/api/module-storage_nostr-async.html +18 -0
- package/docs/api/module-storage_nostr-client-LRUCache.html +3 -0
- package/docs/api/module-storage_nostr-client-NostrClient.html +7 -0
- package/docs/api/module-storage_nostr-client.NostrClient.html +15 -0
- package/docs/api/module-storage_nostr-client.html +6 -0
- package/docs/api/module-storage_nostr-wrapper.html +3 -0
- package/docs/api/module-storage_outbox-queue-OutboxQueue.html +4 -0
- package/docs/api/module-storage_outbox-queue.OutboxQueue.html +3 -0
- package/docs/api/module-storage_outbox-queue.html +3 -0
- package/docs/api/module-storage_persistent-storage-PersistentStorage.html +3 -0
- package/docs/api/module-storage_persistent-storage.html +4 -0
- package/docs/api/module-storage_sync-service-SyncService.html +5 -0
- package/docs/api/module-storage_sync-service.SyncService.html +3 -0
- package/docs/api/module-storage_sync-service.html +3 -0
- package/docs/api/module-storage_unified-storage.html +3 -0
- package/docs/api/module-subscriptions_manager.SubscriptionRegistry.html +3 -0
- package/docs/api/module-subscriptions_manager.html +3 -0
- package/docs/api/schema_validator.js.html +113 -0
- package/docs/api/scripts/core.js +726 -0
- package/docs/api/scripts/core.min.js +23 -0
- package/docs/api/scripts/resize.js +90 -0
- package/docs/api/scripts/search.js +265 -0
- package/docs/api/scripts/search.min.js +6 -0
- package/docs/api/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/api/scripts/third-party/fuse.js +9 -0
- package/docs/api/scripts/third-party/hljs-line-num-original.js +369 -0
- package/docs/api/scripts/third-party/hljs-line-num.js +1 -0
- package/docs/api/scripts/third-party/hljs-original.js +5171 -0
- package/docs/api/scripts/third-party/hljs.js +1 -0
- package/docs/api/scripts/third-party/popper.js +5 -0
- package/docs/api/scripts/third-party/tippy.js +1 -0
- package/docs/api/scripts/third-party/tocbot.js +672 -0
- package/docs/api/scripts/third-party/tocbot.min.js +1 -0
- package/docs/api/spatial_h3-operations.js.html +129 -0
- package/docs/api/storage_backend-factory.js.html +133 -0
- package/docs/api/storage_backend-interface.js.html +164 -0
- package/docs/api/storage_backends_activitypub-backend.js.html +298 -0
- package/docs/api/storage_backends_activitypub_server.js.html +678 -0
- package/docs/api/storage_backends_gundb-backend.js.html +878 -0
- package/docs/api/storage_backends_nostr-backend.js.html +254 -0
- package/docs/api/storage_filesystem-storage-browser.js.html +83 -0
- package/docs/api/storage_filesystem-storage.js.html +207 -0
- package/docs/api/storage_global-tables.js.html +116 -0
- package/docs/api/storage_gun-async.js.html +344 -0
- package/docs/api/storage_gun-auth.js.html +376 -0
- package/docs/api/storage_gun-federation.js.html +788 -0
- package/docs/api/storage_gun-references.js.html +212 -0
- package/docs/api/storage_gun-schema.js.html +309 -0
- package/docs/api/storage_gun-wrapper.js.html +645 -0
- package/docs/api/storage_indexeddb-storage.js.html +224 -0
- package/docs/api/storage_key-storage-simple.js.html +102 -0
- package/docs/api/storage_key-storage.js.html +171 -0
- package/docs/api/storage_memory-storage.js.html +128 -0
- package/docs/api/storage_migration.js.html +354 -0
- package/docs/api/storage_nostr-async.js.html +1076 -0
- package/docs/api/storage_nostr-client.js.html +1598 -0
- package/docs/api/storage_nostr-wrapper.js.html +218 -0
- package/docs/api/storage_outbox-queue.js.html +248 -0
- package/docs/api/storage_persistent-storage.js.html +160 -0
- package/docs/api/storage_sync-service.js.html +201 -0
- package/docs/api/storage_unified-storage.js.html +157 -0
- package/docs/api/styles/clean-jsdoc-theme-base.css +1159 -0
- package/docs/api/styles/clean-jsdoc-theme-dark.css +412 -0
- package/docs/api/styles/clean-jsdoc-theme-light.css +482 -0
- package/docs/api/styles/clean-jsdoc-theme-scrollbar.css +30 -0
- package/docs/api/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
- package/docs/api/styles/clean-jsdoc-theme.min.css +1 -0
- package/docs/api/subscriptions_manager.js.html +162 -0
- package/examples/holosphere-widget.js +1242 -0
- package/examples/widget-demo.html +274 -0
- package/examples/widget.html +703 -0
- package/jsdoc.json +26 -0
- package/package.json +16 -3
- package/src/ai/aggregation.js +13 -2
- package/src/ai/breakdown.js +12 -2
- package/src/ai/classifier.js +14 -3
- package/src/ai/council.js +22 -7
- package/src/ai/embeddings.js +37 -15
- package/src/ai/federation-ai.js +13 -2
- package/src/ai/h3-ai.js +14 -2
- package/src/ai/index.js +16 -7
- package/src/ai/json-ops.js +18 -5
- package/src/ai/llm-service.js +62 -31
- package/src/ai/nl-query.js +12 -2
- package/src/ai/relationships.js +13 -2
- package/src/ai/schema-extractor.js +24 -10
- package/src/ai/spatial.js +13 -2
- package/src/ai/tts.js +25 -8
- package/src/cdn-entry.js +22 -0
- package/src/content/social-protocols.js +34 -25
- package/src/contracts/chain-manager.js +68 -40
- package/src/contracts/deployer.js +70 -42
- package/src/contracts/event-listener.js +61 -29
- package/src/contracts/holon-contracts.js +46 -31
- package/src/contracts/index.js +5 -6
- package/src/contracts/networks.js +19 -14
- package/src/contracts/operations.js +58 -41
- package/src/contracts/queries.js +70 -21
- package/src/core/holosphere.js +37 -8
- package/src/crypto/nostr-utils.js +105 -65
- package/src/crypto/secp256k1.js +7 -2
- package/src/federation/handshake.js +23 -11
- package/src/federation/hologram.js +9 -1
- package/src/hierarchical/upcast.js +34 -20
- package/src/index.js +671 -7
- package/src/lib/ai-methods.js +352 -3
- package/src/lib/contract-methods.js +152 -3
- package/src/lib/errors.js +31 -1
- package/src/lib/federation-methods.js +110 -3
- package/src/lib/index.js +9 -5
- package/src/schema/validator.js +22 -3
- package/src/spatial/h3-operations.js +17 -1
- package/src/storage/backend-factory.js +7 -2
- package/src/storage/backend-interface.js +21 -2
- package/src/storage/backends/activitypub/server.js +25 -3
- package/src/storage/backends/activitypub-backend.js +25 -2
- package/src/storage/backends/gundb-backend.js +322 -11
- package/src/storage/backends/nostr-backend.js +116 -1
- package/src/storage/filesystem-storage-browser.js +42 -2
- package/src/storage/filesystem-storage.js +72 -5
- package/src/storage/global-tables.js +7 -2
- package/src/storage/gun-async.js +20 -11
- package/src/storage/gun-auth.js +15 -4
- package/src/storage/gun-federation.js +14 -5
- package/src/storage/gun-references.js +16 -5
- package/src/storage/gun-schema.js +25 -10
- package/src/storage/gun-wrapper.js +160 -49
- package/src/storage/indexeddb-storage.js +65 -4
- package/src/storage/key-storage-simple.js +32 -9
- package/src/storage/key-storage.js +45 -13
- package/src/storage/memory-storage.js +65 -4
- package/src/storage/migration.js +20 -7
- package/src/storage/nostr-async.js +195 -90
- package/src/storage/nostr-client.js +173 -49
- package/src/storage/nostr-wrapper.js +6 -2
- package/src/storage/outbox-queue.js +55 -18
- package/src/storage/persistent-storage.js +56 -13
- package/src/storage/sync-service.js +51 -17
- package/src/storage/unified-storage.js +38 -3
- package/src/subscriptions/manager.js +33 -16
- package/vite.config.cdn.js +60 -0
- package/dist/index-Bvwyvd0T.cjs +0 -5
- package/dist/index-Bvwyvd0T.cjs.map +0 -1
- package/dist/index-d6f4RJBM.js.map +0 -1
- package/dist/indexeddb-storage-D8kOl0oK.js.map +0 -1
- package/dist/indexeddb-storage-a8GipaDr.cjs.map +0 -1
- package/dist/memory-storage-DBQK622V.js.map +0 -1
- package/dist/memory-storage-gfRovk2O.cjs.map +0 -1
- /package/{cleanup-test-data.js → scripts/cleanup-test-data.js} +0 -0
- /package/{test-ai-real-api.js → scripts/test-ai-real-api.js} +0 -0
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Abstract Storage Backend Interface
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview Abstract Storage Backend Interface.
|
|
3
|
+
*
|
|
4
|
+
* Defines the contract that all storage backends must implement.
|
|
5
|
+
* Provides a consistent API for CRUD operations, subscriptions,
|
|
6
|
+
* and data migration across different storage technologies.
|
|
7
|
+
*
|
|
8
|
+
* @module storage/backend-interface
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Abstract base class for storage backends.
|
|
13
|
+
* All concrete backends (Nostr, GunDB, ActivityPub) must extend this class.
|
|
14
|
+
*
|
|
15
|
+
* @abstract
|
|
16
|
+
* @class StorageBackend
|
|
4
17
|
*/
|
|
5
18
|
export class StorageBackend {
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new StorageBackend instance.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} config - Backend-specific configuration
|
|
23
|
+
* @throws {Error} If instantiated directly (abstract class)
|
|
24
|
+
*/
|
|
6
25
|
constructor(config) {
|
|
7
26
|
if (new.target === StorageBackend) {
|
|
8
27
|
throw new Error('StorageBackend is abstract and cannot be instantiated directly');
|
|
@@ -1,19 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Self-hosted ActivityPub server for HoloSphere
|
|
3
|
-
* Provides federation with Mastodon, Pleroma,
|
|
2
|
+
* @fileoverview Self-hosted ActivityPub server for HoloSphere federation.
|
|
3
|
+
* Provides complete ActivityPub protocol support for federation with Mastodon, Pleroma,
|
|
4
|
+
* and other fediverse servers. Includes WebFinger, NodeInfo, actor endpoints, and SSE subscriptions.
|
|
5
|
+
* @module storage/backends/activitypub/server
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
import express from 'express';
|
|
7
9
|
import crypto from 'crypto';
|
|
8
10
|
import { createPersistentStorage } from '../../persistent-storage.js';
|
|
9
11
|
|
|
12
|
+
/** @constant {string} ActivityStreams JSON-LD context */
|
|
10
13
|
const ACTIVITY_STREAMS_CONTEXT = 'https://www.w3.org/ns/activitystreams';
|
|
14
|
+
/** @constant {string} Security vocabulary JSON-LD context */
|
|
11
15
|
const SECURITY_CONTEXT = 'https://w3id.org/security/v1';
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
|
-
* ActivityPub
|
|
18
|
+
* Self-hosted ActivityPub server for HoloSphere data federation.
|
|
19
|
+
* Implements WebFinger discovery, actor endpoints, inbox/outbox, and HoloSphere data API.
|
|
20
|
+
*
|
|
21
|
+
* @class ActivityPubServer
|
|
22
|
+
* @example
|
|
23
|
+
* const server = new ActivityPubServer({
|
|
24
|
+
* port: 3000,
|
|
25
|
+
* domain: 'holon.example.com',
|
|
26
|
+
* dataDir: './data'
|
|
27
|
+
* });
|
|
28
|
+
* await server.start();
|
|
15
29
|
*/
|
|
16
30
|
export class ActivityPubServer {
|
|
31
|
+
/**
|
|
32
|
+
* Create a new ActivityPub server instance.
|
|
33
|
+
* @param {Object} [config={}] - Server configuration
|
|
34
|
+
* @param {number} [config.port=3000] - HTTP port to listen on
|
|
35
|
+
* @param {string} [config.domain='localhost'] - Server domain for URLs
|
|
36
|
+
* @param {string} [config.protocol='http'] - Protocol (http or https)
|
|
37
|
+
* @param {string} [config.dataDir] - Data directory for persistent storage
|
|
38
|
+
*/
|
|
17
39
|
constructor(config = {}) {
|
|
18
40
|
this.config = {
|
|
19
41
|
port: config.port || 3000,
|
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ActivityPub
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview ActivityPub storage backend client adapter.
|
|
3
|
+
* Provides HTTP-based connectivity to an ActivityPub server for federated data storage
|
|
4
|
+
* and real-time subscriptions via Server-Sent Events.
|
|
5
|
+
* @module storage/backends/activitypub-backend
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
import { StorageBackend } from '../backend-interface.js';
|
|
7
9
|
|
|
10
|
+
/**
|
|
11
|
+
* ActivityPub storage backend implementation.
|
|
12
|
+
* Client adapter for connecting to an ActivityPub server via HTTP API
|
|
13
|
+
* with SSE-based real-time subscriptions.
|
|
14
|
+
*
|
|
15
|
+
* @class ActivityPubBackend
|
|
16
|
+
* @extends StorageBackend
|
|
17
|
+
* @example
|
|
18
|
+
* const backend = await BackendFactory.create('activitypub', {
|
|
19
|
+
* serverUrl: 'https://ap.example.com',
|
|
20
|
+
* appName: 'myapp',
|
|
21
|
+
* apiKey: 'secret-key'
|
|
22
|
+
* });
|
|
23
|
+
*/
|
|
8
24
|
export class ActivityPubBackend extends StorageBackend {
|
|
25
|
+
/**
|
|
26
|
+
* Create a new ActivityPub backend instance.
|
|
27
|
+
* @param {Object} config - Backend configuration
|
|
28
|
+
* @param {string} config.serverUrl - ActivityPub server URL
|
|
29
|
+
* @param {string} [config.appName='holosphere'] - Application/actor name
|
|
30
|
+
* @param {string} [config.apiKey] - Optional API key for authentication
|
|
31
|
+
*/
|
|
9
32
|
constructor(config) {
|
|
10
33
|
super(config);
|
|
11
34
|
this.serverUrl = config.serverUrl;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GunDB
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview GunDB storage backend with authentication, schema validation, references, and global tables.
|
|
3
|
+
* Provides full-featured P2P data storage using GunDB with write caching for immediate consistency.
|
|
4
|
+
* @module storage/backends/gundb-backend
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import { StorageBackend } from '../backend-interface.js';
|
|
@@ -10,7 +11,33 @@ import { GunReferenceHandler } from '../gun-references.js';
|
|
|
10
11
|
import { GunAuth } from '../gun-auth.js';
|
|
11
12
|
import { GunSchemaValidator } from '../gun-schema.js';
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* GunDB storage backend implementation with advanced features.
|
|
16
|
+
* Supports authentication, schema validation, references, global tables,
|
|
17
|
+
* and write caching for immediate consistency.
|
|
18
|
+
*
|
|
19
|
+
* @class GunDBBackend
|
|
20
|
+
* @extends StorageBackend
|
|
21
|
+
* @example
|
|
22
|
+
* const backend = await BackendFactory.create('gundb', {
|
|
23
|
+
* appName: 'myapp',
|
|
24
|
+
* peers: ['wss://gun-server.example.com/gun'],
|
|
25
|
+
* radisk: true
|
|
26
|
+
* });
|
|
27
|
+
*/
|
|
13
28
|
export class GunDBBackend extends StorageBackend {
|
|
29
|
+
/**
|
|
30
|
+
* Create a new GunDB backend instance.
|
|
31
|
+
* @param {Object} config - Backend configuration
|
|
32
|
+
* @param {string} [config.appName='holosphere'] - Application namespace
|
|
33
|
+
* @param {string[]} [config.peers=[]] - Array of peer URLs
|
|
34
|
+
* @param {boolean} [config.radisk=true] - Enable radisk persistence
|
|
35
|
+
* @param {boolean} [config.localStorage=true] - Enable localStorage
|
|
36
|
+
* @param {string} [config.dataDir='radata'] - Data directory for Node.js
|
|
37
|
+
* @param {string} [config.privateKey] - Optional existing private key
|
|
38
|
+
* @param {string} [config.publicKey] - Optional existing public key
|
|
39
|
+
* @param {boolean} [config.strict=false] - Enable strict schema validation
|
|
40
|
+
*/
|
|
14
41
|
constructor(config) {
|
|
15
42
|
super(config);
|
|
16
43
|
this.gun = null;
|
|
@@ -25,28 +52,61 @@ export class GunDBBackend extends StorageBackend {
|
|
|
25
52
|
// Subscription tracking
|
|
26
53
|
this.subscriptions = new Map();
|
|
27
54
|
this.subscriptionCounter = 0;
|
|
55
|
+
|
|
56
|
+
// Write cache for immediate consistency
|
|
57
|
+
// Gun's readAll/map().once() doesn't immediately see new writes - this cache bridges that gap
|
|
58
|
+
this.writeCache = new Map(); // path -> Map(id -> {data, timestamp})
|
|
59
|
+
this.writeCacheTTL = 300000; // Cache entries expire after 5 minutes (increased from 30s)
|
|
60
|
+
|
|
61
|
+
// Pending writes queue for retry
|
|
62
|
+
this.pendingWrites = new Map(); // path -> {data, retries, lastAttempt}
|
|
63
|
+
this.maxWriteRetries = 5;
|
|
64
|
+
this.writeRetryInterval = 10000; // 10 seconds between retries
|
|
28
65
|
}
|
|
29
66
|
|
|
30
67
|
async init() {
|
|
31
68
|
// Dynamically import Gun to avoid issues if not installed
|
|
32
69
|
let Gun;
|
|
33
70
|
try {
|
|
71
|
+
console.log('[gundb-backend] Importing Gun...');
|
|
34
72
|
const gunModule = await import('gun');
|
|
35
73
|
Gun = gunModule.default || gunModule;
|
|
74
|
+
console.log('[gundb-backend] Gun imported:', typeof Gun);
|
|
36
75
|
} catch (error) {
|
|
37
76
|
throw new Error(
|
|
38
77
|
'GunDB backend requires the "gun" package. Install it with: npm install gun'
|
|
39
78
|
);
|
|
40
79
|
}
|
|
41
80
|
|
|
81
|
+
// In Node.js, Gun needs a file path for radisk persistence
|
|
82
|
+
// Default to 'radata' if not specified
|
|
83
|
+
const dataDir = this.config.dataDir || 'radata';
|
|
84
|
+
|
|
42
85
|
const gunConfig = {
|
|
43
86
|
peers: this.config.peers || [],
|
|
44
87
|
radisk: this.config.radisk !== false,
|
|
45
88
|
localStorage: this.config.localStorage !== false,
|
|
46
|
-
file:
|
|
89
|
+
file: dataDir,
|
|
47
90
|
};
|
|
48
91
|
|
|
92
|
+
console.log('[gundb-backend] Gun config:', JSON.stringify(gunConfig));
|
|
93
|
+
|
|
49
94
|
this.gun = Gun(gunConfig);
|
|
95
|
+
console.log('[gundb-backend] Gun instance created:', !!this.gun);
|
|
96
|
+
|
|
97
|
+
// Test basic Gun functionality
|
|
98
|
+
try {
|
|
99
|
+
const testKey = `_test_${Date.now()}`;
|
|
100
|
+
this.gun.get(testKey).put({ test: true }, (ack) => {
|
|
101
|
+
console.log('[gundb-backend] Gun test write ack:', ack);
|
|
102
|
+
});
|
|
103
|
+
console.log('[gundb-backend] Gun test write initiated');
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.error('[gundb-backend] Gun test write failed:', e.message);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Add a small delay to let Gun initialize
|
|
109
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
50
110
|
|
|
51
111
|
// Generate or use provided key pair using Gun's SEA
|
|
52
112
|
try {
|
|
@@ -82,6 +142,111 @@ export class GunDBBackend extends StorageBackend {
|
|
|
82
142
|
await this.schemaValidator.init();
|
|
83
143
|
}
|
|
84
144
|
|
|
145
|
+
// ============================================================================
|
|
146
|
+
// WRITE CACHE (for immediate consistency)
|
|
147
|
+
// ============================================================================
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Add item to the local write cache for immediate consistency
|
|
151
|
+
* @private
|
|
152
|
+
*/
|
|
153
|
+
_addToWriteCache(path, data) {
|
|
154
|
+
if (!data || !data.id) return;
|
|
155
|
+
|
|
156
|
+
// Extract the parent path (without the data id)
|
|
157
|
+
const parentPath = path.substring(0, path.lastIndexOf('/'));
|
|
158
|
+
if (!parentPath) return;
|
|
159
|
+
|
|
160
|
+
if (!this.writeCache.has(parentPath)) {
|
|
161
|
+
this.writeCache.set(parentPath, new Map());
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const pathCache = this.writeCache.get(parentPath);
|
|
165
|
+
pathCache.set(data.id.toString(), {
|
|
166
|
+
data: data,
|
|
167
|
+
timestamp: Date.now()
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Remove item from write cache (e.g., on delete)
|
|
173
|
+
* @private
|
|
174
|
+
*/
|
|
175
|
+
_removeFromWriteCache(path, id) {
|
|
176
|
+
// Extract the parent path
|
|
177
|
+
const parentPath = path.substring(0, path.lastIndexOf('/'));
|
|
178
|
+
const pathCache = this.writeCache.get(parentPath);
|
|
179
|
+
if (pathCache) {
|
|
180
|
+
pathCache.delete(id.toString());
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get cached writes for a path, filtering out expired entries
|
|
186
|
+
* @private
|
|
187
|
+
*/
|
|
188
|
+
_getWriteCacheEntries(path) {
|
|
189
|
+
const pathCache = this.writeCache.get(path);
|
|
190
|
+
if (!pathCache) return [];
|
|
191
|
+
|
|
192
|
+
const now = Date.now();
|
|
193
|
+
const validEntries = [];
|
|
194
|
+
|
|
195
|
+
for (const [id, entry] of pathCache) {
|
|
196
|
+
if (now - entry.timestamp < this.writeCacheTTL) {
|
|
197
|
+
validEntries.push(entry.data);
|
|
198
|
+
} else {
|
|
199
|
+
// Clean up expired entries
|
|
200
|
+
pathCache.delete(id);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return validEntries;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Merge cached writes with results from Gun
|
|
209
|
+
* @private
|
|
210
|
+
*/
|
|
211
|
+
_mergeWithWriteCache(path, gunResults) {
|
|
212
|
+
const cachedWrites = this._getWriteCacheEntries(path);
|
|
213
|
+
if (cachedWrites.length === 0) return gunResults;
|
|
214
|
+
|
|
215
|
+
// Create a map by ID for deduplication
|
|
216
|
+
const resultMap = new Map();
|
|
217
|
+
|
|
218
|
+
// Add Gun results first
|
|
219
|
+
for (const item of gunResults) {
|
|
220
|
+
if (item && item.id) {
|
|
221
|
+
resultMap.set(item.id.toString(), item);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Overlay cached writes (they're more recent)
|
|
226
|
+
for (const item of cachedWrites) {
|
|
227
|
+
if (item && item.id && !item._deleted) {
|
|
228
|
+
resultMap.set(item.id.toString(), item);
|
|
229
|
+
} else if (item && item.id && item._deleted) {
|
|
230
|
+
// Remove deleted items
|
|
231
|
+
resultMap.delete(item.id.toString());
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return Array.from(resultMap.values());
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Clear write cache for a specific path or all paths
|
|
240
|
+
* @param {string} [path] - Optional path to clear, clears all if not provided
|
|
241
|
+
*/
|
|
242
|
+
clearWriteCache(path = null) {
|
|
243
|
+
if (path) {
|
|
244
|
+
this.writeCache.delete(path);
|
|
245
|
+
} else {
|
|
246
|
+
this.writeCache.clear();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
85
250
|
// ============================================================================
|
|
86
251
|
// PATH BUILDING
|
|
87
252
|
// ============================================================================
|
|
@@ -116,7 +281,59 @@ export class GunDBBackend extends StorageBackend {
|
|
|
116
281
|
}
|
|
117
282
|
}
|
|
118
283
|
|
|
119
|
-
|
|
284
|
+
// Add to write cache FIRST for immediate consistency
|
|
285
|
+
// This ensures readAll returns the new data even if Gun write is slow/times out
|
|
286
|
+
this._addToWriteCache(path, data);
|
|
287
|
+
|
|
288
|
+
// Try to write to Gun with retry on timeout
|
|
289
|
+
const result = await this._writeWithRetry(path, data);
|
|
290
|
+
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Write to Gun with automatic retry on timeout
|
|
296
|
+
* @private
|
|
297
|
+
*/
|
|
298
|
+
async _writeWithRetry(path, data, attempt = 0) {
|
|
299
|
+
const result = await wrapper.write(this.gun, path, data);
|
|
300
|
+
|
|
301
|
+
if (result.timeout && attempt < this.maxWriteRetries) {
|
|
302
|
+
// Queue for background retry
|
|
303
|
+
this.pendingWrites.set(path, {
|
|
304
|
+
data,
|
|
305
|
+
retries: attempt + 1,
|
|
306
|
+
lastAttempt: Date.now()
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Schedule retry
|
|
310
|
+
this._scheduleRetry(path);
|
|
311
|
+
} else if (!result.timeout) {
|
|
312
|
+
// Success - remove from pending
|
|
313
|
+
this.pendingWrites.delete(path);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Schedule a background retry for a pending write
|
|
321
|
+
* @private
|
|
322
|
+
*/
|
|
323
|
+
_scheduleRetry(path) {
|
|
324
|
+
setTimeout(async () => {
|
|
325
|
+
const pending = this.pendingWrites.get(path);
|
|
326
|
+
if (!pending) return;
|
|
327
|
+
|
|
328
|
+
if (pending.retries >= this.maxWriteRetries) {
|
|
329
|
+
console.warn(`[gundb-backend] Max retries reached for: ${path}`);
|
|
330
|
+
this.pendingWrites.delete(path);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
console.log(`[gundb-backend] Retrying write (attempt ${pending.retries + 1}): ${path}`);
|
|
335
|
+
await this._writeWithRetry(path, pending.data, pending.retries);
|
|
336
|
+
}, this.writeRetryInterval);
|
|
120
337
|
}
|
|
121
338
|
|
|
122
339
|
async read(path, options = {}) {
|
|
@@ -131,7 +348,10 @@ export class GunDBBackend extends StorageBackend {
|
|
|
131
348
|
}
|
|
132
349
|
|
|
133
350
|
async readAll(path, options = {}) {
|
|
134
|
-
const
|
|
351
|
+
const gunItems = await wrapper.readAll(this.gun, path);
|
|
352
|
+
|
|
353
|
+
// Merge with write cache for immediate consistency
|
|
354
|
+
const items = this._mergeWithWriteCache(path, gunItems);
|
|
135
355
|
|
|
136
356
|
// Resolve references if requested
|
|
137
357
|
if (options.resolveReferences) {
|
|
@@ -157,7 +377,24 @@ export class GunDBBackend extends StorageBackend {
|
|
|
157
377
|
}
|
|
158
378
|
|
|
159
379
|
async delete(path) {
|
|
160
|
-
|
|
380
|
+
const result = await wrapper.deleteData(this.gun, path);
|
|
381
|
+
|
|
382
|
+
// Extract id from path and mark as deleted in cache
|
|
383
|
+
const pathParts = path.split('/');
|
|
384
|
+
const id = pathParts[pathParts.length - 1];
|
|
385
|
+
if (id) {
|
|
386
|
+
// Add tombstone to cache so readAll doesn't return this item
|
|
387
|
+
const parentPath = path.substring(0, path.lastIndexOf('/'));
|
|
388
|
+
if (!this.writeCache.has(parentPath)) {
|
|
389
|
+
this.writeCache.set(parentPath, new Map());
|
|
390
|
+
}
|
|
391
|
+
this.writeCache.get(parentPath).set(id.toString(), {
|
|
392
|
+
data: { id, _deleted: true },
|
|
393
|
+
timestamp: Date.now()
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return result;
|
|
161
398
|
}
|
|
162
399
|
|
|
163
400
|
async deleteAll(path) {
|
|
@@ -180,7 +417,62 @@ export class GunDBBackend extends StorageBackend {
|
|
|
180
417
|
// ============================================================================
|
|
181
418
|
|
|
182
419
|
async writeGlobal(tableName, data) {
|
|
183
|
-
|
|
420
|
+
// Add to write cache FIRST for immediate consistency
|
|
421
|
+
// This ensures readAllGlobal returns the new data even if Gun write is slow/times out
|
|
422
|
+
const path = this.buildGlobalPath(tableName, data.id);
|
|
423
|
+
this._addToWriteCache(path, data);
|
|
424
|
+
|
|
425
|
+
// Try to write to Gun with retry on timeout
|
|
426
|
+
const result = await this._writeGlobalWithRetry(tableName, data);
|
|
427
|
+
|
|
428
|
+
return result;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Write to global table with automatic retry on timeout
|
|
433
|
+
* @private
|
|
434
|
+
*/
|
|
435
|
+
async _writeGlobalWithRetry(tableName, data, attempt = 0) {
|
|
436
|
+
const path = this.buildGlobalPath(tableName, data.id);
|
|
437
|
+
const result = await wrapper.writeGlobal(this.gun, this.appName, tableName, data);
|
|
438
|
+
|
|
439
|
+
if (result.timeout && attempt < this.maxWriteRetries) {
|
|
440
|
+
// Queue for background retry
|
|
441
|
+
this.pendingWrites.set(path, {
|
|
442
|
+
data: { tableName, data },
|
|
443
|
+
isGlobal: true,
|
|
444
|
+
retries: attempt + 1,
|
|
445
|
+
lastAttempt: Date.now()
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// Schedule retry
|
|
449
|
+
this._scheduleGlobalRetry(path, tableName);
|
|
450
|
+
} else if (!result.timeout) {
|
|
451
|
+
// Success - remove from pending
|
|
452
|
+
this.pendingWrites.delete(path);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Schedule a background retry for a pending global write
|
|
460
|
+
* @private
|
|
461
|
+
*/
|
|
462
|
+
_scheduleGlobalRetry(path, tableName) {
|
|
463
|
+
setTimeout(async () => {
|
|
464
|
+
const pending = this.pendingWrites.get(path);
|
|
465
|
+
if (!pending || !pending.isGlobal) return;
|
|
466
|
+
|
|
467
|
+
if (pending.retries >= this.maxWriteRetries) {
|
|
468
|
+
console.warn(`[gundb-backend] Max retries reached for global: ${path}`);
|
|
469
|
+
this.pendingWrites.delete(path);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
console.log(`[gundb-backend] Retrying global write (attempt ${pending.retries + 1}): ${path}`);
|
|
474
|
+
await this._writeGlobalWithRetry(tableName, pending.data.data, pending.retries);
|
|
475
|
+
}, this.writeRetryInterval);
|
|
184
476
|
}
|
|
185
477
|
|
|
186
478
|
async readGlobal(tableName, key) {
|
|
@@ -188,11 +480,27 @@ export class GunDBBackend extends StorageBackend {
|
|
|
188
480
|
}
|
|
189
481
|
|
|
190
482
|
async readAllGlobal(tableName, timeout = 5000) {
|
|
191
|
-
|
|
483
|
+
const gunItems = await wrapper.readAllGlobal(this.gun, this.appName, tableName, timeout);
|
|
484
|
+
|
|
485
|
+
// Merge with write cache for immediate consistency
|
|
486
|
+
const path = this.buildGlobalPath(tableName);
|
|
487
|
+
return this._mergeWithWriteCache(path, gunItems);
|
|
192
488
|
}
|
|
193
489
|
|
|
194
490
|
async deleteGlobal(tableName, key) {
|
|
195
|
-
|
|
491
|
+
const result = await wrapper.deleteGlobal(this.gun, this.appName, tableName, key);
|
|
492
|
+
|
|
493
|
+
// Mark as deleted in cache
|
|
494
|
+
const path = this.buildGlobalPath(tableName);
|
|
495
|
+
if (!this.writeCache.has(path)) {
|
|
496
|
+
this.writeCache.set(path, new Map());
|
|
497
|
+
}
|
|
498
|
+
this.writeCache.get(path).set(key.toString(), {
|
|
499
|
+
data: { id: key, _deleted: true },
|
|
500
|
+
timestamp: Date.now()
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
return result;
|
|
196
504
|
}
|
|
197
505
|
|
|
198
506
|
async deleteAllGlobal(tableName) {
|
|
@@ -517,12 +825,15 @@ export class GunDBBackend extends StorageBackend {
|
|
|
517
825
|
this.schemaValidator.clearCache();
|
|
518
826
|
}
|
|
519
827
|
|
|
520
|
-
// 3.
|
|
828
|
+
// 3. Clear write cache
|
|
829
|
+
this.writeCache.clear();
|
|
830
|
+
|
|
831
|
+
// 4. Logout auth
|
|
521
832
|
if (this.auth) {
|
|
522
833
|
this.auth.logout();
|
|
523
834
|
}
|
|
524
835
|
|
|
525
|
-
//
|
|
836
|
+
// 5. Clean up Gun connections
|
|
526
837
|
if (this.gun) {
|
|
527
838
|
try {
|
|
528
839
|
// Clean up mesh connections
|