holosphere 2.0.0-alpha1 โ 2.0.0-alpha10
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 +473 -0
- package/FEATURES.md +431 -0
- package/LICENSE +29 -166
- package/LICENSE-AGPL.md +180 -0
- package/README.md +97 -16
- package/dist/2019-D2OG2idw.js +6680 -0
- package/dist/2019-D2OG2idw.js.map +1 -0
- package/dist/2019-EION3wKo.cjs +8 -0
- package/dist/2019-EION3wKo.cjs.map +1 -0
- package/dist/_commonjsHelpers-C37NGDzP.cjs +2 -0
- package/dist/_commonjsHelpers-C37NGDzP.cjs.map +1 -0
- package/dist/_commonjsHelpers-CUmg6egw.js +7 -0
- package/dist/_commonjsHelpers-CUmg6egw.js.map +1 -0
- package/dist/browser-BSniCNqO.js +3058 -0
- package/dist/browser-BSniCNqO.js.map +1 -0
- package/dist/browser-Cq59Ij19.cjs +2 -0
- package/dist/browser-Cq59Ij19.cjs.map +1 -0
- package/dist/cdn/holosphere.min.js +55 -0
- package/dist/cdn/holosphere.min.js.map +1 -0
- package/dist/cjs/holosphere.cjs +2 -0
- package/dist/cjs/holosphere.cjs.map +1 -0
- package/dist/esm/holosphere.js +53 -0
- package/dist/esm/holosphere.js.map +1 -0
- package/dist/index-DDGt_V9o.cjs +12 -0
- package/dist/index-DDGt_V9o.cjs.map +1 -0
- package/dist/index-DJXftyvB.js +39841 -0
- 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-DeZ1xz_s.js +15104 -0
- package/dist/index-DeZ1xz_s.js.map +1 -0
- package/dist/indexeddb-storage-BFt6hMeF.js +176 -0
- package/dist/indexeddb-storage-BFt6hMeF.js.map +1 -0
- package/dist/indexeddb-storage-BK5tv4Sh.cjs +2 -0
- package/dist/indexeddb-storage-BK5tv4Sh.cjs.map +1 -0
- package/dist/memory-storage-C9HuoL2E.js +91 -0
- package/dist/memory-storage-C9HuoL2E.js.map +1 -0
- package/dist/memory-storage-Dao7jfYG.cjs +2 -0
- package/dist/memory-storage-Dao7jfYG.cjs.map +1 -0
- package/dist/secp256k1-BbKzbLtD.cjs +12 -0
- package/dist/secp256k1-BbKzbLtD.cjs.map +1 -0
- package/dist/secp256k1-CreY7Pcl.js +1890 -0
- package/dist/secp256k1-CreY7Pcl.js.map +1 -0
- package/docs/CONTRACTS.md +797 -0
- package/docs/FOSDEM_PROPOSAL.md +388 -0
- package/docs/LOCALFIRST.md +266 -0
- 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/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/examples/demo.html +47 -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 +25 -7
- 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/abis/Appreciative.json +1280 -0
- package/src/contracts/abis/AppreciativeFactory.json +101 -0
- package/src/contracts/abis/Bundle.json +1438 -0
- package/src/contracts/abis/BundleFactory.json +106 -0
- package/src/contracts/abis/Holon.json +881 -0
- package/src/contracts/abis/Holons.json +330 -0
- package/src/contracts/abis/Managed.json +1262 -0
- package/src/contracts/abis/ManagedFactory.json +149 -0
- package/src/contracts/abis/Membrane.json +261 -0
- package/src/contracts/abis/Splitter.json +1624 -0
- package/src/contracts/abis/SplitterFactory.json +220 -0
- package/src/contracts/abis/TestToken.json +321 -0
- package/src/contracts/abis/Zoned.json +1461 -0
- package/src/contracts/abis/ZonedFactory.json +154 -0
- package/src/contracts/chain-manager.js +403 -0
- package/src/contracts/deployer.js +500 -0
- package/src/contracts/event-listener.js +539 -0
- package/src/contracts/holon-contracts.js +359 -0
- package/src/contracts/index.js +82 -0
- package/src/contracts/networks.js +229 -0
- package/src/contracts/operations.js +687 -0
- package/src/contracts/queries.js +638 -0
- package/src/core/holosphere.js +487 -6
- package/src/crypto/nostr-utils.js +303 -0
- package/src/crypto/secp256k1.js +7 -2
- package/src/federation/handshake.js +475 -0
- package/src/federation/hologram.js +117 -3
- package/src/hierarchical/upcast.js +40 -25
- package/src/index.js +1501 -1909
- package/src/lib/ai-methods.js +657 -0
- package/src/lib/contract-methods.js +442 -0
- package/src/lib/errors.js +53 -0
- package/src/lib/federation-methods.js +345 -0
- package/src/lib/index.js +30 -0
- package/src/schema/validator.js +22 -3
- package/src/spatial/h3-operations.js +19 -3
- 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 +692 -50
- 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 +35 -3
- package/src/storage/gun-async.js +75 -15
- package/src/storage/gun-auth.js +373 -0
- package/src/storage/gun-federation.js +785 -0
- package/src/storage/gun-references.js +209 -0
- package/src/storage/gun-schema.js +306 -0
- package/src/storage/gun-wrapper.js +475 -54
- package/src/storage/indexeddb-storage.js +112 -13
- package/src/storage/key-storage-simple.js +32 -9
- package/src/storage/key-storage.js +45 -13
- package/src/storage/memory-storage.js +68 -2
- package/src/storage/migration.js +20 -7
- package/src/storage/nostr-async.js +412 -122
- package/src/storage/nostr-client.js +749 -76
- package/src/storage/nostr-wrapper.js +6 -2
- package/src/storage/outbox-queue.js +55 -18
- package/src/storage/persistent-storage.js +62 -14
- package/src/storage/sync-service.js +51 -17
- package/src/storage/unified-storage.js +154 -0
- package/src/subscriptions/manager.js +34 -17
- package/types/index.d.ts +133 -0
- package/vite.config.cdn.js +60 -0
- 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
- /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
|
@@ -0,0 +1,1053 @@
|
|
|
1
|
+
<!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: federation/hologram.js</title><!--[if lt IE 9]>
|
|
2
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
3
|
+
<![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="dark"><div class="sidebar-container"><div class="sidebar" id="sidebar"><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai.html">ai</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation.html">ai/aggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.html">ai/breakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.html">ai/classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.html">ai/council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.html">ai/embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.html">ai/federation-ai</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.html">ai/h3-ai</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.html">ai/json-ops</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.html">ai/llm-service</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.html">ai/nl-query</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.html">ai/relationships</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.html">ai/schema-extractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.html">ai/spatial</a></div><div class="sidebar-section-children"><a href="module-ai_tts.html">ai/tts</a></div><div class="sidebar-section-children"><a href="module-content_social-protocols.html">content/social-protocols</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.html">core/holosphere</a></div><div class="sidebar-section-children"><a href="module-crypto_nostr-utils.html">crypto/nostr-utils</a></div><div class="sidebar-section-children"><a href="module-crypto_secp256k1.html">crypto/secp256k1</a></div><div class="sidebar-section-children"><a href="module-federation_hologram.html">federation/hologram</a></div><div class="sidebar-section-children"><a href="module-hierarchical_upcast.html">hierarchical/upcast</a></div><div class="sidebar-section-children"><a href="module-holosphere.html">holosphere</a></div><div class="sidebar-section-children"><a href="module-lib_ai-methods.html">lib/ai-methods</a></div><div class="sidebar-section-children"><a href="module-lib_contract-methods.html">lib/contract-methods</a></div><div class="sidebar-section-children"><a href="module-lib_errors.html">lib/errors</a></div><div class="sidebar-section-children"><a href="module-lib_federation-methods.html">lib/federation-methods</a></div><div class="sidebar-section-children"><a href="module-lib_index.html">lib/index</a></div><div class="sidebar-section-children"><a href="module-schema_validator.html">schema/validator</a></div><div class="sidebar-section-children"><a href="module-spatial_h3-operations.html">spatial/h3-operations</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.html">storage/backend-factory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.html">storage/backend-interface</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.html">storage/backends/activitypub-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.html">storage/backends/activitypub/server</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.html">storage/backends/gundb-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.html">storage/backends/nostr-backend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.html">storage/filesystem-storage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.html">storage/filesystem-storage-browser</a></div><div class="sidebar-section-children"><a href="module-storage_global-tables.html">storage/global-tables</a></div><div class="sidebar-section-children"><a href="module-storage_gun-async.html">storage/gun-async</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.html">storage/gun-auth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-federation.html">storage/gun-federation</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.html">storage/gun-references</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.html">storage/gun-schema</a></div><div class="sidebar-section-children"><a href="module-storage_gun-wrapper.html">storage/gun-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.html">storage/indexeddb-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage.html">storage/key-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage-simple.html">storage/key-storage-simple</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.html">storage/memory-storage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.html">storage/migration</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-async.html">storage/nostr-async</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.html">storage/nostr-client</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-wrapper.html">storage/nostr-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.html">storage/outbox-queue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage.html">storage/persistent-storage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.html">storage/sync-service</a></div><div class="sidebar-section-children"><a href="module-storage_unified-storage.html">storage/unified-storage</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.html">subscriptions/manager</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai_aggregation.SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation-SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown-TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_classifier-Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_council-Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings-Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai-FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai-H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops-JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service-LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query-NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships-RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor-SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_spatial-SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_tts.TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-ai_tts-TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-core_holosphere-HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-lib_errors.AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.BackendFactory.html">BackendFactory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface-StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend-ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server-ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend-GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend-NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth-GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references-GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema-GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage-IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage-MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_migration-MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-LRUCache.html">LRUCache</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue-OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage-PersistentStorage.html">PersistentStorage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service-SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.SubscriptionRegistry.html">SubscriptionRegistry</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#FederationRequestPayload">FederationRequestPayload</a></div><div class="sidebar-section-children"><a href="global.html#FederationResponsePayload">FederationResponsePayload</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#addFederatedPartner">addFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#cleanupExpiredCapabilities">cleanupExpiredCapabilities</a></div><div class="sidebar-section-children"><a href="global.html#createFederationRequest">createFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#createFederationResponse">createFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#declineFederationRequest">declineFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#getCapabilityForAuthor">getCapabilityForAuthor</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthors">getFederatedAuthors</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthorsForScope">getFederatedAuthorsForScope</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedPartner">getFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#getFederationRegistry">getFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#getPendingFederationRequests">getPendingFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#initiateFederationHandshake">initiateFederationHandshake</a></div><div class="sidebar-section-children"><a href="global.html#isFederationRequest">isFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#isFederationResponse">isFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#rejectFederationRequest">rejectFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#removeFederatedPartner">removeFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#revokeOutboundCapability">revokeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#saveFederationRegistry">saveFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationResponse">sendFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#storeInboundCapability">storeInboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#storeOutboundCapability">storeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationAcceptances">subscribeFederationAcceptances</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationDeclines">subscribeFederationDeclines</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationRequests">subscribeFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#subscribeToFederationDMs">subscribeToFederationDMs</a></div><div class="sidebar-section-children"><a href="global.html#updateDiscoverySettings">updateDiscoverySettings</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section id="source-page" class="source-page"><header><h1 id="title" class="has-anchor">federation_hologram.js</h1></header><article><pre class="prettyprint source lang-js"><code>/**
|
|
4
|
+
* @fileoverview Federation and Hologram (Reference) Management.
|
|
5
|
+
*
|
|
6
|
+
* Provides hologram (lightweight reference) creation, resolution, and management.
|
|
7
|
+
* Holograms enable data to appear in multiple holons while maintaining a single
|
|
8
|
+
* source of truth. Supports circular reference detection and cross-holosphere
|
|
9
|
+
* federation with capability-based access control.
|
|
10
|
+
*
|
|
11
|
+
* @module federation/hologram
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { buildPath, write, read, update } from '../storage/unified-storage.js';
|
|
15
|
+
import { verifyCapability } from '../crypto/secp256k1.js';
|
|
16
|
+
import { getCapabilityForAuthor } from './registry.js';
|
|
17
|
+
|
|
18
|
+
/** @constant {number} Maximum depth for hologram resolution chain */
|
|
19
|
+
const MAX_RESOLUTION_DEPTH = 10;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check if creating a hologram would result in a circular reference
|
|
23
|
+
* This follows the chain from the source to see if it eventually points back to the target
|
|
24
|
+
* @param {Object} client - Nostr client instance
|
|
25
|
+
* @param {string} appname - Application namespace
|
|
26
|
+
* @param {string} sourceHolon - Source holon ID (where original data lives)
|
|
27
|
+
* @param {string} targetHolon - Target holon ID (where hologram would be created)
|
|
28
|
+
* @param {string} lensName - Lens name
|
|
29
|
+
* @param {string} dataId - Data ID
|
|
30
|
+
* @returns {Promise<Object>} Result with { isCircular, chain }
|
|
31
|
+
*/
|
|
32
|
+
export async function wouldCreateCircularHologram(client, appname, sourceHolon, targetHolon, lensName, dataId) {
|
|
33
|
+
const visited = new Set();
|
|
34
|
+
const chain = [];
|
|
35
|
+
|
|
36
|
+
let currentHolon = sourceHolon;
|
|
37
|
+
let currentLens = lensName;
|
|
38
|
+
let currentDataId = dataId;
|
|
39
|
+
let currentAppname = appname;
|
|
40
|
+
|
|
41
|
+
// Follow the chain to see if we eventually reach targetHolon
|
|
42
|
+
while (visited.size < MAX_RESOLUTION_DEPTH) {
|
|
43
|
+
const key = `${currentAppname}:${currentHolon}:${currentLens}:${currentDataId}`;
|
|
44
|
+
|
|
45
|
+
if (visited.has(key)) {
|
|
46
|
+
// Already visited this node - there's a cycle in the existing chain
|
|
47
|
+
return { isCircular: true, chain, reason: 'existing_cycle' };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
visited.add(key);
|
|
51
|
+
chain.push({ holon: currentHolon, lens: currentLens, dataId: currentDataId });
|
|
52
|
+
|
|
53
|
+
// Check if current holon is our target - this would create a circular reference
|
|
54
|
+
if (currentHolon === targetHolon) {
|
|
55
|
+
return { isCircular: true, chain, reason: 'would_create_cycle' };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Read the data at current location
|
|
59
|
+
const path = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
|
|
60
|
+
const data = await read(client, path);
|
|
61
|
+
|
|
62
|
+
if (!data) {
|
|
63
|
+
// Data doesn't exist - no circular reference possible from this chain
|
|
64
|
+
return { isCircular: false, chain };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!data.hologram || !data.target) {
|
|
68
|
+
// Not a hologram - chain ends here, no circular reference
|
|
69
|
+
return { isCircular: false, chain };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Follow the hologram to its target
|
|
73
|
+
currentAppname = data.target.appname || currentAppname;
|
|
74
|
+
currentHolon = data.target.holonId;
|
|
75
|
+
currentLens = data.target.lensName || currentLens;
|
|
76
|
+
currentDataId = data.target.dataId || currentDataId;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Max depth reached - treat as potential circular to be safe
|
|
80
|
+
return { isCircular: true, chain, reason: 'max_depth_exceeded' };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Create a hologram (lightweight reference)
|
|
85
|
+
* @param {string} sourceHolon - Source holon ID
|
|
86
|
+
* @param {string} targetHolon - Target holon ID
|
|
87
|
+
* @param {string} lensName - Lens name
|
|
88
|
+
* @param {string} dataId - Data ID
|
|
89
|
+
* @param {string} appname - Application namespace
|
|
90
|
+
* @param {Object} options - Optional cross-holosphere settings
|
|
91
|
+
* @param {string} options.authorPubKey - Source author's public key (for cross-holosphere)
|
|
92
|
+
* @param {string} options.capability - Capability token (for cross-holosphere)
|
|
93
|
+
* @returns {Object} Hologram object
|
|
94
|
+
*/
|
|
95
|
+
export function createHologram(sourceHolon, targetHolon, lensName, dataId, appname, options = {}) {
|
|
96
|
+
const { authorPubKey = null, capability = null } = options;
|
|
97
|
+
|
|
98
|
+
const soul = buildPath(appname, sourceHolon, lensName, dataId);
|
|
99
|
+
|
|
100
|
+
const hologram = {
|
|
101
|
+
id: dataId,
|
|
102
|
+
hologram: true,
|
|
103
|
+
soul,
|
|
104
|
+
target: {
|
|
105
|
+
appname,
|
|
106
|
+
holonId: sourceHolon,
|
|
107
|
+
lensName,
|
|
108
|
+
dataId,
|
|
109
|
+
},
|
|
110
|
+
_meta: {
|
|
111
|
+
created: Date.now(),
|
|
112
|
+
sourceHolon,
|
|
113
|
+
source: sourceHolon, // Alias for compatibility
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Cross-holosphere enhancements
|
|
118
|
+
if (authorPubKey) {
|
|
119
|
+
hologram.crossHolosphere = true;
|
|
120
|
+
hologram.target.authorPubKey = authorPubKey;
|
|
121
|
+
hologram._meta.sourcePubKey = authorPubKey;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (capability) {
|
|
125
|
+
hologram.capability = capability;
|
|
126
|
+
hologram._meta.grantedAt = Date.now();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return hologram;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Resolve hologram to actual data, merging local overrides
|
|
134
|
+
* Supports cross-holosphere holograms with capability token verification
|
|
135
|
+
* @param {Object} client - Nostr client instance
|
|
136
|
+
* @param {Object} hologram - Hologram object
|
|
137
|
+
* @param {Set} visited - Visited souls (circular reference detection)
|
|
138
|
+
* @param {Array} chain - Chain of souls for debugging circular references
|
|
139
|
+
* @param {Object} options - Resolution options
|
|
140
|
+
* @param {string} options.appname - Application namespace (for registry lookup)
|
|
141
|
+
* @param {boolean} options.deleteCircular - If true, delete circular holograms when detected (default: true)
|
|
142
|
+
* @param {string} options.hologramPath - Path of the hologram being resolved (for deletion)
|
|
143
|
+
* @returns {Promise<Object|null>} Resolved data with _hologram metadata, or null
|
|
144
|
+
*/
|
|
145
|
+
export async function resolveHologram(client, hologram, visited = new Set(), chain = [], options = {}) {
|
|
146
|
+
const { deleteCircular = true, hologramPath = null } = options;
|
|
147
|
+
|
|
148
|
+
if (!hologram || !hologram.hologram) {
|
|
149
|
+
return hologram; // Not a hologram, return as-is
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const { soul } = hologram;
|
|
153
|
+
const target = hologram.target || {};
|
|
154
|
+
|
|
155
|
+
// Circular reference detection
|
|
156
|
+
if (visited.has(soul)) {
|
|
157
|
+
const chainStr = [...chain, soul].join(' โ ');
|
|
158
|
+
console.warn(`๐ Circular reference detected - removing hologram`);
|
|
159
|
+
console.warn(` Soul: ${soul}`);
|
|
160
|
+
console.warn(` Chain: ${chainStr}`);
|
|
161
|
+
console.warn(` Source holon: ${target.holonId || 'unknown'}`);
|
|
162
|
+
console.warn(` Lens: ${target.lensName || 'unknown'}`);
|
|
163
|
+
console.warn(` Data ID: ${target.dataId || hologram.id || 'unknown'}`);
|
|
164
|
+
console.warn(` Resolution depth: ${visited.size}`);
|
|
165
|
+
|
|
166
|
+
// Delete the circular hologram
|
|
167
|
+
if (deleteCircular && hologramPath) {
|
|
168
|
+
console.info(` ๐๏ธ Deleting circular hologram at: ${hologramPath}`);
|
|
169
|
+
await write(client, hologramPath, null);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (visited.size >= MAX_RESOLUTION_DEPTH) {
|
|
176
|
+
const chainStr = [...chain, soul].join(' โ ');
|
|
177
|
+
console.warn(`โ ๏ธ Max resolution depth (${MAX_RESOLUTION_DEPTH}) exceeded - removing hologram`);
|
|
178
|
+
console.warn(` Current soul: ${soul}`);
|
|
179
|
+
console.warn(` Chain: ${chainStr}`);
|
|
180
|
+
console.warn(` Source holon: ${target.holonId || 'unknown'}`);
|
|
181
|
+
console.warn(` Lens: ${target.lensName || 'unknown'}`);
|
|
182
|
+
|
|
183
|
+
// Delete the problematic hologram
|
|
184
|
+
if (deleteCircular && hologramPath) {
|
|
185
|
+
console.info(` ๐๏ธ Deleting deep chain hologram at: ${hologramPath}`);
|
|
186
|
+
await write(client, hologramPath, null);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
visited.add(soul);
|
|
193
|
+
chain.push(soul);
|
|
194
|
+
|
|
195
|
+
let sourceData;
|
|
196
|
+
|
|
197
|
+
// Handle cross-holosphere holograms
|
|
198
|
+
if (hologram.crossHolosphere && target.authorPubKey) {
|
|
199
|
+
// Get capability - try embedded first, then registry fallback
|
|
200
|
+
let capability = hologram.capability;
|
|
201
|
+
|
|
202
|
+
if (!capability && options.appname) {
|
|
203
|
+
// Fallback to registry lookup
|
|
204
|
+
const capEntry = await getCapabilityForAuthor(
|
|
205
|
+
client,
|
|
206
|
+
options.appname,
|
|
207
|
+
target.authorPubKey,
|
|
208
|
+
{
|
|
209
|
+
holonId: target.holonId,
|
|
210
|
+
lensName: target.lensName,
|
|
211
|
+
dataId: target.dataId,
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
if (capEntry) {
|
|
215
|
+
capability = capEntry.token;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Verify capability before resolving
|
|
220
|
+
if (!capability) {
|
|
221
|
+
console.warn(`โ Cross-holosphere hologram missing capability: ${soul}`);
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const isValid = await verifyCapability(
|
|
226
|
+
capability,
|
|
227
|
+
'read',
|
|
228
|
+
{
|
|
229
|
+
holonId: target.holonId,
|
|
230
|
+
lensName: target.lensName,
|
|
231
|
+
dataId: target.dataId,
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
if (!isValid) {
|
|
236
|
+
console.warn(`โ Capability verification failed for cross-holosphere hologram: ${soul}`);
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Read from federated source (different author)
|
|
241
|
+
sourceData = await read(client, soul, {
|
|
242
|
+
authors: [target.authorPubKey]
|
|
243
|
+
});
|
|
244
|
+
} else {
|
|
245
|
+
// Same-holosphere resolution (original behavior)
|
|
246
|
+
sourceData = await read(client, soul);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (!sourceData) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// If source data is also a hologram, recursively resolve
|
|
254
|
+
if (sourceData.hologram) {
|
|
255
|
+
// Pass the soul as the hologramPath so circular holograms can be deleted
|
|
256
|
+
return resolveHologram(client, sourceData, visited, chain, { ...options, hologramPath: soul });
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Merge hologram with source data
|
|
260
|
+
return mergeHologramWithSource(hologram, sourceData);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Merge hologram local overrides with source data
|
|
265
|
+
* @private
|
|
266
|
+
* @param {Object} hologram - Hologram object
|
|
267
|
+
* @param {Object} sourceData - Source data
|
|
268
|
+
* @returns {Object} Merged data with _hologram metadata
|
|
269
|
+
*/
|
|
270
|
+
function mergeHologramWithSource(hologram, sourceData) {
|
|
271
|
+
// Extract local overrides from the hologram (exclude hologram-specific fields)
|
|
272
|
+
const hologramOnlyFields = ['hologram', 'soul', 'target', '_meta', 'id', 'capability', 'crossHolosphere'];
|
|
273
|
+
const localOverrides = {};
|
|
274
|
+
const localOverrideKeys = [];
|
|
275
|
+
|
|
276
|
+
for (const key of Object.keys(hologram)) {
|
|
277
|
+
if (!hologramOnlyFields.includes(key)) {
|
|
278
|
+
localOverrides[key] = hologram[key];
|
|
279
|
+
localOverrideKeys.push(key);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Merge: source data + local overrides + hologram metadata
|
|
284
|
+
const sourceHolon = hologram._meta?.sourceHolon || hologram._meta?.source || hologram.target?.holonId;
|
|
285
|
+
const resolved = {
|
|
286
|
+
...sourceData, // Original data from source
|
|
287
|
+
...localOverrides, // Local overrides (x, y, pinned, etc.)
|
|
288
|
+
_hologram: {
|
|
289
|
+
isHologram: true,
|
|
290
|
+
soul: hologram.soul,
|
|
291
|
+
sourceHolon: sourceHolon,
|
|
292
|
+
localOverrides: localOverrideKeys,
|
|
293
|
+
crossHolosphere: hologram.crossHolosphere || false,
|
|
294
|
+
sourcePubKey: hologram._meta?.sourcePubKey || null,
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// Preserve original _meta and add source from hologram
|
|
299
|
+
if (sourceData._meta) {
|
|
300
|
+
resolved._meta = { ...sourceData._meta, source: sourceHolon };
|
|
301
|
+
} else {
|
|
302
|
+
resolved._meta = { source: sourceHolon };
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return resolved;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Setup federation between holons
|
|
310
|
+
* @param {Object} client - Nostr client instance
|
|
311
|
+
* @param {string} appname - Application namespace
|
|
312
|
+
* @param {string} sourceHolon - Source holon ID
|
|
313
|
+
* @param {string} targetHolon - Target holon ID
|
|
314
|
+
* @param {string} lensName - Lens name
|
|
315
|
+
* @param {Object} options - Federation options
|
|
316
|
+
* @param {string} options.direction - 'inbound' or 'outbound'
|
|
317
|
+
* @param {string} options.mode - 'reference' or 'copy'
|
|
318
|
+
* @returns {Promise<boolean>} Success indicator
|
|
319
|
+
*/
|
|
320
|
+
export async function setupFederation(
|
|
321
|
+
client,
|
|
322
|
+
appname,
|
|
323
|
+
sourceHolon,
|
|
324
|
+
targetHolon,
|
|
325
|
+
lensName,
|
|
326
|
+
options = {}
|
|
327
|
+
) {
|
|
328
|
+
const { direction = 'outbound', mode = 'reference' } = options;
|
|
329
|
+
|
|
330
|
+
const federationConfig = {
|
|
331
|
+
sourceHolon,
|
|
332
|
+
targetHolon,
|
|
333
|
+
lensName,
|
|
334
|
+
direction,
|
|
335
|
+
mode,
|
|
336
|
+
created: Date.now(),
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
// Store federation config
|
|
340
|
+
const configPath = buildPath(appname, sourceHolon, lensName, '_federation');
|
|
341
|
+
return write(client, configPath, federationConfig);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Propagate data to federated location
|
|
346
|
+
* @param {Object} client - Nostr client instance
|
|
347
|
+
* @param {string} appname - Application namespace
|
|
348
|
+
* @param {Object} data - Data to propagate
|
|
349
|
+
* @param {string} sourceHolon - Source holon ID
|
|
350
|
+
* @param {string} targetHolon - Target holon ID
|
|
351
|
+
* @param {string} lensName - Lens name
|
|
352
|
+
* @param {string} mode - 'reference' or 'copy'
|
|
353
|
+
* @returns {Promise<boolean>} Success indicator
|
|
354
|
+
*/
|
|
355
|
+
export async function propagateData(
|
|
356
|
+
client,
|
|
357
|
+
appname,
|
|
358
|
+
data,
|
|
359
|
+
sourceHolon,
|
|
360
|
+
targetHolon,
|
|
361
|
+
lensName,
|
|
362
|
+
mode = 'reference'
|
|
363
|
+
) {
|
|
364
|
+
const dataId = data.id;
|
|
365
|
+
|
|
366
|
+
// Don't create hologram to the same holon - it would point to itself
|
|
367
|
+
if (sourceHolon === targetHolon) {
|
|
368
|
+
console.info(`โญ๏ธ Skipping propagation - source and target are the same holon: ${sourceHolon}`);
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Don't propagate holograms back to avoid circular references
|
|
373
|
+
// If this data is already a hologram pointing to the target, skip it
|
|
374
|
+
if (data.hologram === true) {
|
|
375
|
+
// Check if this hologram would create a circular reference
|
|
376
|
+
if (data.target && data.target.holonId === targetHolon) {
|
|
377
|
+
console.info(`๐ Skipping propagation - would create circular reference:`);
|
|
378
|
+
console.info(` Data ID: ${dataId}`);
|
|
379
|
+
console.info(` Source holon: ${sourceHolon}`);
|
|
380
|
+
console.info(` Target holon: ${targetHolon}`);
|
|
381
|
+
console.info(` Hologram points to: ${data.target.holonId}`);
|
|
382
|
+
console.info(` Lens: ${lensName}`);
|
|
383
|
+
console.info(` Original soul: ${data.soul || 'unknown'}`);
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Check if targetHolon is already in the original source's activeHolograms
|
|
388
|
+
// This prevents creating duplicate holograms when the target already has one
|
|
389
|
+
if (data.target) {
|
|
390
|
+
const originalSourcePath = buildPath(
|
|
391
|
+
data.target.appname || appname,
|
|
392
|
+
data.target.holonId,
|
|
393
|
+
data.target.lensName || lensName,
|
|
394
|
+
data.target.dataId || dataId
|
|
395
|
+
);
|
|
396
|
+
const originalSource = await read(client, originalSourcePath);
|
|
397
|
+
|
|
398
|
+
if (originalSource?._meta?.activeHolograms) {
|
|
399
|
+
const alreadyHasHologram = originalSource._meta.activeHolograms.some(
|
|
400
|
+
h => h.targetHolon === targetHolon
|
|
401
|
+
);
|
|
402
|
+
if (alreadyHasHologram) {
|
|
403
|
+
console.info(`โญ๏ธ Skipping propagation - target already in activeHolograms:`);
|
|
404
|
+
console.info(` Data ID: ${dataId}`);
|
|
405
|
+
console.info(` Original source: ${data.target.holonId}`);
|
|
406
|
+
console.info(` Target holon: ${targetHolon}`);
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Deep circular check for hologram copy - ensure the original source doesn't eventually point to target
|
|
413
|
+
const originalSourceHolon = data.target.holonId;
|
|
414
|
+
const originalDataId = data.target.dataId || dataId;
|
|
415
|
+
const originalLens = data.target.lensName || lensName;
|
|
416
|
+
const originalAppname = data.target.appname || appname;
|
|
417
|
+
|
|
418
|
+
const circularCheck = await wouldCreateCircularHologram(
|
|
419
|
+
client, originalAppname, originalSourceHolon, targetHolon, originalLens, originalDataId
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
if (circularCheck.isCircular) {
|
|
423
|
+
const chainStr = circularCheck.chain.map(c => c.holon).join(' โ ');
|
|
424
|
+
console.warn(`๐ Preventing circular hologram copy:`);
|
|
425
|
+
console.warn(` Data ID: ${dataId}`);
|
|
426
|
+
console.warn(` Original source: ${originalSourceHolon}`);
|
|
427
|
+
console.warn(` Would copy to: ${targetHolon}`);
|
|
428
|
+
console.warn(` Existing chain: ${chainStr}`);
|
|
429
|
+
console.warn(` Reason: ${circularCheck.reason}`);
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// When propagating a hologram, copy it instead of creating a hologram of a hologram
|
|
434
|
+
// This maintains the reference to the original source
|
|
435
|
+
const targetPath = buildPath(appname, targetHolon, lensName, dataId);
|
|
436
|
+
const copiedHologram = {
|
|
437
|
+
...data,
|
|
438
|
+
_meta: {
|
|
439
|
+
...data._meta,
|
|
440
|
+
copiedFrom: sourceHolon,
|
|
441
|
+
copiedAt: Date.now()
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
const success = await write(client, targetPath, copiedHologram);
|
|
445
|
+
|
|
446
|
+
// Add this new location to the original source's activeHolograms
|
|
447
|
+
if (success && data.target) {
|
|
448
|
+
await addActiveHologram(
|
|
449
|
+
client,
|
|
450
|
+
data.target.appname || appname,
|
|
451
|
+
data.target.holonId,
|
|
452
|
+
data.target.lensName || lensName,
|
|
453
|
+
data.target.dataId || dataId,
|
|
454
|
+
targetHolon
|
|
455
|
+
);
|
|
456
|
+
console.info(`๐ Copied hologram to ${targetHolon}:`);
|
|
457
|
+
console.info(` Data ID: ${dataId}`);
|
|
458
|
+
console.info(` Original source: ${data.target.holonId}`);
|
|
459
|
+
console.info(` Copied from: ${sourceHolon}`);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return success;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// For non-hologram data, check if targetHolon is already in activeHolograms
|
|
466
|
+
if (mode === 'reference' && data._meta?.activeHolograms) {
|
|
467
|
+
const alreadyHasHologram = data._meta.activeHolograms.some(
|
|
468
|
+
h => h.targetHolon === targetHolon
|
|
469
|
+
);
|
|
470
|
+
if (alreadyHasHologram) {
|
|
471
|
+
console.info(`โญ๏ธ Skipping propagation - target already in activeHolograms:`);
|
|
472
|
+
console.info(` Data ID: ${dataId}`);
|
|
473
|
+
console.info(` Source holon: ${sourceHolon}`);
|
|
474
|
+
console.info(` Target holon: ${targetHolon}`);
|
|
475
|
+
return true;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (mode === 'reference') {
|
|
480
|
+
// Deep circular reference check - follow the chain from source to see if it would loop back
|
|
481
|
+
const circularCheck = await wouldCreateCircularHologram(
|
|
482
|
+
client, appname, sourceHolon, targetHolon, lensName, dataId
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
if (circularCheck.isCircular) {
|
|
486
|
+
const chainStr = circularCheck.chain.map(c => c.holon).join(' โ ');
|
|
487
|
+
console.warn(`๐ Preventing circular hologram creation:`);
|
|
488
|
+
console.warn(` Data ID: ${dataId}`);
|
|
489
|
+
console.warn(` Would create: ${sourceHolon} โ ${targetHolon}`);
|
|
490
|
+
console.warn(` Existing chain: ${chainStr}`);
|
|
491
|
+
console.warn(` Reason: ${circularCheck.reason}`);
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Create hologram in target
|
|
496
|
+
const hologram = createHologram(sourceHolon, targetHolon, lensName, dataId, appname);
|
|
497
|
+
const targetPath = buildPath(appname, targetHolon, lensName, dataId);
|
|
498
|
+
const success = await write(client, targetPath, hologram);
|
|
499
|
+
|
|
500
|
+
// Add hologram to source data's _meta.activeHolograms for tracking
|
|
501
|
+
if (success) {
|
|
502
|
+
await addActiveHologram(client, appname, sourceHolon, lensName, dataId, targetHolon);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return success;
|
|
506
|
+
} else {
|
|
507
|
+
// Copy data to target
|
|
508
|
+
const targetPath = buildPath(appname, targetHolon, lensName, dataId);
|
|
509
|
+
return write(client, targetPath, { ...data, _meta: { ...data._meta, source: sourceHolon } });
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Update local overrides on an existing hologram
|
|
515
|
+
* This allows storing holon-specific data (position, pinned status, etc.) on a hologram
|
|
516
|
+
* @param {Object} client - Nostr client instance
|
|
517
|
+
* @param {string} appname - Application namespace
|
|
518
|
+
* @param {string} holonId - Holon where the hologram lives
|
|
519
|
+
* @param {string} lensName - Lens name
|
|
520
|
+
* @param {string} dataId - Data ID
|
|
521
|
+
* @param {Object} overrides - Local override fields to set (e.g., { x: 100, y: 200, pinned: true })
|
|
522
|
+
* @returns {Promise<boolean>} Success indicator
|
|
523
|
+
*/
|
|
524
|
+
export async function updateHologramOverrides(client, appname, holonId, lensName, dataId, overrides) {
|
|
525
|
+
const path = buildPath(appname, holonId, lensName, dataId);
|
|
526
|
+
|
|
527
|
+
// Read existing hologram
|
|
528
|
+
const existing = await read(client, path);
|
|
529
|
+
|
|
530
|
+
if (!existing) {
|
|
531
|
+
console.warn(`Hologram not found at ${path}`);
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Only update if it's actually a hologram
|
|
536
|
+
if (!existing.hologram) {
|
|
537
|
+
console.warn(`Data at ${path} is not a hologram, cannot update overrides`);
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Merge overrides into hologram (but don't allow overriding hologram-specific fields)
|
|
542
|
+
const protectedFields = ['hologram', 'soul', 'target', '_meta', 'id'];
|
|
543
|
+
const safeOverrides = {};
|
|
544
|
+
|
|
545
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
546
|
+
if (!protectedFields.includes(key)) {
|
|
547
|
+
safeOverrides[key] = value;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const updated = {
|
|
552
|
+
...existing,
|
|
553
|
+
...safeOverrides
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
return write(client, path, updated);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Check if data is a hologram (unresolved reference)
|
|
561
|
+
* @param {Object} data - Data to check
|
|
562
|
+
* @returns {boolean} True if data is an unresolved hologram
|
|
563
|
+
*/
|
|
564
|
+
export function isHologram(data) {
|
|
565
|
+
return data && data.hologram === true;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Check if data was resolved from a hologram
|
|
570
|
+
* @param {Object} data - Data to check
|
|
571
|
+
* @returns {boolean} True if data was resolved from a hologram
|
|
572
|
+
*/
|
|
573
|
+
export function isResolvedHologram(data) {
|
|
574
|
+
return data && data._hologram && data._hologram.isHologram === true;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Get hologram source information from resolved data
|
|
579
|
+
* @param {Object} data - Resolved data
|
|
580
|
+
* @returns {Object|null} Source info { soul, sourceHolon, localOverrides } or null
|
|
581
|
+
*/
|
|
582
|
+
export function getHologramSource(data) {
|
|
583
|
+
if (!isResolvedHologram(data)) {
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
soul: data._hologram.soul,
|
|
588
|
+
sourceHolon: data._hologram.sourceHolon,
|
|
589
|
+
localOverrides: data._hologram.localOverrides || []
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Add a hologram reference to the source data's _meta.activeHolograms
|
|
595
|
+
* This tracks all holograms pointing to this specific data item
|
|
596
|
+
* If the source is itself a hologram, follows the chain to find the real source
|
|
597
|
+
* @param {Object} client - Nostr client instance
|
|
598
|
+
* @param {string} appname - Application namespace
|
|
599
|
+
* @param {string} sourceHolon - Source holon ID (where original data lives)
|
|
600
|
+
* @param {string} lensName - Lens name
|
|
601
|
+
* @param {string} dataId - Data ID
|
|
602
|
+
* @param {string} targetHolon - Target holon ID (where hologram lives)
|
|
603
|
+
* @returns {Promise<boolean>} Success indicator
|
|
604
|
+
*/
|
|
605
|
+
export async function addActiveHologram(client, appname, sourceHolon, lensName, dataId, targetHolon) {
|
|
606
|
+
let currentAppname = appname;
|
|
607
|
+
let currentHolon = sourceHolon;
|
|
608
|
+
let currentLens = lensName;
|
|
609
|
+
let currentDataId = dataId;
|
|
610
|
+
let sourcePath = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
|
|
611
|
+
|
|
612
|
+
// Read existing source data
|
|
613
|
+
let sourceData = await read(client, sourcePath);
|
|
614
|
+
if (!sourceData) {
|
|
615
|
+
console.warn(`Source data not found at ${sourcePath}`);
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// If source is a hologram, follow the chain to find the real source
|
|
620
|
+
// This ensures activeHolograms is always tracked on the actual data, not on holograms
|
|
621
|
+
let depth = 0;
|
|
622
|
+
const maxDepth = 10;
|
|
623
|
+
while (sourceData.hologram === true && sourceData.target && depth < maxDepth) {
|
|
624
|
+
depth++;
|
|
625
|
+
currentAppname = sourceData.target.appname || currentAppname;
|
|
626
|
+
currentHolon = sourceData.target.holonId;
|
|
627
|
+
currentLens = sourceData.target.lensName || currentLens;
|
|
628
|
+
currentDataId = sourceData.target.dataId || currentDataId;
|
|
629
|
+
sourcePath = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
|
|
630
|
+
|
|
631
|
+
sourceData = await read(client, sourcePath);
|
|
632
|
+
if (!sourceData) {
|
|
633
|
+
console.warn(`Real source data not found at ${sourcePath}`);
|
|
634
|
+
return false;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
if (depth > 0) {
|
|
639
|
+
console.info(`๐ Followed hologram chain (depth: ${depth}) to real source: ${currentHolon}/${currentLens}/${currentDataId}`);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Initialize _meta and activeHolograms if needed
|
|
643
|
+
if (!sourceData._meta) {
|
|
644
|
+
sourceData._meta = {};
|
|
645
|
+
}
|
|
646
|
+
if (!Array.isArray(sourceData._meta.activeHolograms)) {
|
|
647
|
+
sourceData._meta.activeHolograms = [];
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const now = Date.now();
|
|
651
|
+
|
|
652
|
+
// Check if this hologram already exists
|
|
653
|
+
const existingIndex = sourceData._meta.activeHolograms.findIndex(
|
|
654
|
+
h => h.targetHolon === targetHolon
|
|
655
|
+
);
|
|
656
|
+
|
|
657
|
+
if (existingIndex >= 0) {
|
|
658
|
+
// Update existing entry
|
|
659
|
+
sourceData._meta.activeHolograms[existingIndex].lastUpdated = now;
|
|
660
|
+
} else {
|
|
661
|
+
// Add new entry
|
|
662
|
+
sourceData._meta.activeHolograms.push({
|
|
663
|
+
targetHolon,
|
|
664
|
+
created: now,
|
|
665
|
+
lastUpdated: now
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Write to the real source path (not the original one if we followed a chain)
|
|
670
|
+
return write(client, sourcePath, sourceData);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Remove a hologram reference from the source data's _meta.activeHolograms
|
|
675
|
+
* If the source is itself a hologram, follows the chain to find the real source
|
|
676
|
+
* @param {Object} client - Nostr client instance
|
|
677
|
+
* @param {string} appname - Application namespace
|
|
678
|
+
* @param {string} sourceHolon - Source holon ID
|
|
679
|
+
* @param {string} lensName - Lens name
|
|
680
|
+
* @param {string} dataId - Data ID
|
|
681
|
+
* @param {string} targetHolon - Target holon ID
|
|
682
|
+
* @returns {Promise<boolean>} Success indicator
|
|
683
|
+
*/
|
|
684
|
+
export async function removeActiveHologram(client, appname, sourceHolon, lensName, dataId, targetHolon) {
|
|
685
|
+
let currentAppname = appname;
|
|
686
|
+
let currentHolon = sourceHolon;
|
|
687
|
+
let currentLens = lensName;
|
|
688
|
+
let currentDataId = dataId;
|
|
689
|
+
let sourcePath = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
|
|
690
|
+
|
|
691
|
+
// Read existing source data
|
|
692
|
+
let sourceData = await read(client, sourcePath);
|
|
693
|
+
if (!sourceData) {
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// If source is a hologram, follow the chain to find the real source
|
|
698
|
+
let depth = 0;
|
|
699
|
+
const maxDepth = 10;
|
|
700
|
+
while (sourceData.hologram === true && sourceData.target && depth < maxDepth) {
|
|
701
|
+
depth++;
|
|
702
|
+
currentAppname = sourceData.target.appname || currentAppname;
|
|
703
|
+
currentHolon = sourceData.target.holonId;
|
|
704
|
+
currentLens = sourceData.target.lensName || currentLens;
|
|
705
|
+
currentDataId = sourceData.target.dataId || currentDataId;
|
|
706
|
+
sourcePath = buildPath(currentAppname, currentHolon, currentLens, currentDataId);
|
|
707
|
+
|
|
708
|
+
sourceData = await read(client, sourcePath);
|
|
709
|
+
if (!sourceData) {
|
|
710
|
+
return false;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if (!sourceData._meta || !Array.isArray(sourceData._meta.activeHolograms)) {
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
const initialLength = sourceData._meta.activeHolograms.length;
|
|
719
|
+
sourceData._meta.activeHolograms = sourceData._meta.activeHolograms.filter(
|
|
720
|
+
h => h.targetHolon !== targetHolon
|
|
721
|
+
);
|
|
722
|
+
|
|
723
|
+
// Only write if something changed
|
|
724
|
+
if (sourceData._meta.activeHolograms.length < initialLength) {
|
|
725
|
+
return write(client, sourcePath, sourceData);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Refresh lastUpdated timestamps on all activeHolograms in source data
|
|
733
|
+
* Also updates the hologram objects in target holons
|
|
734
|
+
* Called when source data is updated
|
|
735
|
+
* @param {Object} client - Nostr client instance
|
|
736
|
+
* @param {string} appname - Application namespace
|
|
737
|
+
* @param {string} sourceHolon - Source holon ID
|
|
738
|
+
* @param {string} lensName - Lens name
|
|
739
|
+
* @param {string} dataId - Data ID that was updated
|
|
740
|
+
* @param {Object} sourceData - The source data object (already read, to avoid re-reading)
|
|
741
|
+
* @returns {Promise<Object>} Result with refreshed count
|
|
742
|
+
*/
|
|
743
|
+
export async function refreshActiveHolograms(client, appname, sourceHolon, lensName, dataId, sourceData = null) {
|
|
744
|
+
// Read source data if not provided
|
|
745
|
+
if (!sourceData) {
|
|
746
|
+
const sourcePath = buildPath(appname, sourceHolon, lensName, dataId);
|
|
747
|
+
sourceData = await read(client, sourcePath);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
if (!sourceData || !sourceData._meta || !Array.isArray(sourceData._meta.activeHolograms)) {
|
|
751
|
+
return { refreshed: 0, holograms: [] };
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
const now = Date.now();
|
|
755
|
+
const refreshed = [];
|
|
756
|
+
|
|
757
|
+
// Update timestamps on all activeHolograms
|
|
758
|
+
for (const hologramEntry of sourceData._meta.activeHolograms) {
|
|
759
|
+
hologramEntry.lastUpdated = now;
|
|
760
|
+
|
|
761
|
+
// Also update the hologram itself in the target holon
|
|
762
|
+
const hologramPath = buildPath(appname, hologramEntry.targetHolon, lensName, dataId);
|
|
763
|
+
const hologram = await read(client, hologramPath);
|
|
764
|
+
|
|
765
|
+
if (hologram && hologram.hologram === true) {
|
|
766
|
+
// Update hologram's _meta.lastUpdated
|
|
767
|
+
if (!hologram._meta) hologram._meta = {};
|
|
768
|
+
hologram._meta.lastUpdated = now;
|
|
769
|
+
await write(client, hologramPath, hologram);
|
|
770
|
+
refreshed.push({
|
|
771
|
+
targetHolon: hologramEntry.targetHolon,
|
|
772
|
+
dataId,
|
|
773
|
+
timestamp: now
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// Source data's activeHolograms timestamps are updated in-place
|
|
779
|
+
// The caller should save sourceData if needed
|
|
780
|
+
|
|
781
|
+
return { refreshed: refreshed.length, holograms: refreshed, sourceData };
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Delete a hologram and clean up the activeHolograms list on the original source
|
|
786
|
+
* @param {Object} client - Nostr client instance
|
|
787
|
+
* @param {string} appname - Application namespace
|
|
788
|
+
* @param {string} holonId - Holon where the hologram lives (to be deleted from)
|
|
789
|
+
* @param {string} lensName - Lens name
|
|
790
|
+
* @param {string} dataId - Data ID of the hologram
|
|
791
|
+
* @param {Object} options - Optional settings
|
|
792
|
+
* @param {boolean} options.deleteData - If true, actually delete the data (default: true)
|
|
793
|
+
* @returns {Promise<Object>} Result with deletion info
|
|
794
|
+
*/
|
|
795
|
+
export async function deleteHologram(client, appname, holonId, lensName, dataId, options = {}) {
|
|
796
|
+
const { deleteData = true } = options;
|
|
797
|
+
const path = buildPath(appname, holonId, lensName, dataId);
|
|
798
|
+
const result = {
|
|
799
|
+
success: false,
|
|
800
|
+
wasHologram: false,
|
|
801
|
+
sourceHolon: null,
|
|
802
|
+
activeHologramsUpdated: false,
|
|
803
|
+
error: null
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
try {
|
|
807
|
+
// Read the hologram to get source information
|
|
808
|
+
const hologram = await read(client, path);
|
|
809
|
+
|
|
810
|
+
if (!hologram) {
|
|
811
|
+
console.warn(`๐๏ธ Hologram not found at ${path}`);
|
|
812
|
+
result.error = 'Hologram not found';
|
|
813
|
+
return result;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// Check if it's actually a hologram
|
|
817
|
+
if (hologram.hologram === true && hologram.target) {
|
|
818
|
+
result.wasHologram = true;
|
|
819
|
+
result.sourceHolon = hologram.target.holonId;
|
|
820
|
+
|
|
821
|
+
console.info(`๐๏ธ Deleting hologram:`);
|
|
822
|
+
console.info(` Path: ${path}`);
|
|
823
|
+
console.info(` Data ID: ${dataId}`);
|
|
824
|
+
console.info(` From holon: ${holonId}`);
|
|
825
|
+
console.info(` Source holon: ${hologram.target.holonId}`);
|
|
826
|
+
console.info(` Lens: ${lensName}`);
|
|
827
|
+
|
|
828
|
+
// Remove from source's activeHolograms list
|
|
829
|
+
const removed = await removeActiveHologram(
|
|
830
|
+
client,
|
|
831
|
+
hologram.target.appname || appname,
|
|
832
|
+
hologram.target.holonId,
|
|
833
|
+
hologram.target.lensName || lensName,
|
|
834
|
+
hologram.target.dataId || dataId,
|
|
835
|
+
holonId
|
|
836
|
+
);
|
|
837
|
+
|
|
838
|
+
result.activeHologramsUpdated = removed;
|
|
839
|
+
|
|
840
|
+
if (removed) {
|
|
841
|
+
console.info(` โ Removed from activeHolograms on source`);
|
|
842
|
+
} else {
|
|
843
|
+
console.warn(` โ ๏ธ Could not update activeHolograms on source (may already be removed)`);
|
|
844
|
+
}
|
|
845
|
+
} else {
|
|
846
|
+
console.info(`๐๏ธ Deleting non-hologram data at ${path}`);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
// Delete the hologram data if requested
|
|
850
|
+
if (deleteData) {
|
|
851
|
+
// Write null to delete (or use a delete function if available)
|
|
852
|
+
const deleted = await write(client, path, null);
|
|
853
|
+
result.success = deleted;
|
|
854
|
+
|
|
855
|
+
if (deleted) {
|
|
856
|
+
console.info(` โ Hologram deleted successfully`);
|
|
857
|
+
} else {
|
|
858
|
+
console.warn(` โ ๏ธ Failed to delete hologram data`);
|
|
859
|
+
result.error = 'Failed to delete hologram data';
|
|
860
|
+
}
|
|
861
|
+
} else {
|
|
862
|
+
result.success = true;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
return result;
|
|
866
|
+
} catch (error) {
|
|
867
|
+
console.error(`โ Error deleting hologram at ${path}:`, error);
|
|
868
|
+
result.error = error.message || 'Unknown error';
|
|
869
|
+
return result;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
/**
|
|
874
|
+
* Cleanup circular holograms in a holon's lens
|
|
875
|
+
* This detects and removes holograms that create circular references (AโBโA)
|
|
876
|
+
* Useful for cleaning up existing bad data created before circular reference prevention was added
|
|
877
|
+
* @param {Object} client - Nostr client instance
|
|
878
|
+
* @param {string} appname - Application namespace
|
|
879
|
+
* @param {string} holonId - Holon to clean up
|
|
880
|
+
* @param {string} lensName - Lens name to check
|
|
881
|
+
* @param {Object} options - Optional settings
|
|
882
|
+
* @param {boolean} options.dryRun - If true, only report what would be deleted (default: false)
|
|
883
|
+
* @returns {Promise<Object>} Result with cleanup info
|
|
884
|
+
*/
|
|
885
|
+
export async function cleanupCircularHolograms(client, appname, holonId, lensName, options = {}) {
|
|
886
|
+
const { dryRun = false } = options;
|
|
887
|
+
const result = {
|
|
888
|
+
scanned: 0,
|
|
889
|
+
circularFound: 0,
|
|
890
|
+
deleted: 0,
|
|
891
|
+
errors: [],
|
|
892
|
+
details: []
|
|
893
|
+
};
|
|
894
|
+
|
|
895
|
+
console.info(`๐งน ${dryRun ? '[DRY RUN] ' : ''}Cleaning up circular holograms in ${holonId}/${lensName}...`);
|
|
896
|
+
|
|
897
|
+
try {
|
|
898
|
+
// Get all data in this lens
|
|
899
|
+
const basePath = buildPath(appname, holonId, lensName);
|
|
900
|
+
// We need to iterate through all items - this requires listing capability
|
|
901
|
+
// For now, we'll rely on the caller to provide a list of IDs to check
|
|
902
|
+
// or we can use a different approach
|
|
903
|
+
|
|
904
|
+
// Alternative: Read the lens index if it exists
|
|
905
|
+
const lensIndexPath = buildPath(appname, holonId, lensName, '_index');
|
|
906
|
+
const lensIndex = await read(client, lensIndexPath);
|
|
907
|
+
|
|
908
|
+
if (!lensIndex || !Array.isArray(lensIndex.items)) {
|
|
909
|
+
console.warn(` No index found for ${holonId}/${lensName}, cannot scan for circular references`);
|
|
910
|
+
console.info(` Tip: Provide specific IDs to check using cleanupCircularHologramsByIds()`);
|
|
911
|
+
return result;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
for (const itemId of lensIndex.items) {
|
|
915
|
+
result.scanned++;
|
|
916
|
+
const itemPath = buildPath(appname, holonId, lensName, itemId);
|
|
917
|
+
const item = await read(client, itemPath);
|
|
918
|
+
|
|
919
|
+
if (!item || item.hologram !== true || !item.target) {
|
|
920
|
+
continue; // Not a hologram, skip
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// This is a hologram - check if it creates a circular reference
|
|
924
|
+
const sourceHolon = item.target.holonId;
|
|
925
|
+
const sourceDataId = item.target.dataId || itemId;
|
|
926
|
+
const sourceLens = item.target.lensName || lensName;
|
|
927
|
+
|
|
928
|
+
// Read the source data
|
|
929
|
+
const sourcePath = buildPath(item.target.appname || appname, sourceHolon, sourceLens, sourceDataId);
|
|
930
|
+
const sourceData = await read(client, sourcePath);
|
|
931
|
+
|
|
932
|
+
if (sourceData && sourceData.hologram === true && sourceData.target) {
|
|
933
|
+
// Source is also a hologram - check if it points back
|
|
934
|
+
if (sourceData.target.holonId === holonId) {
|
|
935
|
+
result.circularFound++;
|
|
936
|
+
const detail = {
|
|
937
|
+
itemId,
|
|
938
|
+
path: itemPath,
|
|
939
|
+
pointsTo: `${sourceHolon}/${sourceLens}/${sourceDataId}`,
|
|
940
|
+
circularWith: `${sourceData.target.holonId}/${sourceData.target.lensName}/${sourceData.target.dataId}`
|
|
941
|
+
};
|
|
942
|
+
result.details.push(detail);
|
|
943
|
+
|
|
944
|
+
console.warn(` ๐ Found circular hologram:`);
|
|
945
|
+
console.warn(` ${holonId}/${lensName}/${itemId} โ ${sourceHolon}/${sourceLens}/${sourceDataId} โ ${holonId}`);
|
|
946
|
+
|
|
947
|
+
if (!dryRun) {
|
|
948
|
+
// Delete this hologram
|
|
949
|
+
const deleteResult = await deleteHologram(client, appname, holonId, lensName, itemId);
|
|
950
|
+
if (deleteResult.success) {
|
|
951
|
+
result.deleted++;
|
|
952
|
+
console.info(` โ Deleted circular hologram`);
|
|
953
|
+
} else {
|
|
954
|
+
result.errors.push({ itemId, error: deleteResult.error });
|
|
955
|
+
console.error(` โ Failed to delete: ${deleteResult.error}`);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
console.info(`๐งน Cleanup complete for ${holonId}/${lensName}:`);
|
|
963
|
+
console.info(` Scanned: ${result.scanned}`);
|
|
964
|
+
console.info(` Circular found: ${result.circularFound}`);
|
|
965
|
+
console.info(` Deleted: ${result.deleted}`);
|
|
966
|
+
if (result.errors.length > 0) {
|
|
967
|
+
console.warn(` Errors: ${result.errors.length}`);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
return result;
|
|
971
|
+
} catch (error) {
|
|
972
|
+
console.error(`โ Error during cleanup:`, error);
|
|
973
|
+
result.errors.push({ error: error.message });
|
|
974
|
+
return result;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/**
|
|
979
|
+
* Cleanup circular holograms for a specific list of IDs
|
|
980
|
+
* Use this when you don't have an index but know which IDs to check
|
|
981
|
+
* @param {Object} client - Nostr client instance
|
|
982
|
+
* @param {string} appname - Application namespace
|
|
983
|
+
* @param {string} holonId - Holon to clean up
|
|
984
|
+
* @param {string} lensName - Lens name
|
|
985
|
+
* @param {string[]} dataIds - Array of data IDs to check
|
|
986
|
+
* @param {Object} options - Optional settings
|
|
987
|
+
* @param {boolean} options.dryRun - If true, only report what would be deleted
|
|
988
|
+
* @returns {Promise<Object>} Result with cleanup info
|
|
989
|
+
*/
|
|
990
|
+
export async function cleanupCircularHologramsByIds(client, appname, holonId, lensName, dataIds, options = {}) {
|
|
991
|
+
const { dryRun = false } = options;
|
|
992
|
+
const result = {
|
|
993
|
+
scanned: 0,
|
|
994
|
+
circularFound: 0,
|
|
995
|
+
deleted: 0,
|
|
996
|
+
errors: [],
|
|
997
|
+
details: []
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
console.info(`๐งน ${dryRun ? '[DRY RUN] ' : ''}Cleaning up circular holograms for ${dataIds.length} IDs in ${holonId}/${lensName}...`);
|
|
1001
|
+
|
|
1002
|
+
for (const itemId of dataIds) {
|
|
1003
|
+
result.scanned++;
|
|
1004
|
+
const itemPath = buildPath(appname, holonId, lensName, itemId);
|
|
1005
|
+
const item = await read(client, itemPath);
|
|
1006
|
+
|
|
1007
|
+
if (!item || item.hologram !== true || !item.target) {
|
|
1008
|
+
continue; // Not a hologram, skip
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// This is a hologram - check if it creates a circular reference
|
|
1012
|
+
const sourceHolon = item.target.holonId;
|
|
1013
|
+
const sourceDataId = item.target.dataId || itemId;
|
|
1014
|
+
const sourceLens = item.target.lensName || lensName;
|
|
1015
|
+
|
|
1016
|
+
// Read the source data
|
|
1017
|
+
const sourcePath = buildPath(item.target.appname || appname, sourceHolon, sourceLens, sourceDataId);
|
|
1018
|
+
const sourceData = await read(client, sourcePath);
|
|
1019
|
+
|
|
1020
|
+
if (sourceData && sourceData.hologram === true && sourceData.target) {
|
|
1021
|
+
// Source is also a hologram - check if it points back
|
|
1022
|
+
if (sourceData.target.holonId === holonId) {
|
|
1023
|
+
result.circularFound++;
|
|
1024
|
+
const detail = {
|
|
1025
|
+
itemId,
|
|
1026
|
+
path: itemPath,
|
|
1027
|
+
pointsTo: `${sourceHolon}/${sourceLens}/${sourceDataId}`,
|
|
1028
|
+
circularWith: `${sourceData.target.holonId}/${sourceData.target.lensName}/${sourceData.target.dataId}`
|
|
1029
|
+
};
|
|
1030
|
+
result.details.push(detail);
|
|
1031
|
+
|
|
1032
|
+
console.warn(` ๐ Found circular hologram: ${itemId}`);
|
|
1033
|
+
console.warn(` Chain: ${holonId} โ ${sourceHolon} โ ${holonId}`);
|
|
1034
|
+
|
|
1035
|
+
if (!dryRun) {
|
|
1036
|
+
// Delete this hologram
|
|
1037
|
+
const deleteResult = await deleteHologram(client, appname, holonId, lensName, itemId);
|
|
1038
|
+
if (deleteResult.success) {
|
|
1039
|
+
result.deleted++;
|
|
1040
|
+
console.info(` โ Deleted`);
|
|
1041
|
+
} else {
|
|
1042
|
+
result.errors.push({ itemId, error: deleteResult.error });
|
|
1043
|
+
console.error(` โ Failed: ${deleteResult.error}`);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
console.info(`๐งน Cleanup complete: scanned=${result.scanned}, circular=${result.circularFound}, deleted=${result.deleted}`);
|
|
1051
|
+
return result;
|
|
1052
|
+
}
|
|
1053
|
+
</code></pre></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><div class="mobile-nav-links"></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai.html">ai</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation.html">ai/aggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.html">ai/breakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.html">ai/classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.html">ai/council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.html">ai/embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.html">ai/federation-ai</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.html">ai/h3-ai</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.html">ai/json-ops</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.html">ai/llm-service</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.html">ai/nl-query</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.html">ai/relationships</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.html">ai/schema-extractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.html">ai/spatial</a></div><div class="sidebar-section-children"><a href="module-ai_tts.html">ai/tts</a></div><div class="sidebar-section-children"><a href="module-content_social-protocols.html">content/social-protocols</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.html">core/holosphere</a></div><div class="sidebar-section-children"><a href="module-crypto_nostr-utils.html">crypto/nostr-utils</a></div><div class="sidebar-section-children"><a href="module-crypto_secp256k1.html">crypto/secp256k1</a></div><div class="sidebar-section-children"><a href="module-federation_hologram.html">federation/hologram</a></div><div class="sidebar-section-children"><a href="module-hierarchical_upcast.html">hierarchical/upcast</a></div><div class="sidebar-section-children"><a href="module-holosphere.html">holosphere</a></div><div class="sidebar-section-children"><a href="module-lib_ai-methods.html">lib/ai-methods</a></div><div class="sidebar-section-children"><a href="module-lib_contract-methods.html">lib/contract-methods</a></div><div class="sidebar-section-children"><a href="module-lib_errors.html">lib/errors</a></div><div class="sidebar-section-children"><a href="module-lib_federation-methods.html">lib/federation-methods</a></div><div class="sidebar-section-children"><a href="module-lib_index.html">lib/index</a></div><div class="sidebar-section-children"><a href="module-schema_validator.html">schema/validator</a></div><div class="sidebar-section-children"><a href="module-spatial_h3-operations.html">spatial/h3-operations</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.html">storage/backend-factory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.html">storage/backend-interface</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.html">storage/backends/activitypub-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.html">storage/backends/activitypub/server</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.html">storage/backends/gundb-backend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.html">storage/backends/nostr-backend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.html">storage/filesystem-storage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.html">storage/filesystem-storage-browser</a></div><div class="sidebar-section-children"><a href="module-storage_global-tables.html">storage/global-tables</a></div><div class="sidebar-section-children"><a href="module-storage_gun-async.html">storage/gun-async</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.html">storage/gun-auth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-federation.html">storage/gun-federation</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.html">storage/gun-references</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.html">storage/gun-schema</a></div><div class="sidebar-section-children"><a href="module-storage_gun-wrapper.html">storage/gun-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.html">storage/indexeddb-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage.html">storage/key-storage</a></div><div class="sidebar-section-children"><a href="module-storage_key-storage-simple.html">storage/key-storage-simple</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.html">storage/memory-storage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.html">storage/migration</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-async.html">storage/nostr-async</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.html">storage/nostr-client</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-wrapper.html">storage/nostr-wrapper</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.html">storage/outbox-queue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage.html">storage/persistent-storage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.html">storage/sync-service</a></div><div class="sidebar-section-children"><a href="module-storage_unified-storage.html">storage/unified-storage</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.html">subscriptions/manager</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-ai_aggregation.SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_aggregation-SmartAggregation.html">SmartAggregation</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown.TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_breakdown-TaskBreakdown.html">TaskBreakdown</a></div><div class="sidebar-section-children"><a href="module-ai_classifier.Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_classifier-Classifier.html">Classifier</a></div><div class="sidebar-section-children"><a href="module-ai_council.Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_council-Council.html">Council</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings.Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_embeddings-Embeddings.html">Embeddings</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai.FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_federation-ai-FederationAdvisor.html">FederationAdvisor</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai.H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_h3-ai-H3AI.html">H3AI</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops.JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_json-ops-JSONOps.html">JSONOps</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service.LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_llm-service-LLMService.html">LLMService</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query.NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_nl-query-NLQuery.html">NLQuery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships.RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_relationships-RelationshipDiscovery.html">RelationshipDiscovery</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor.SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_schema-extractor-SchemaExtractor.html">SchemaExtractor</a></div><div class="sidebar-section-children"><a href="module-ai_spatial.SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_spatial-SpatialAnalysis.html">SpatialAnalysis</a></div><div class="sidebar-section-children"><a href="module-ai_tts.TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-ai_tts-TTS.html">TTS</a></div><div class="sidebar-section-children"><a href="module-core_holosphere.HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-core_holosphere-HoloSphere.html">HoloSphere</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-holosphere-HoloSphereBase.html">HoloSphereBase</a></div><div class="sidebar-section-children"><a href="module-lib_errors.AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-AuthorizationError.html">AuthorizationError</a></div><div class="sidebar-section-children"><a href="module-lib_errors-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator.ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-schema_validator-ValidationError.html">ValidationError</a></div><div class="sidebar-section-children"><a href="module-storage_backend-factory.BackendFactory.html">BackendFactory</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface.StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backend-interface-StorageBackend.html">StorageBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend.ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub-backend-ActivityPubBackend.html">ActivityPubBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server.ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_activitypub_server-ActivityPubServer.html">ActivityPubServer</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend.GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_gundb-backend-GunDBBackend.html">GunDBBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend.NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_backends_nostr-backend-NostrBackend.html">NostrBackend</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-browser-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage.FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_filesystem-storage-FileSystemStorage.html">FileSystemStorage</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth.GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-auth-GunAuth.html">GunAuth</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references.GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-references-GunReferenceHandler.html">GunReferenceHandler</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema.GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_gun-schema-GunSchemaValidator.html">GunSchemaValidator</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage.IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_indexeddb-storage-IndexedDBStorage.html">IndexedDBStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage.MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_memory-storage-MemoryStorage.html">MemoryStorage</a></div><div class="sidebar-section-children"><a href="module-storage_migration.MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_migration-MigrationTool.html">MigrationTool</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client.NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-LRUCache.html">LRUCache</a></div><div class="sidebar-section-children"><a href="module-storage_nostr-client-NostrClient.html">NostrClient</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue.OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_outbox-queue-OutboxQueue.html">OutboxQueue</a></div><div class="sidebar-section-children"><a href="module-storage_persistent-storage-PersistentStorage.html">PersistentStorage</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service.SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-storage_sync-service-SyncService.html">SyncService</a></div><div class="sidebar-section-children"><a href="module-subscriptions_manager.SubscriptionRegistry.html">SubscriptionRegistry</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#FederationRequestPayload">FederationRequestPayload</a></div><div class="sidebar-section-children"><a href="global.html#FederationResponsePayload">FederationResponsePayload</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#acceptFederationRequest">acceptFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#addFederatedPartner">addFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#cleanupExpiredCapabilities">cleanupExpiredCapabilities</a></div><div class="sidebar-section-children"><a href="global.html#createFederationRequest">createFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#createFederationResponse">createFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#declineFederationRequest">declineFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#getCapabilityForAuthor">getCapabilityForAuthor</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthors">getFederatedAuthors</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedAuthorsForScope">getFederatedAuthorsForScope</a></div><div class="sidebar-section-children"><a href="global.html#getFederatedPartner">getFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#getFederationRegistry">getFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#getPendingFederationRequests">getPendingFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#initiateFederationHandshake">initiateFederationHandshake</a></div><div class="sidebar-section-children"><a href="global.html#isFederationRequest">isFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#isFederationResponse">isFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#rejectFederationRequest">rejectFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#removeFederatedPartner">removeFederatedPartner</a></div><div class="sidebar-section-children"><a href="global.html#revokeOutboundCapability">revokeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#saveFederationRegistry">saveFederationRegistry</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationRequest">sendFederationRequest</a></div><div class="sidebar-section-children"><a href="global.html#sendFederationResponse">sendFederationResponse</a></div><div class="sidebar-section-children"><a href="global.html#storeInboundCapability">storeInboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#storeOutboundCapability">storeOutboundCapability</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationAcceptances">subscribeFederationAcceptances</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationDeclines">subscribeFederationDeclines</a></div><div class="sidebar-section-children"><a href="global.html#subscribeFederationRequests">subscribeFederationRequests</a></div><div class="sidebar-section-children"><a href="global.html#subscribeToFederationDMs">subscribeToFederationDMs</a></div><div class="sidebar-section-children"><a href="global.html#updateDiscoverySettings">updateDiscoverySettings</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>
|