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,1868 @@
|
|
|
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: index.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">index.js</h1></header><article><pre class="prettyprint source lang-js"><code>/**
|
|
4
|
+
* @fileoverview HoloSphere - Holonic Geospatial Communication Infrastructure
|
|
5
|
+
*
|
|
6
|
+
* This is the main entry point for the HoloSphere library, providing a comprehensive
|
|
7
|
+
* distributed P2P geospatial communication system. It combines H3 hexagonal indexing
|
|
8
|
+
* for spatial organization, Nostr protocol for distributed storage, smart contracts
|
|
9
|
+
* for fund distribution, and AI services for intelligent data processing.
|
|
10
|
+
*
|
|
11
|
+
* @module holosphere
|
|
12
|
+
* @author HoloSphere Team
|
|
13
|
+
* @license MIT
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { HoloSphere as HoloSphereCore } from './core/holosphere.js';
|
|
17
|
+
import * as spatial from './spatial/h3-operations.js';
|
|
18
|
+
import * as storage from './storage/unified-storage.js';
|
|
19
|
+
import * as nostrStorage from './storage/nostr-wrapper.js';
|
|
20
|
+
import * as nostrAsync from './storage/nostr-async.js';
|
|
21
|
+
import * as globalTables from './storage/global-tables.js';
|
|
22
|
+
import * as schema from './schema/validator.js';
|
|
23
|
+
import { ValidationError } from './schema/validator.js';
|
|
24
|
+
import * as federation from './federation/hologram.js';
|
|
25
|
+
import * as handshake from './federation/handshake.js';
|
|
26
|
+
import * as crypto from './crypto/secp256k1.js';
|
|
27
|
+
import * as nostrUtils from './crypto/nostr-utils.js';
|
|
28
|
+
import * as social from './content/social-protocols.js';
|
|
29
|
+
import * as subscriptions from './subscriptions/manager.js';
|
|
30
|
+
import * as hierarchical from './hierarchical/upcast.js';
|
|
31
|
+
|
|
32
|
+
// AI Module imports
|
|
33
|
+
import { LLMService } from './ai/llm-service.js';
|
|
34
|
+
import { SchemaExtractor } from './ai/schema-extractor.js';
|
|
35
|
+
import { JSONOps } from './ai/json-ops.js';
|
|
36
|
+
import { Embeddings } from './ai/embeddings.js';
|
|
37
|
+
import { Council } from './ai/council.js';
|
|
38
|
+
import { TTS, VOICES, MODELS } from './ai/tts.js';
|
|
39
|
+
import { NLQuery } from './ai/nl-query.js';
|
|
40
|
+
import { Classifier } from './ai/classifier.js';
|
|
41
|
+
import { SpatialAnalysis } from './ai/spatial.js';
|
|
42
|
+
import { SmartAggregation } from './ai/aggregation.js';
|
|
43
|
+
import { FederationAdvisor } from './ai/federation-ai.js';
|
|
44
|
+
import { RelationshipDiscovery } from './ai/relationships.js';
|
|
45
|
+
import { TaskBreakdown } from './ai/breakdown.js';
|
|
46
|
+
import { H3AI } from './ai/h3-ai.js';
|
|
47
|
+
|
|
48
|
+
// Contracts Module imports
|
|
49
|
+
import { ChainManager } from './contracts/chain-manager.js';
|
|
50
|
+
import { ContractDeployer, ABIs as ContractABIs } from './contracts/deployer.js';
|
|
51
|
+
import { HolonContracts } from './contracts/holon-contracts.js';
|
|
52
|
+
import { ContractOperations } from './contracts/operations.js';
|
|
53
|
+
import { EventListener, SANKEY_EVENTS } from './contracts/event-listener.js';
|
|
54
|
+
import { ContractQueries } from './contracts/queries.js';
|
|
55
|
+
import * as networks from './contracts/networks.js';
|
|
56
|
+
|
|
57
|
+
// Mixin imports
|
|
58
|
+
import { withAIMethods } from './lib/ai-methods.js';
|
|
59
|
+
import { withContractMethods } from './lib/contract-methods.js';
|
|
60
|
+
import { withFederationMethods } from './lib/federation-methods.js';
|
|
61
|
+
import { AuthorizationError } from './lib/errors.js';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Base HoloSphere class with core data operations.
|
|
65
|
+
* Extends HoloSphereCore with schema validation, caching, subscriptions, and AI capabilities.
|
|
66
|
+
*
|
|
67
|
+
* @class HoloSphereBase
|
|
68
|
+
* @extends HoloSphereCore
|
|
69
|
+
*/
|
|
70
|
+
class HoloSphereBase extends HoloSphereCore {
|
|
71
|
+
/**
|
|
72
|
+
* Creates a new HoloSphereBase instance.
|
|
73
|
+
*
|
|
74
|
+
* @param {Object} config - Configuration options
|
|
75
|
+
* @param {string} config.appName - Application namespace for data isolation
|
|
76
|
+
* @param {string} [config.backend='nostr'] - Storage backend type ('nostr', 'gundb', 'activitypub')
|
|
77
|
+
* @param {string[]} [config.relays] - Nostr relay URLs for distributed storage
|
|
78
|
+
* @param {string} [config.openaiKey] - OpenAI API key for AI services
|
|
79
|
+
* @param {Object} [config.aiOptions] - AI service configuration
|
|
80
|
+
* @param {string} [config.aiOptions.model] - OpenAI model to use
|
|
81
|
+
* @param {number} [config.aiOptions.temperature] - Temperature for AI responses
|
|
82
|
+
*/
|
|
83
|
+
constructor(config) {
|
|
84
|
+
super(config);
|
|
85
|
+
/** @type {Map<string, {schema: Object, strict: boolean, timestamp: number}>} */
|
|
86
|
+
this.schemas = new Map();
|
|
87
|
+
/** @type {Map<string, any>} */
|
|
88
|
+
this._cache = new Map();
|
|
89
|
+
/** @type {subscriptions.SubscriptionRegistry} */
|
|
90
|
+
this.subscriptionRegistry = new subscriptions.SubscriptionRegistry();
|
|
91
|
+
|
|
92
|
+
// Initialize AI services if openaiKey is provided or OPENAI_API_KEY env var is set
|
|
93
|
+
/** @type {Object|null} */
|
|
94
|
+
this._ai = null;
|
|
95
|
+
const openaiKey = config.openaiKey || this._getEnv('OPENAI_API_KEY');
|
|
96
|
+
if (openaiKey) {
|
|
97
|
+
const aiOptions = {
|
|
98
|
+
...config.aiOptions,
|
|
99
|
+
model: config.aiOptions?.model || this._getEnv('HOLOSPHERE_AI_MODEL'),
|
|
100
|
+
temperature: config.aiOptions?.temperature ?? this._parseFloat(this._getEnv('HOLOSPHERE_AI_TEMPERATURE')),
|
|
101
|
+
};
|
|
102
|
+
this._initializeAI(openaiKey, aiOptions);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Contracts module (lazy initialized)
|
|
106
|
+
/** @type {Object|null} */
|
|
107
|
+
this._contracts = null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Gets an environment variable value (Node.js only).
|
|
112
|
+
*
|
|
113
|
+
* @private
|
|
114
|
+
* @param {string} name - Environment variable name
|
|
115
|
+
* @returns {string|undefined} Environment variable value or undefined
|
|
116
|
+
*/
|
|
117
|
+
_getEnv(name) {
|
|
118
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
119
|
+
return process.env[name];
|
|
120
|
+
}
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Parses a string value to a float.
|
|
126
|
+
*
|
|
127
|
+
* @private
|
|
128
|
+
* @param {string|undefined|null} value - Value to parse
|
|
129
|
+
* @returns {number|undefined} Parsed float or undefined if invalid
|
|
130
|
+
*/
|
|
131
|
+
_parseFloat(value) {
|
|
132
|
+
if (value === undefined || value === null) return undefined;
|
|
133
|
+
const parsed = parseFloat(value);
|
|
134
|
+
return isNaN(parsed) ? undefined : parsed;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Initializes AI services with the provided API key.
|
|
139
|
+
*
|
|
140
|
+
* @private
|
|
141
|
+
* @param {string} apiKey - OpenAI API key
|
|
142
|
+
* @param {Object} [options={}] - AI configuration options
|
|
143
|
+
* @param {string} [options.model] - OpenAI model to use
|
|
144
|
+
* @param {number} [options.temperature] - Temperature for AI responses
|
|
145
|
+
*/
|
|
146
|
+
_initializeAI(apiKey, options = {}) {
|
|
147
|
+
const llmOptions = {
|
|
148
|
+
...options.llm,
|
|
149
|
+
model: options.model || options.llm?.model,
|
|
150
|
+
temperature: options.temperature ?? options.llm?.temperature,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
this._ai = {
|
|
154
|
+
llm: new LLMService(apiKey, llmOptions),
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const OpenAI = require('openai').default;
|
|
158
|
+
const openai = new OpenAI({ apiKey });
|
|
159
|
+
this._ai.openai = openai;
|
|
160
|
+
|
|
161
|
+
this._ai.embeddings = new Embeddings(openai, this);
|
|
162
|
+
this._ai.schemaExtractor = new SchemaExtractor(this._ai.llm);
|
|
163
|
+
this._ai.jsonOps = new JSONOps(this._ai.llm);
|
|
164
|
+
this._ai.council = new Council(this._ai.llm);
|
|
165
|
+
this._ai.tts = new TTS(openai);
|
|
166
|
+
this._ai.nlQuery = new NLQuery(this._ai.llm, this);
|
|
167
|
+
this._ai.classifier = new Classifier(this._ai.llm, this);
|
|
168
|
+
this._ai.spatial = new SpatialAnalysis(this._ai.llm, this);
|
|
169
|
+
this._ai.aggregation = new SmartAggregation(this._ai.llm, this);
|
|
170
|
+
this._ai.federationAdvisor = new FederationAdvisor(this._ai.llm, this, this._ai.embeddings);
|
|
171
|
+
this._ai.relationships = new RelationshipDiscovery(this._ai.llm, this, this._ai.embeddings);
|
|
172
|
+
this._ai.taskBreakdown = new TaskBreakdown(this._ai.llm, this);
|
|
173
|
+
this._ai.h3ai = new H3AI(this._ai.llm, this);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Checks if AI services are initialized.
|
|
178
|
+
*
|
|
179
|
+
* @returns {boolean} True if AI services are available
|
|
180
|
+
*/
|
|
181
|
+
hasAI() {
|
|
182
|
+
return this._ai !== null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Gets the initialized AI services object.
|
|
187
|
+
*
|
|
188
|
+
* @returns {Object|null} AI services object containing llm, embeddings, etc., or null if not initialized
|
|
189
|
+
*/
|
|
190
|
+
getAIServices() {
|
|
191
|
+
return this._ai;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// === Spatial Operations ===
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Converts geographic coordinates to an H3 holon ID.
|
|
198
|
+
*
|
|
199
|
+
* @param {number} lat - Latitude (-90 to 90)
|
|
200
|
+
* @param {number} lng - Longitude (-180 to 180)
|
|
201
|
+
* @param {number} resolution - H3 resolution level (0-15)
|
|
202
|
+
* @returns {Promise<string>} H3 cell ID representing the holon
|
|
203
|
+
*/
|
|
204
|
+
async toHolon(lat, lng, resolution) {
|
|
205
|
+
return spatial.toHolon(lat, lng, resolution);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Gets all parent holons at higher resolutions.
|
|
210
|
+
*
|
|
211
|
+
* @param {string} holonId - H3 cell ID
|
|
212
|
+
* @param {number} [maxResolution] - Maximum resolution to traverse up to
|
|
213
|
+
* @returns {Promise<string[]>} Array of parent H3 cell IDs
|
|
214
|
+
*/
|
|
215
|
+
async getParents(holonId, maxResolution) {
|
|
216
|
+
return spatial.getParents(holonId, maxResolution);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Gets all child holons at the next resolution level.
|
|
221
|
+
*
|
|
222
|
+
* @param {string} holonId - H3 cell ID
|
|
223
|
+
* @returns {Promise<string[]>} Array of child H3 cell IDs
|
|
224
|
+
*/
|
|
225
|
+
async getChildren(holonId) {
|
|
226
|
+
return spatial.getChildren(holonId);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Validates if a string is a valid H3 cell ID.
|
|
231
|
+
*
|
|
232
|
+
* @param {string} holonId - String to validate
|
|
233
|
+
* @returns {boolean} True if valid H3 cell ID
|
|
234
|
+
*/
|
|
235
|
+
isValidH3(holonId) {
|
|
236
|
+
return spatial.isValidH3(holonId);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// === Data Operations ===
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Writes data to a specific holon and lens.
|
|
243
|
+
*
|
|
244
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
245
|
+
* @param {string} lensName - Name of the lens (data category)
|
|
246
|
+
* @param {Object} data - Data object to write (must have or will be assigned an id)
|
|
247
|
+
* @param {Object} [options={}] - Write options
|
|
248
|
+
* @param {string} [options.capabilityToken] - Capability token for authorization
|
|
249
|
+
* @param {boolean} [options.validate=true] - Whether to validate against schema
|
|
250
|
+
* @param {boolean} [options.strict] - Override schema strict mode
|
|
251
|
+
* @param {boolean} [options.autoPropagate=true] - Whether to propagate to federated holons
|
|
252
|
+
* @param {Object} [options.propagationOptions] - Options for propagation
|
|
253
|
+
* @returns {Promise<boolean>} True if write succeeded
|
|
254
|
+
* @throws {ValidationError} If holonId, lensName, or data is invalid
|
|
255
|
+
* @throws {AuthorizationError} If capability token is invalid
|
|
256
|
+
*/
|
|
257
|
+
async write(holonId, lensName, data, options = {}) {
|
|
258
|
+
if (!holonId || typeof holonId !== 'string') {
|
|
259
|
+
throw new ValidationError('ValidationError: holonId must be a non-empty string');
|
|
260
|
+
}
|
|
261
|
+
if (!lensName || typeof lensName !== 'string') {
|
|
262
|
+
throw new ValidationError('ValidationError: lensName must be a non-empty string');
|
|
263
|
+
}
|
|
264
|
+
if (!data || typeof data !== 'object') {
|
|
265
|
+
throw new ValidationError('ValidationError: data must be an object');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const capToken = options.capabilityToken || options.capability;
|
|
269
|
+
if (capToken) {
|
|
270
|
+
const authorized = await this.verifyCapability(capToken, 'write', { holonId, lensName });
|
|
271
|
+
if (!authorized) {
|
|
272
|
+
throw new AuthorizationError('AuthorizationError: Invalid capability token for write operation', 'write');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (!data.id) {
|
|
277
|
+
data.id = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName, data.id);
|
|
281
|
+
this._log('DEBUG', 'write', { holonId, lensName, dataId: data.id, path });
|
|
282
|
+
const existingData = await storage.read(this.client, path);
|
|
283
|
+
|
|
284
|
+
// Handle hologram writes
|
|
285
|
+
if (existingData && existingData.hologram === true && existingData.target) {
|
|
286
|
+
const hologramStructureFields = ['hologram', 'soul', 'target', 'id', '_meta'];
|
|
287
|
+
const localOverrideFields = Object.keys(existingData).filter(k => !hologramStructureFields.includes(k));
|
|
288
|
+
|
|
289
|
+
const localData = { ...existingData };
|
|
290
|
+
const sourceUpdates = {};
|
|
291
|
+
|
|
292
|
+
for (const [key, value] of Object.entries(data)) {
|
|
293
|
+
if (hologramStructureFields.includes(key) || key === '_hologram') continue;
|
|
294
|
+
if (localOverrideFields.includes(key)) {
|
|
295
|
+
localData[key] = value;
|
|
296
|
+
} else {
|
|
297
|
+
sourceUpdates[key] = value;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (Object.keys(sourceUpdates).length > 0 && options.validate !== false && this.schemas.has(lensName)) {
|
|
302
|
+
const sourcePath = storage.buildPath(
|
|
303
|
+
existingData.target.appname || this.config.appName,
|
|
304
|
+
existingData.target.holonId,
|
|
305
|
+
existingData.target.lensName,
|
|
306
|
+
existingData.target.dataId
|
|
307
|
+
);
|
|
308
|
+
const currentSourceData = await storage.read(this.client, sourcePath);
|
|
309
|
+
const mergedSourceData = { ...currentSourceData, ...sourceUpdates };
|
|
310
|
+
|
|
311
|
+
const schemaObj = this.schemas.get(lensName);
|
|
312
|
+
const strict = options.strict !== undefined ? options.strict : schemaObj.strict;
|
|
313
|
+
|
|
314
|
+
if (schemaObj.schema && typeof schemaObj.schema === 'object' && !schemaObj.schema.$ref) {
|
|
315
|
+
schema.validate(mergedSourceData, schemaObj.schema, lensName, strict);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const startTime = Date.now();
|
|
320
|
+
await storage.write(this.client, path, localData);
|
|
321
|
+
|
|
322
|
+
if (Object.keys(sourceUpdates).length > 0) {
|
|
323
|
+
const sourcePath = storage.buildPath(
|
|
324
|
+
existingData.target.appname || this.config.appName,
|
|
325
|
+
existingData.target.holonId,
|
|
326
|
+
existingData.target.lensName,
|
|
327
|
+
existingData.target.dataId
|
|
328
|
+
);
|
|
329
|
+
await storage.update(this.client, sourcePath, sourceUpdates);
|
|
330
|
+
await federation.refreshActiveHolograms(
|
|
331
|
+
this.client,
|
|
332
|
+
existingData.target.appname || this.config.appName,
|
|
333
|
+
existingData.target.holonId,
|
|
334
|
+
existingData.target.lensName,
|
|
335
|
+
existingData.target.dataId
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const endTime = Date.now();
|
|
340
|
+
this._metrics.writes++;
|
|
341
|
+
if (!this._metrics.totalWriteTime) this._metrics.totalWriteTime = 0;
|
|
342
|
+
this._metrics.totalWriteTime += (endTime - startTime);
|
|
343
|
+
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Regular write
|
|
348
|
+
if (!data._meta) data._meta = {};
|
|
349
|
+
data._meta.createdAt = data._meta.createdAt || Date.now();
|
|
350
|
+
data._meta.updatedAt = Date.now();
|
|
351
|
+
|
|
352
|
+
if (options.validate !== false && this.schemas.has(lensName)) {
|
|
353
|
+
const schemaObj = this.schemas.get(lensName);
|
|
354
|
+
const strict = options.strict !== undefined ? options.strict : schemaObj.strict;
|
|
355
|
+
if (schemaObj.schema && typeof schemaObj.schema === 'object' && !schemaObj.schema.$ref) {
|
|
356
|
+
schema.validate(data, schemaObj.schema, lensName, strict);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const startTime = Date.now();
|
|
361
|
+
await storage.write(this.client, path, data);
|
|
362
|
+
const endTime = Date.now();
|
|
363
|
+
|
|
364
|
+
this._metrics.writes++;
|
|
365
|
+
if (!this._metrics.totalWriteTime) this._metrics.totalWriteTime = 0;
|
|
366
|
+
this._metrics.totalWriteTime += (endTime - startTime);
|
|
367
|
+
|
|
368
|
+
const { autoPropagate = true } = options;
|
|
369
|
+
if (autoPropagate && !data.hologram) {
|
|
370
|
+
await this.propagate(holonId, lensName, data, options.propagationOptions || {});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Recursively resolves holograms (references) to their source data.
|
|
378
|
+
* Handles circular reference detection and local overrides.
|
|
379
|
+
*
|
|
380
|
+
* @private
|
|
381
|
+
* @param {Object|Array|null} data - Data that may contain holograms
|
|
382
|
+
* @param {Set<string>} [visited=new Set()] - Set of visited paths for circular detection
|
|
383
|
+
* @returns {Promise<Object|Array|null>} Resolved data with holograms replaced by source data
|
|
384
|
+
*/
|
|
385
|
+
async _resolveHolograms(data, visited = new Set()) {
|
|
386
|
+
if (!data) return data;
|
|
387
|
+
|
|
388
|
+
if (Array.isArray(data)) {
|
|
389
|
+
const resolved = [];
|
|
390
|
+
for (const item of data) {
|
|
391
|
+
const resolvedItem = await this._resolveHolograms(item, new Set());
|
|
392
|
+
if (resolvedItem !== null) {
|
|
393
|
+
resolved.push(resolvedItem);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return resolved;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (data && typeof data === 'object') {
|
|
400
|
+
if (data.hologram === true && data.target) {
|
|
401
|
+
const sourcePath = storage.buildPath(
|
|
402
|
+
data.target.appname || this.config.appName,
|
|
403
|
+
data.target.holonId,
|
|
404
|
+
data.target.lensName,
|
|
405
|
+
data.target.dataId
|
|
406
|
+
);
|
|
407
|
+
this._log('DEBUG', 'resolving hologram', {
|
|
408
|
+
hologramId: data.id,
|
|
409
|
+
sourcePath,
|
|
410
|
+
targetHolon: data.target.holonId,
|
|
411
|
+
targetLens: data.target.lensName,
|
|
412
|
+
targetDataId: data.target.dataId
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Circular reference detection
|
|
416
|
+
if (visited.has(sourcePath)) {
|
|
417
|
+
this._log('WARN', 'Circular hologram reference detected', { sourcePath });
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
visited.add(sourcePath);
|
|
421
|
+
|
|
422
|
+
let resolveOptions = {};
|
|
423
|
+
if (data.target.authorPubKey) {
|
|
424
|
+
resolveOptions.authors = [data.target.authorPubKey];
|
|
425
|
+
resolveOptions.includeAuthor = true;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const sourceData = await storage.read(this.client, sourcePath, resolveOptions);
|
|
429
|
+
this._log('DEBUG', 'hologram source fetched', { found: !!sourceData, sourcePath });
|
|
430
|
+
if (sourceData) {
|
|
431
|
+
// If source is also a hologram, recursively resolve it
|
|
432
|
+
let resolvedSource = sourceData;
|
|
433
|
+
if (sourceData.hologram === true && sourceData.target) {
|
|
434
|
+
resolvedSource = await this._resolveHolograms(sourceData, visited);
|
|
435
|
+
if (resolvedSource === null) {
|
|
436
|
+
return null; // Circular reference or unresolvable
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Get local override fields from the hologram (excluding hologram structure fields)
|
|
441
|
+
const hologramStructureFields = ['hologram', 'soul', 'target', '_meta', 'id', 'capability', 'crossHolosphere'];
|
|
442
|
+
const localOverrides = {};
|
|
443
|
+
for (const [k, v] of Object.entries(data)) {
|
|
444
|
+
if (!hologramStructureFields.includes(k)) {
|
|
445
|
+
localOverrides[k] = v;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const merged = {
|
|
450
|
+
...resolvedSource,
|
|
451
|
+
...localOverrides,
|
|
452
|
+
_hologram: {
|
|
453
|
+
isHologram: true,
|
|
454
|
+
soul: data.soul,
|
|
455
|
+
sourceHolon: data.target.holonId,
|
|
456
|
+
source: data.target,
|
|
457
|
+
localOverrides: Object.keys(localOverrides),
|
|
458
|
+
crossHolosphere: data.crossHolosphere || false,
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
// Preserve source _meta but add hologram source info
|
|
463
|
+
if (resolvedSource._meta) {
|
|
464
|
+
merged._meta = { ...resolvedSource._meta, source: data.target.holonId };
|
|
465
|
+
} else {
|
|
466
|
+
merged._meta = { source: data.target.holonId };
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
return merged;
|
|
470
|
+
}
|
|
471
|
+
return null; // Source not found
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return data;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Reads data from a specific holon and lens.
|
|
479
|
+
*
|
|
480
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
481
|
+
* @param {string} lensName - Name of the lens (data category)
|
|
482
|
+
* @param {string|null} [dataId=null] - Specific data ID, or null to read all
|
|
483
|
+
* @param {Object} [options={}] - Read options
|
|
484
|
+
* @param {string} [options.capabilityToken] - Capability token for authorization
|
|
485
|
+
* @param {boolean} [options.resolveHolograms=true] - Whether to resolve hologram references
|
|
486
|
+
* @returns {Promise<Object|Array|null>} Data object, array of objects, or null if not found
|
|
487
|
+
* @throws {ValidationError} If holonId or lensName is invalid
|
|
488
|
+
* @throws {AuthorizationError} If capability token is invalid
|
|
489
|
+
*/
|
|
490
|
+
async read(holonId, lensName, dataId = null, options = {}) {
|
|
491
|
+
if (!holonId || typeof holonId !== 'string') {
|
|
492
|
+
throw new ValidationError('ValidationError: holonId must be a non-empty string');
|
|
493
|
+
}
|
|
494
|
+
if (!lensName || typeof lensName !== 'string') {
|
|
495
|
+
throw new ValidationError('ValidationError: lensName must be a non-empty string');
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const capToken = options.capabilityToken || options.capability;
|
|
499
|
+
if (capToken) {
|
|
500
|
+
const authorized = await this.verifyCapability(capToken, 'read', { holonId, lensName, dataId });
|
|
501
|
+
if (!authorized) {
|
|
502
|
+
throw new AuthorizationError('AuthorizationError: Invalid capability token for read operation', 'read');
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const startTime = Date.now();
|
|
507
|
+
let result;
|
|
508
|
+
|
|
509
|
+
if (dataId) {
|
|
510
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName, dataId);
|
|
511
|
+
this._log('DEBUG', 'read', { holonId, lensName, dataId, path });
|
|
512
|
+
result = await storage.read(this.client, path);
|
|
513
|
+
this._log('DEBUG', 'read result', { found: !!result, isHologram: result?.hologram === true });
|
|
514
|
+
} else {
|
|
515
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName);
|
|
516
|
+
this._log('DEBUG', 'readAll', { holonId, lensName, path });
|
|
517
|
+
result = await storage.readAll(this.client, path);
|
|
518
|
+
this._log('DEBUG', 'readAll result', { count: Array.isArray(result) ? result.length : 0 });
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const { resolveHolograms = true } = options;
|
|
522
|
+
if (resolveHolograms && result) {
|
|
523
|
+
this._log('DEBUG', 'resolving holograms', { itemCount: Array.isArray(result) ? result.length : 1 });
|
|
524
|
+
result = await this._resolveHolograms(result);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const endTime = Date.now();
|
|
528
|
+
this._metrics.reads++;
|
|
529
|
+
if (!this._metrics.totalReadTime) this._metrics.totalReadTime = 0;
|
|
530
|
+
this._metrics.totalReadTime += (endTime - startTime);
|
|
531
|
+
|
|
532
|
+
return result;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Updates existing data in a specific holon and lens.
|
|
537
|
+
*
|
|
538
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
539
|
+
* @param {string} lensName - Name of the lens (data category)
|
|
540
|
+
* @param {string} dataId - ID of the data to update
|
|
541
|
+
* @param {Object} updates - Object containing fields to update
|
|
542
|
+
* @param {Object} [options={}] - Update options
|
|
543
|
+
* @param {string} [options.capabilityToken] - Capability token for authorization
|
|
544
|
+
* @param {boolean} [options.validate=true] - Whether to validate against schema
|
|
545
|
+
* @param {boolean} [options.strict] - Override schema strict mode
|
|
546
|
+
* @returns {Promise<boolean>} True if update succeeded, false if data not found
|
|
547
|
+
* @throws {ValidationError} If holonId, lensName, dataId, or updates is invalid
|
|
548
|
+
* @throws {AuthorizationError} If capability token is invalid
|
|
549
|
+
*/
|
|
550
|
+
async update(holonId, lensName, dataId, updates, options = {}) {
|
|
551
|
+
if (!holonId || typeof holonId !== 'string') {
|
|
552
|
+
throw new ValidationError('ValidationError: holonId must be a non-empty string');
|
|
553
|
+
}
|
|
554
|
+
if (!lensName || typeof lensName !== 'string') {
|
|
555
|
+
throw new ValidationError('ValidationError: lensName must be a non-empty string');
|
|
556
|
+
}
|
|
557
|
+
if (!dataId || typeof dataId !== 'string') {
|
|
558
|
+
throw new ValidationError('ValidationError: dataId must be a non-empty string');
|
|
559
|
+
}
|
|
560
|
+
if (!updates || typeof updates !== 'object') {
|
|
561
|
+
throw new ValidationError('ValidationError: updates must be an object');
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
const capToken = options.capabilityToken || options.capability;
|
|
565
|
+
if (capToken) {
|
|
566
|
+
const authorized = await this.verifyCapability(capToken, 'write', { holonId, lensName, dataId });
|
|
567
|
+
if (!authorized) {
|
|
568
|
+
throw new AuthorizationError('AuthorizationError: Invalid capability token for update operation', 'write');
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName, dataId);
|
|
573
|
+
const existingData = await storage.read(this.client, path);
|
|
574
|
+
|
|
575
|
+
if (!existingData) {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// Handle hologram updates
|
|
580
|
+
if (existingData.hologram === true && existingData.target) {
|
|
581
|
+
return this.write(holonId, lensName, { ...existingData, ...updates, id: dataId }, options);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const mergedData = { ...existingData, ...updates };
|
|
585
|
+
mergedData._meta = mergedData._meta || {};
|
|
586
|
+
mergedData._meta.updatedAt = Date.now();
|
|
587
|
+
|
|
588
|
+
if (options.validate !== false && this.schemas.has(lensName)) {
|
|
589
|
+
const schemaObj = this.schemas.get(lensName);
|
|
590
|
+
const strict = options.strict !== undefined ? options.strict : schemaObj.strict;
|
|
591
|
+
if (schemaObj.schema && typeof schemaObj.schema === 'object' && !schemaObj.schema.$ref) {
|
|
592
|
+
schema.validate(mergedData, schemaObj.schema, lensName, strict);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const startTime = Date.now();
|
|
597
|
+
await storage.write(this.client, path, mergedData);
|
|
598
|
+
const endTime = Date.now();
|
|
599
|
+
|
|
600
|
+
this._metrics.writes++;
|
|
601
|
+
if (!this._metrics.totalWriteTime) this._metrics.totalWriteTime = 0;
|
|
602
|
+
this._metrics.totalWriteTime += (endTime - startTime);
|
|
603
|
+
|
|
604
|
+
if (existingData._meta && existingData._meta.activeHolograms) {
|
|
605
|
+
await federation.refreshActiveHolograms(this.client, this.config.appName, holonId, lensName, dataId);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return true;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Deletes data from a specific holon and lens.
|
|
613
|
+
*
|
|
614
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
615
|
+
* @param {string} lensName - Name of the lens (data category)
|
|
616
|
+
* @param {string} dataId - ID of the data to delete
|
|
617
|
+
* @param {Object} [options={}] - Delete options
|
|
618
|
+
* @param {string} [options.capabilityToken] - Capability token for authorization
|
|
619
|
+
* @returns {Promise<boolean>} True if deletion succeeded, false if data not found
|
|
620
|
+
* @throws {ValidationError} If holonId, lensName, or dataId is invalid
|
|
621
|
+
* @throws {AuthorizationError} If not owner and no valid capability token
|
|
622
|
+
*/
|
|
623
|
+
async delete(holonId, lensName, dataId, options = {}) {
|
|
624
|
+
if (!holonId || typeof holonId !== 'string') {
|
|
625
|
+
throw new ValidationError('ValidationError: holonId must be a non-empty string');
|
|
626
|
+
}
|
|
627
|
+
if (!lensName || typeof lensName !== 'string') {
|
|
628
|
+
throw new ValidationError('ValidationError: lensName must be a non-empty string');
|
|
629
|
+
}
|
|
630
|
+
if (!dataId || typeof dataId !== 'string') {
|
|
631
|
+
throw new ValidationError('ValidationError: dataId must be a non-empty string');
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName, dataId);
|
|
635
|
+
const existingData = await storage.read(this.client, path);
|
|
636
|
+
|
|
637
|
+
// Return false if data doesn't exist
|
|
638
|
+
if (!existingData) {
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Check authorization: owner can delete, others need capability token
|
|
643
|
+
const dataOwner = existingData.owner || existingData._creator;
|
|
644
|
+
const isOwner = !dataOwner || dataOwner === this.client.publicKey;
|
|
645
|
+
|
|
646
|
+
const capToken = options.capabilityToken || options.capability;
|
|
647
|
+
if (!isOwner) {
|
|
648
|
+
// Non-owner must provide a valid capability token
|
|
649
|
+
if (!capToken) {
|
|
650
|
+
throw new AuthorizationError('AuthorizationError: Capability token required for delete operation', 'delete');
|
|
651
|
+
}
|
|
652
|
+
const authorized = await this.verifyCapability(capToken, 'delete', { holonId, lensName, dataId });
|
|
653
|
+
if (!authorized) {
|
|
654
|
+
throw new AuthorizationError('AuthorizationError: Invalid capability token for delete operation', 'delete');
|
|
655
|
+
}
|
|
656
|
+
} else if (capToken) {
|
|
657
|
+
// Owner provided a token - validate it anyway
|
|
658
|
+
const authorized = await this.verifyCapability(capToken, 'delete', { holonId, lensName, dataId });
|
|
659
|
+
if (!authorized) {
|
|
660
|
+
throw new AuthorizationError('AuthorizationError: Invalid capability token for delete operation', 'delete');
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (existingData.hologram === true) {
|
|
665
|
+
return this.deleteHologram(holonId, lensName, dataId, options);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
await storage.deleteData(this.client, path);
|
|
669
|
+
this._metrics.deletes++;
|
|
670
|
+
return true;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// === Global Tables ===
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Writes data to a global table (not holon-specific).
|
|
677
|
+
*
|
|
678
|
+
* @param {string} table - Name of the global table
|
|
679
|
+
* @param {Object} data - Data object to write (must have an id field)
|
|
680
|
+
* @returns {Promise<boolean>} True if write succeeded
|
|
681
|
+
*/
|
|
682
|
+
async writeGlobal(table, data) {
|
|
683
|
+
return globalTables.writeGlobal(this.client, this.config.appName, table, data);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Reads data from a global table.
|
|
688
|
+
*
|
|
689
|
+
* @param {string} table - Name of the global table
|
|
690
|
+
* @param {string|null} [key=null] - Specific key to read, or null to read all
|
|
691
|
+
* @returns {Promise<Object|Array|null>} Data object, array of objects, or null
|
|
692
|
+
*/
|
|
693
|
+
async readGlobal(table, key = null) {
|
|
694
|
+
return globalTables.readGlobal(this.client, this.config.appName, table, key);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Updates data in a global table.
|
|
699
|
+
*
|
|
700
|
+
* @param {string} table - Name of the global table
|
|
701
|
+
* @param {string} key - Key of the data to update
|
|
702
|
+
* @param {Object} updates - Object containing fields to update
|
|
703
|
+
* @returns {Promise<boolean>} True if update succeeded
|
|
704
|
+
*/
|
|
705
|
+
async updateGlobal(table, key, updates) {
|
|
706
|
+
return globalTables.updateGlobal(this.client, this.config.appName, table, key, updates);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Deletes data from a global table.
|
|
711
|
+
*
|
|
712
|
+
* @param {string} table - Name of the global table
|
|
713
|
+
* @param {string} key - Key of the data to delete
|
|
714
|
+
* @returns {Promise<boolean>} True if deletion succeeded
|
|
715
|
+
*/
|
|
716
|
+
async deleteGlobal(table, key) {
|
|
717
|
+
return globalTables.deleteGlobal(this.client, this.config.appName, table, key);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Gets all data from a global table.
|
|
722
|
+
*
|
|
723
|
+
* @param {string} table - Name of the global table
|
|
724
|
+
* @returns {Promise<Array>} Array of all data objects in the table
|
|
725
|
+
*/
|
|
726
|
+
async getAllGlobal(table) {
|
|
727
|
+
return globalTables.getAllGlobal(this.client, this.config.appName, table);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Deletes all data from a global table.
|
|
732
|
+
*
|
|
733
|
+
* @param {string} table - Name of the global table
|
|
734
|
+
* @returns {Promise<boolean>} True if deletion succeeded
|
|
735
|
+
*/
|
|
736
|
+
async deleteAllGlobal(table) {
|
|
737
|
+
return globalTables.deleteAllGlobal(this.client, this.config.appName, table);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// === Batch Operations ===
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Gets all data from a specific holon and lens.
|
|
744
|
+
*
|
|
745
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
746
|
+
* @param {string} lensName - Name of the lens (data category)
|
|
747
|
+
* @returns {Promise<Array|null>} Array of data objects or null
|
|
748
|
+
*/
|
|
749
|
+
async getAll(holonId, lensName) {
|
|
750
|
+
return this.read(holonId, lensName, null);
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Deletes all data from a specific holon and lens.
|
|
755
|
+
*
|
|
756
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
757
|
+
* @param {string} lensName - Name of the lens (data category)
|
|
758
|
+
* @returns {Promise<boolean>} True if deletion succeeded
|
|
759
|
+
*/
|
|
760
|
+
async deleteAll(holonId, lensName) {
|
|
761
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName);
|
|
762
|
+
return storage.deleteAll(this.client, path);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// === Schema Operations ===
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Sets a JSON Schema for validating data in a specific lens.
|
|
769
|
+
*
|
|
770
|
+
* @param {string} lensName - Name of the lens to associate the schema with
|
|
771
|
+
* @param {Object|string} schemaInput - JSON Schema object or URI reference
|
|
772
|
+
* @param {boolean} [strict=false] - If true, validation will reject additional properties
|
|
773
|
+
* @returns {Promise<void>}
|
|
774
|
+
* @throws {ValidationError} If lensName is invalid or schema format is invalid
|
|
775
|
+
*/
|
|
776
|
+
async setSchema(lensName, schemaInput, strict = false) {
|
|
777
|
+
if (!lensName || typeof lensName !== 'string') {
|
|
778
|
+
throw new ValidationError('ValidationError: lensName must be a non-empty string');
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Handle null/undefined
|
|
782
|
+
if (schemaInput == null) {
|
|
783
|
+
throw new ValidationError('ValidationError: schema cannot be null or undefined');
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
let schemaObj;
|
|
787
|
+
|
|
788
|
+
// Handle URI string - store as $ref
|
|
789
|
+
if (typeof schemaInput === 'string') {
|
|
790
|
+
schemaObj = { $ref: schemaInput };
|
|
791
|
+
} else if (typeof schemaInput === 'object') {
|
|
792
|
+
// Validate it looks like a JSON Schema (must have type or $ref or properties or items)
|
|
793
|
+
const isValidSchema = schemaInput.$ref ||
|
|
794
|
+
schemaInput.type ||
|
|
795
|
+
schemaInput.properties ||
|
|
796
|
+
schemaInput.items ||
|
|
797
|
+
schemaInput.allOf ||
|
|
798
|
+
schemaInput.anyOf ||
|
|
799
|
+
schemaInput.oneOf ||
|
|
800
|
+
schemaInput.$schema;
|
|
801
|
+
|
|
802
|
+
if (!isValidSchema) {
|
|
803
|
+
throw new ValidationError('ValidationError: Invalid JSON Schema format');
|
|
804
|
+
}
|
|
805
|
+
schemaObj = schemaInput;
|
|
806
|
+
} else {
|
|
807
|
+
throw new ValidationError('ValidationError: schema must be an object or URI string');
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
this.schemas.set(lensName, { schema: schemaObj, strict, timestamp: Date.now() });
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* Gets the JSON Schema for a specific lens.
|
|
815
|
+
*
|
|
816
|
+
* @param {string} lensName - Name of the lens
|
|
817
|
+
* @returns {Promise<Object|null>} The schema object or null if not set
|
|
818
|
+
*/
|
|
819
|
+
async getSchema(lensName) {
|
|
820
|
+
const schemaObj = this.schemas.get(lensName);
|
|
821
|
+
return schemaObj ? schemaObj.schema : null;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Clears the JSON Schema for a specific lens.
|
|
826
|
+
*
|
|
827
|
+
* @param {string} lensName - Name of the lens
|
|
828
|
+
* @returns {Promise<void>}
|
|
829
|
+
*/
|
|
830
|
+
async clearSchema(lensName) {
|
|
831
|
+
this.schemas.delete(lensName);
|
|
832
|
+
// Returns undefined for contract compliance
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// === Federation Operations ===
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Sets up federation between two holons for a specific lens.
|
|
839
|
+
* Federation enables data sharing and synchronization between holons.
|
|
840
|
+
*
|
|
841
|
+
* @param {string} sourceHolon - Source holon H3 cell ID
|
|
842
|
+
* @param {string} targetHolon - Target holon H3 cell ID
|
|
843
|
+
* @param {string} lensName - Name of the lens to federate
|
|
844
|
+
* @param {Object} [options={}] - Federation options
|
|
845
|
+
* @param {string} [options.direction='outbound'] - Direction: 'inbound', 'outbound', or 'bidirectional'
|
|
846
|
+
* @param {string} [options.mode='reference'] - Mode: 'reference' (hologram) or 'copy'
|
|
847
|
+
* @param {Function} [options.filter] - Filter function to select which data to federate
|
|
848
|
+
* @returns {Promise<boolean>} True if federation was set up successfully
|
|
849
|
+
* @throws {Error} If trying to federate a holon with itself or invalid direction
|
|
850
|
+
*/
|
|
851
|
+
async federate(sourceHolon, targetHolon, lensName, options = {}) {
|
|
852
|
+
const { direction = 'outbound', mode = 'reference', filter = null } = options;
|
|
853
|
+
|
|
854
|
+
// Validation
|
|
855
|
+
if (sourceHolon === targetHolon) {
|
|
856
|
+
throw new Error('Cannot federate a holon with itself');
|
|
857
|
+
}
|
|
858
|
+
if (!['inbound', 'outbound', 'bidirectional'].includes(direction)) {
|
|
859
|
+
throw new Error(`Invalid direction: ${direction}. Must be 'inbound', 'outbound', or 'bidirectional'`);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// Store federation config
|
|
863
|
+
await federation.setupFederation(
|
|
864
|
+
this.client,
|
|
865
|
+
this.config.appName,
|
|
866
|
+
sourceHolon,
|
|
867
|
+
targetHolon,
|
|
868
|
+
lensName,
|
|
869
|
+
options
|
|
870
|
+
);
|
|
871
|
+
|
|
872
|
+
// Actually propagate existing data based on direction
|
|
873
|
+
if (direction === 'outbound' || direction === 'bidirectional') {
|
|
874
|
+
await this._propagateExistingData(sourceHolon, targetHolon, lensName, { mode, filter });
|
|
875
|
+
}
|
|
876
|
+
if (direction === 'inbound' || direction === 'bidirectional') {
|
|
877
|
+
await this._propagateExistingData(targetHolon, sourceHolon, lensName, { mode, filter });
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
this._metrics.federations = (this._metrics.federations || 0) + 1;
|
|
881
|
+
return true;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Propagates existing data from one holon to another.
|
|
886
|
+
*
|
|
887
|
+
* @private
|
|
888
|
+
* @param {string} fromHolon - Source holon H3 cell ID
|
|
889
|
+
* @param {string} toHolon - Target holon H3 cell ID
|
|
890
|
+
* @param {string} lensName - Name of the lens
|
|
891
|
+
* @param {Object} [options={}] - Propagation options
|
|
892
|
+
* @param {string} [options.mode='reference'] - Mode: 'reference' or 'copy'
|
|
893
|
+
* @param {Function} [options.filter] - Filter function to select data
|
|
894
|
+
* @returns {Promise<void>}
|
|
895
|
+
*/
|
|
896
|
+
async _propagateExistingData(fromHolon, toHolon, lensName, options = {}) {
|
|
897
|
+
const { mode = 'reference', filter = null } = options;
|
|
898
|
+
const existingData = await this.read(fromHolon, lensName, null, { resolveHolograms: false });
|
|
899
|
+
if (!existingData) return;
|
|
900
|
+
|
|
901
|
+
const items = Array.isArray(existingData) ? existingData : [existingData];
|
|
902
|
+
for (const item of items) {
|
|
903
|
+
// Skip holograms to avoid circular propagation
|
|
904
|
+
if (item.hologram === true) continue;
|
|
905
|
+
// Apply filter if provided
|
|
906
|
+
if (filter && !filter(item)) continue;
|
|
907
|
+
await federation.propagateData(
|
|
908
|
+
this.client,
|
|
909
|
+
this.config.appName,
|
|
910
|
+
item,
|
|
911
|
+
fromHolon,
|
|
912
|
+
toHolon,
|
|
913
|
+
lensName,
|
|
914
|
+
mode
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Gets federated data from a holon, optionally resolving holograms.
|
|
921
|
+
*
|
|
922
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
923
|
+
* @param {string} lensName - Name of the lens
|
|
924
|
+
* @param {Object} [options={}] - Options
|
|
925
|
+
* @param {boolean} [options.resolveHolograms=true] - Whether to resolve hologram references
|
|
926
|
+
* @returns {Promise<Array|null>} Array of data objects or null
|
|
927
|
+
*/
|
|
928
|
+
async getFederatedData(holonId, lensName, options = {}) {
|
|
929
|
+
const { resolveHolograms = true } = options;
|
|
930
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName);
|
|
931
|
+
const data = await storage.readAll(this.client, path);
|
|
932
|
+
|
|
933
|
+
if (!data || !resolveHolograms) return data;
|
|
934
|
+
|
|
935
|
+
// Resolve holograms using existing method
|
|
936
|
+
return this._resolveHolograms(data);
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Removes federation between two holons for a specific lens.
|
|
941
|
+
*
|
|
942
|
+
* @param {string} sourceHolon - Source holon H3 cell ID
|
|
943
|
+
* @param {string} targetHolon - Target holon H3 cell ID
|
|
944
|
+
* @param {string} lensName - Name of the lens
|
|
945
|
+
* @returns {Promise<boolean>} Always returns true (idempotent operation)
|
|
946
|
+
*/
|
|
947
|
+
async unfederate(sourceHolon, targetHolon, lensName) {
|
|
948
|
+
// Remove federation config for this relationship - idempotent
|
|
949
|
+
const configPath = storage.buildPath(this.config.appName, sourceHolon, lensName, '_federation');
|
|
950
|
+
try {
|
|
951
|
+
await storage.deleteData(this.client, configPath);
|
|
952
|
+
} catch (e) {
|
|
953
|
+
// Ignore errors - already unfederated or doesn't exist
|
|
954
|
+
}
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* Updates local override values on a hologram.
|
|
960
|
+
*
|
|
961
|
+
* @param {string} holonId - H3 cell ID where the hologram exists
|
|
962
|
+
* @param {string} lensName - Name of the lens
|
|
963
|
+
* @param {string} dataId - ID of the hologram
|
|
964
|
+
* @param {Object} overrides - Object containing local override values
|
|
965
|
+
* @returns {Promise<boolean>} True if update succeeded
|
|
966
|
+
*/
|
|
967
|
+
async updateHologramOverrides(holonId, lensName, dataId, overrides) {
|
|
968
|
+
return federation.updateHologramOverrides(
|
|
969
|
+
this.client,
|
|
970
|
+
this.config.appName,
|
|
971
|
+
holonId,
|
|
972
|
+
lensName,
|
|
973
|
+
dataId,
|
|
974
|
+
overrides
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/**
|
|
979
|
+
* Creates a hologram (reference) object structure.
|
|
980
|
+
*
|
|
981
|
+
* @param {string} sourceHolon - Source holon H3 cell ID where the original data lives
|
|
982
|
+
* @param {string} lensName - Name of the lens
|
|
983
|
+
* @param {Object} data - Data object containing the id to reference
|
|
984
|
+
* @param {string} [targetHolon=null] - Target holon for the hologram, defaults to sourceHolon
|
|
985
|
+
* @returns {Object} Hologram object structure
|
|
986
|
+
*/
|
|
987
|
+
createHologram(sourceHolon, lensName, data, targetHolon = null) {
|
|
988
|
+
return federation.createHologram(
|
|
989
|
+
sourceHolon,
|
|
990
|
+
targetHolon || sourceHolon,
|
|
991
|
+
lensName,
|
|
992
|
+
data.id,
|
|
993
|
+
this.config.appName
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
/**
|
|
998
|
+
* Gets all active holograms (references) pointing to a specific data item.
|
|
999
|
+
*
|
|
1000
|
+
* @param {string} holonId - H3 cell ID of the source holon
|
|
1001
|
+
* @param {string} lensName - Name of the lens
|
|
1002
|
+
* @param {string} dataId - ID of the source data
|
|
1003
|
+
* @returns {Promise<Array>} Array of active hologram references
|
|
1004
|
+
*/
|
|
1005
|
+
async getActiveHolograms(holonId, lensName, dataId) {
|
|
1006
|
+
// Read the source data and return its activeHolograms list
|
|
1007
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName, dataId);
|
|
1008
|
+
const sourceData = await storage.read(this.client, path);
|
|
1009
|
+
if (!sourceData || !sourceData._meta || !sourceData._meta.activeHolograms) {
|
|
1010
|
+
return [];
|
|
1011
|
+
}
|
|
1012
|
+
return sourceData._meta.activeHolograms;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* Removes an active hologram reference from a source data item.
|
|
1017
|
+
*
|
|
1018
|
+
* @param {string} sourceHolon - Source holon H3 cell ID
|
|
1019
|
+
* @param {string} lensName - Name of the lens
|
|
1020
|
+
* @param {string} dataId - ID of the source data
|
|
1021
|
+
* @param {string} targetHolon - Target holon where the hologram exists
|
|
1022
|
+
* @returns {Promise<boolean>} True if removal succeeded
|
|
1023
|
+
*/
|
|
1024
|
+
async removeActiveHologram(sourceHolon, lensName, dataId, targetHolon) {
|
|
1025
|
+
return federation.removeActiveHologram(
|
|
1026
|
+
this.client,
|
|
1027
|
+
this.config.appName,
|
|
1028
|
+
sourceHolon,
|
|
1029
|
+
lensName,
|
|
1030
|
+
dataId,
|
|
1031
|
+
targetHolon
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* Deletes a hologram and cleans up its references.
|
|
1037
|
+
*
|
|
1038
|
+
* @param {string} holonId - H3 cell ID where the hologram exists
|
|
1039
|
+
* @param {string} lensName - Name of the lens
|
|
1040
|
+
* @param {string} dataId - ID of the hologram to delete
|
|
1041
|
+
* @param {Object} [options={}] - Delete options
|
|
1042
|
+
* @returns {Promise<boolean>} True if deletion succeeded
|
|
1043
|
+
*/
|
|
1044
|
+
async deleteHologram(holonId, lensName, dataId, options = {}) {
|
|
1045
|
+
return federation.deleteHologram(
|
|
1046
|
+
this.client,
|
|
1047
|
+
this.config.appName,
|
|
1048
|
+
holonId,
|
|
1049
|
+
lensName,
|
|
1050
|
+
dataId,
|
|
1051
|
+
options
|
|
1052
|
+
);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Propagates data from source holon to target holon.
|
|
1057
|
+
*
|
|
1058
|
+
* @param {Object} data - Data to propagate
|
|
1059
|
+
* @param {string} sourceHolon - Source holon H3 cell ID
|
|
1060
|
+
* @param {string} targetHolon - Target holon H3 cell ID
|
|
1061
|
+
* @param {string} lensName - Name of the lens
|
|
1062
|
+
* @param {Object} [options={}] - Propagation options
|
|
1063
|
+
* @param {string} [options.mode='reference'] - Mode: 'reference' creates hologram, 'copy' duplicates data
|
|
1064
|
+
* @returns {Promise<Object>} Result of propagation
|
|
1065
|
+
*/
|
|
1066
|
+
async propagateData(data, sourceHolon, targetHolon, lensName, options = {}) {
|
|
1067
|
+
// Extract mode from options, default to 'reference' for hologram creation
|
|
1068
|
+
const mode = options.mode || 'reference';
|
|
1069
|
+
return federation.propagateData(
|
|
1070
|
+
this.client,
|
|
1071
|
+
this.config.appName,
|
|
1072
|
+
data,
|
|
1073
|
+
sourceHolon,
|
|
1074
|
+
targetHolon,
|
|
1075
|
+
lensName,
|
|
1076
|
+
mode
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* Resolves a hologram to its source data.
|
|
1082
|
+
*
|
|
1083
|
+
* @param {Object} hologram - Hologram object to resolve
|
|
1084
|
+
* @param {Object} [options={}] - Resolution options
|
|
1085
|
+
* @returns {Promise<Object|null>} Resolved data or null if source not found
|
|
1086
|
+
*/
|
|
1087
|
+
async resolveHologram(hologram, options = {}) {
|
|
1088
|
+
return federation.resolveHologram(this.client, hologram, new Set(), [], { ...options, appname: this.config.appName });
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* Checks if an object is a hologram (unresolved reference).
|
|
1093
|
+
*
|
|
1094
|
+
* @param {Object} data - Data object to check
|
|
1095
|
+
* @returns {boolean} True if the object is a hologram
|
|
1096
|
+
*/
|
|
1097
|
+
isHologram(data) {
|
|
1098
|
+
return federation.isHologram(data);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Checks if an object is a resolved hologram (has _hologram metadata).
|
|
1103
|
+
*
|
|
1104
|
+
* @param {Object} data - Data object to check
|
|
1105
|
+
* @returns {boolean} True if the object is a resolved hologram
|
|
1106
|
+
*/
|
|
1107
|
+
isResolvedHologram(data) {
|
|
1108
|
+
return federation.isResolvedHologram(data);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* Gets the source information from a hologram or resolved hologram.
|
|
1113
|
+
*
|
|
1114
|
+
* @param {Object} data - Hologram or resolved hologram object
|
|
1115
|
+
* @returns {Object|null} Source information or null
|
|
1116
|
+
*/
|
|
1117
|
+
getHologramSource(data) {
|
|
1118
|
+
return federation.getHologramSource(data);
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* Cleans up circular hologram references in a holon.
|
|
1123
|
+
*
|
|
1124
|
+
* @param {string} holonId - H3 cell ID of the holon
|
|
1125
|
+
* @param {string} lensName - Name of the lens
|
|
1126
|
+
* @param {Object} [options={}] - Cleanup options
|
|
1127
|
+
* @returns {Promise<Object>} Cleanup results
|
|
1128
|
+
*/
|
|
1129
|
+
async cleanupCircularHolograms(holonId, lensName, options = {}) {
|
|
1130
|
+
return federation.cleanupCircularHolograms(
|
|
1131
|
+
this.client,
|
|
1132
|
+
this.config.appName,
|
|
1133
|
+
holonId,
|
|
1134
|
+
lensName,
|
|
1135
|
+
options
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* Cleans up circular hologram references for specific data IDs.
|
|
1141
|
+
*
|
|
1142
|
+
* @param {string} holonId - H3 cell ID of the holon
|
|
1143
|
+
* @param {string} lensName - Name of the lens
|
|
1144
|
+
* @param {string[]} dataIds - Array of data IDs to check
|
|
1145
|
+
* @param {Object} [options={}] - Cleanup options
|
|
1146
|
+
* @returns {Promise<Object>} Cleanup results
|
|
1147
|
+
*/
|
|
1148
|
+
async cleanupCircularHologramsByIds(holonId, lensName, dataIds, options = {}) {
|
|
1149
|
+
return federation.cleanupCircularHologramsByIds(
|
|
1150
|
+
this.client,
|
|
1151
|
+
this.config.appName,
|
|
1152
|
+
holonId,
|
|
1153
|
+
lensName,
|
|
1154
|
+
dataIds,
|
|
1155
|
+
options
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* Propagates data to all federated holons.
|
|
1161
|
+
*
|
|
1162
|
+
* @param {string} holonId - Source holon H3 cell ID
|
|
1163
|
+
* @param {string} lensName - Name of the lens
|
|
1164
|
+
* @param {Object} data - Data to propagate
|
|
1165
|
+
* @param {Object} [options={}] - Propagation options
|
|
1166
|
+
* @param {boolean} [options.useHolograms=true] - Whether to create holograms
|
|
1167
|
+
* @param {boolean} [options.resolveExisting=true] - Whether to resolve existing data
|
|
1168
|
+
* @returns {Promise<Array|undefined>} Array of propagation results or undefined if no targets
|
|
1169
|
+
*/
|
|
1170
|
+
async propagate(holonId, lensName, data, options = {}) {
|
|
1171
|
+
const federationData = await this.getFederation(holonId);
|
|
1172
|
+
// getFederation returns an object with federated array, not an array directly
|
|
1173
|
+
const targets = federationData?.federated || federationData?.outbound || [];
|
|
1174
|
+
if (!targets || targets.length === 0) return;
|
|
1175
|
+
|
|
1176
|
+
const { useHolograms = true, resolveExisting = true } = options;
|
|
1177
|
+
const results = [];
|
|
1178
|
+
|
|
1179
|
+
for (const targetHolonId of targets) {
|
|
1180
|
+
const result = await this.propagateData(
|
|
1181
|
+
data,
|
|
1182
|
+
holonId,
|
|
1183
|
+
targetHolonId,
|
|
1184
|
+
lensName,
|
|
1185
|
+
{ useHolograms, resolveExisting }
|
|
1186
|
+
);
|
|
1187
|
+
results.push({ parent: targetHolonId, ...result });
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
return results;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/**
|
|
1194
|
+
* Gets the federation configuration for a holon.
|
|
1195
|
+
*
|
|
1196
|
+
* @param {string} holonId - H3 cell ID of the holon
|
|
1197
|
+
* @returns {Promise<Object|null>} Federation configuration object or null
|
|
1198
|
+
* @throws {Error} If holonId is not provided
|
|
1199
|
+
*/
|
|
1200
|
+
async getFederation(holonId) {
|
|
1201
|
+
if (!holonId) {
|
|
1202
|
+
throw new Error('getFederation: Missing holon ID');
|
|
1203
|
+
}
|
|
1204
|
+
const data = await this.readGlobal('federation', holonId);
|
|
1205
|
+
if (!data) return null;
|
|
1206
|
+
|
|
1207
|
+
if (!Array.isArray(data.inbound)) data.inbound = [];
|
|
1208
|
+
if (!Array.isArray(data.outbound)) data.outbound = [];
|
|
1209
|
+
if (!data.lensConfig || typeof data.lensConfig !== 'object') data.lensConfig = {};
|
|
1210
|
+
if (!data.partnerNames || typeof data.partnerNames !== 'object') data.partnerNames = {};
|
|
1211
|
+
|
|
1212
|
+
if (!Array.isArray(data.federated)) {
|
|
1213
|
+
const allFederated = new Set([...data.inbound, ...data.outbound]);
|
|
1214
|
+
data.federated = Array.from(allFederated);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
return data;
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
/**
|
|
1221
|
+
* Establishes a holon-level federation relationship.
|
|
1222
|
+
*
|
|
1223
|
+
* @param {string} sourceHolon - Source holon H3 cell ID
|
|
1224
|
+
* @param {string} targetHolon - Target holon H3 cell ID
|
|
1225
|
+
* @param {Object} [options={}] - Federation options
|
|
1226
|
+
* @param {Object} [options.lensConfig] - Lens configuration for federation
|
|
1227
|
+
* @param {string[]} [options.lensConfig.inbound] - Lenses for inbound federation
|
|
1228
|
+
* @param {string[]} [options.lensConfig.outbound] - Lenses for outbound federation
|
|
1229
|
+
* @param {string} [options.partnerName] - Human-readable name for the partner holon
|
|
1230
|
+
* @param {boolean} [options.skipPropagation=false] - Skip propagating existing data
|
|
1231
|
+
* @returns {Promise<boolean>} True if federation was established
|
|
1232
|
+
* @throws {Error} If trying to federate a holon with itself
|
|
1233
|
+
*/
|
|
1234
|
+
async federateHolon(sourceHolon, targetHolon, options = {}) {
|
|
1235
|
+
const { lensConfig = { inbound: [], outbound: [] }, partnerName = null, skipPropagation = false } = options;
|
|
1236
|
+
|
|
1237
|
+
if (sourceHolon === targetHolon) {
|
|
1238
|
+
throw new Error('Cannot federate a holon with itself');
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
let federationData = await this.readGlobal('federation', sourceHolon) || {
|
|
1242
|
+
id: sourceHolon,
|
|
1243
|
+
name: sourceHolon,
|
|
1244
|
+
federated: [],
|
|
1245
|
+
inbound: [],
|
|
1246
|
+
outbound: [],
|
|
1247
|
+
lensConfig: {},
|
|
1248
|
+
partnerNames: {},
|
|
1249
|
+
timestamp: Date.now()
|
|
1250
|
+
};
|
|
1251
|
+
|
|
1252
|
+
if (!Array.isArray(federationData.federated)) federationData.federated = [];
|
|
1253
|
+
if (!Array.isArray(federationData.inbound)) federationData.inbound = [];
|
|
1254
|
+
if (!Array.isArray(federationData.outbound)) federationData.outbound = [];
|
|
1255
|
+
if (!federationData.lensConfig || typeof federationData.lensConfig !== 'object') federationData.lensConfig = {};
|
|
1256
|
+
if (!federationData.partnerNames || typeof federationData.partnerNames !== 'object') federationData.partnerNames = {};
|
|
1257
|
+
|
|
1258
|
+
if (!federationData.federated.includes(targetHolon)) {
|
|
1259
|
+
federationData.federated.push(targetHolon);
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// Store the partner's name if provided
|
|
1263
|
+
if (partnerName) {
|
|
1264
|
+
federationData.partnerNames[targetHolon] = partnerName;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
if (lensConfig.outbound && lensConfig.outbound.length > 0) {
|
|
1268
|
+
if (!federationData.outbound.includes(targetHolon)) {
|
|
1269
|
+
federationData.outbound.push(targetHolon);
|
|
1270
|
+
}
|
|
1271
|
+
} else {
|
|
1272
|
+
federationData.outbound = federationData.outbound.filter(id => id !== targetHolon);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
if (lensConfig.inbound && lensConfig.inbound.length > 0) {
|
|
1276
|
+
if (!federationData.inbound.includes(targetHolon)) {
|
|
1277
|
+
federationData.inbound.push(targetHolon);
|
|
1278
|
+
}
|
|
1279
|
+
} else {
|
|
1280
|
+
federationData.inbound = federationData.inbound.filter(id => id !== targetHolon);
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
federationData.lensConfig[targetHolon] = {
|
|
1284
|
+
inbound: lensConfig.inbound || [],
|
|
1285
|
+
outbound: lensConfig.outbound || [],
|
|
1286
|
+
timestamp: Date.now()
|
|
1287
|
+
};
|
|
1288
|
+
|
|
1289
|
+
const success = await this.writeGlobal('federation', federationData);
|
|
1290
|
+
this.clearCache('federation');
|
|
1291
|
+
|
|
1292
|
+
// Only propagate existing data if skipPropagation is false
|
|
1293
|
+
if (success && !skipPropagation) {
|
|
1294
|
+
for (const lens of (lensConfig.inbound || [])) {
|
|
1295
|
+
await this.federate(targetHolon, sourceHolon, lens, { direction: 'outbound', mode: 'reference' });
|
|
1296
|
+
}
|
|
1297
|
+
for (const lens of (lensConfig.outbound || [])) {
|
|
1298
|
+
await this.federate(sourceHolon, targetHolon, lens, { direction: 'outbound', mode: 'reference' });
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
return success;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
/**
|
|
1306
|
+
* Removes a holon-level federation relationship.
|
|
1307
|
+
*
|
|
1308
|
+
* @param {string} sourceHolon - Source holon H3 cell ID
|
|
1309
|
+
* @param {string} targetHolon - Target holon H3 cell ID
|
|
1310
|
+
* @returns {Promise<boolean>} True if unfederation succeeded, false if no federation existed
|
|
1311
|
+
*/
|
|
1312
|
+
async unfederateHolon(sourceHolon, targetHolon) {
|
|
1313
|
+
const federationData = await this.readGlobal('federation', sourceHolon);
|
|
1314
|
+
if (!federationData) return false;
|
|
1315
|
+
|
|
1316
|
+
const lensConfig = federationData.lensConfig?.[targetHolon];
|
|
1317
|
+
|
|
1318
|
+
federationData.federated = (federationData.federated || []).filter(id => id !== targetHolon);
|
|
1319
|
+
federationData.inbound = (federationData.inbound || []).filter(id => id !== targetHolon);
|
|
1320
|
+
federationData.outbound = (federationData.outbound || []).filter(id => id !== targetHolon);
|
|
1321
|
+
|
|
1322
|
+
if (federationData.lensConfig) {
|
|
1323
|
+
delete federationData.lensConfig[targetHolon];
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
const success = await this.writeGlobal('federation', federationData);
|
|
1327
|
+
this.clearCache('federation');
|
|
1328
|
+
|
|
1329
|
+
if (success && lensConfig) {
|
|
1330
|
+
for (const lens of (lensConfig.inbound || [])) {
|
|
1331
|
+
await this.unfederate(targetHolon, sourceHolon, lens);
|
|
1332
|
+
}
|
|
1333
|
+
for (const lens of (lensConfig.outbound || [])) {
|
|
1334
|
+
await this.unfederate(sourceHolon, targetHolon, lens);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
return success;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
/**
|
|
1342
|
+
* Gets the federation configuration between two holons.
|
|
1343
|
+
*
|
|
1344
|
+
* @param {string} sourceHolon - Source holon H3 cell ID
|
|
1345
|
+
* @param {string} targetHolon - Target holon H3 cell ID
|
|
1346
|
+
* @returns {Promise<Object|null>} Lens configuration or null
|
|
1347
|
+
*/
|
|
1348
|
+
async getFederatedConfig(sourceHolon, targetHolon) {
|
|
1349
|
+
const federationData = await this.readGlobal('federation', sourceHolon);
|
|
1350
|
+
if (!federationData || !federationData.lensConfig) return null;
|
|
1351
|
+
return federationData.lensConfig[targetHolon] || null;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// === Hierarchical Operations ===
|
|
1355
|
+
|
|
1356
|
+
/**
|
|
1357
|
+
* Performs hierarchical upcast aggregation.
|
|
1358
|
+
* Aggregates data from child holons up to parent holons in the H3 hierarchy.
|
|
1359
|
+
*
|
|
1360
|
+
* @param {string} holonId - Starting holon H3 cell ID
|
|
1361
|
+
* @param {string} lensName - Name of the lens
|
|
1362
|
+
* @param {string} dataId - ID of the data to upcast
|
|
1363
|
+
* @param {Object} [options={}] - Upcast options
|
|
1364
|
+
* @returns {Promise<Object>} Aggregation result
|
|
1365
|
+
*/
|
|
1366
|
+
async upcast(holonId, lensName, dataId, options = {}) {
|
|
1367
|
+
return hierarchical.upcast(this, holonId, lensName, dataId, options);
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// === Subscriptions ===
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* Subscribes to real-time updates for a holon and lens.
|
|
1374
|
+
*
|
|
1375
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1376
|
+
* @param {string} lensName - Name of the lens
|
|
1377
|
+
* @param {Function} callback - Callback function called with updated data
|
|
1378
|
+
* @param {Object} [options={}] - Subscription options
|
|
1379
|
+
* @returns {{unsubscribe: Function}} Subscription object with unsubscribe method
|
|
1380
|
+
* @throws {TypeError} If callback is not a function
|
|
1381
|
+
*/
|
|
1382
|
+
subscribe(holonId, lensName, callback, options = {}) {
|
|
1383
|
+
if (typeof callback !== 'function') {
|
|
1384
|
+
throw new TypeError('callback must be a function');
|
|
1385
|
+
}
|
|
1386
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName);
|
|
1387
|
+
const subscriptionOptions = { realtimeOnly: true, ...options };
|
|
1388
|
+
const subscriptionId = `${holonId}-${lensName}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
1389
|
+
let innerSubscription = null;
|
|
1390
|
+
let unsubscribeCalled = false;
|
|
1391
|
+
|
|
1392
|
+
subscriptions.createSubscription(this.client, path, callback, subscriptionOptions)
|
|
1393
|
+
.then(subscription => {
|
|
1394
|
+
innerSubscription = subscription;
|
|
1395
|
+
if (unsubscribeCalled) {
|
|
1396
|
+
subscription.unsubscribe();
|
|
1397
|
+
} else {
|
|
1398
|
+
this.subscriptionRegistry.register(subscriptionId, subscription);
|
|
1399
|
+
}
|
|
1400
|
+
})
|
|
1401
|
+
.catch(err => {
|
|
1402
|
+
this._log('ERROR', 'Subscription setup failed', { path, error: err.message });
|
|
1403
|
+
});
|
|
1404
|
+
|
|
1405
|
+
this._metrics.subscriptions = (this._metrics.subscriptions || 0) + 1;
|
|
1406
|
+
return {
|
|
1407
|
+
unsubscribe: () => {
|
|
1408
|
+
unsubscribeCalled = true;
|
|
1409
|
+
if (innerSubscription) {
|
|
1410
|
+
this.subscriptionRegistry.unregister(subscriptionId);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
/**
|
|
1417
|
+
* Subscribes to real-time updates for a global table.
|
|
1418
|
+
*
|
|
1419
|
+
* @param {string} table - Name of the global table
|
|
1420
|
+
* @param {string} key - Key to subscribe to
|
|
1421
|
+
* @param {Function} callback - Callback function called with updated data
|
|
1422
|
+
* @param {Object} [options={}] - Subscription options
|
|
1423
|
+
* @returns {Promise<{unsubscribe: Function}>} Subscription object
|
|
1424
|
+
*/
|
|
1425
|
+
async subscribeGlobal(table, key, callback, options = {}) {
|
|
1426
|
+
return globalTables.subscribeGlobal(
|
|
1427
|
+
this.client,
|
|
1428
|
+
this.config.appName,
|
|
1429
|
+
table,
|
|
1430
|
+
key,
|
|
1431
|
+
callback,
|
|
1432
|
+
options
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
// === Crypto Operations ===
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* Derives a public key from a private key.
|
|
1440
|
+
*
|
|
1441
|
+
* @param {string} privateKey - Hex-encoded private key
|
|
1442
|
+
* @returns {Promise<string>} Hex-encoded public key
|
|
1443
|
+
*/
|
|
1444
|
+
async getPublicKey(privateKey) {
|
|
1445
|
+
return crypto.getPublicKey(privateKey);
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* Signs content with a private key.
|
|
1450
|
+
*
|
|
1451
|
+
* @param {string|Object} content - Content to sign
|
|
1452
|
+
* @param {string} privateKey - Hex-encoded private key
|
|
1453
|
+
* @returns {Promise<string>} Hex-encoded signature
|
|
1454
|
+
*/
|
|
1455
|
+
async sign(content, privateKey) {
|
|
1456
|
+
return crypto.sign(content, privateKey);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* Verifies a signature against content and public key.
|
|
1461
|
+
*
|
|
1462
|
+
* @param {string|Object} content - Original content
|
|
1463
|
+
* @param {string} signature - Hex-encoded signature
|
|
1464
|
+
* @param {string} publicKey - Hex-encoded public key
|
|
1465
|
+
* @returns {Promise<boolean>} True if signature is valid
|
|
1466
|
+
*/
|
|
1467
|
+
async verify(content, signature, publicKey) {
|
|
1468
|
+
return crypto.verify(content, signature, publicKey);
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
/**
|
|
1472
|
+
* Issues a capability token for authorization.
|
|
1473
|
+
*
|
|
1474
|
+
* @param {string[]} permissions - Array of permissions ('read', 'write', 'delete')
|
|
1475
|
+
* @param {Object} scope - Scope of the capability (holonId, lensName, etc.)
|
|
1476
|
+
* @param {string} recipient - Public key of the recipient
|
|
1477
|
+
* @param {Object} [options] - Additional options
|
|
1478
|
+
* @returns {Promise<string>} Signed capability token
|
|
1479
|
+
*/
|
|
1480
|
+
async issueCapability(permissions, scope, recipient, options) {
|
|
1481
|
+
return crypto.issueCapability(permissions, scope, recipient, options);
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
/**
|
|
1485
|
+
* Verifies a capability token.
|
|
1486
|
+
*
|
|
1487
|
+
* @param {string} token - Capability token to verify
|
|
1488
|
+
* @param {string} requiredPermission - Required permission to check
|
|
1489
|
+
* @param {Object} scope - Scope to verify against
|
|
1490
|
+
* @returns {Promise<boolean>} True if token is valid and has required permission
|
|
1491
|
+
*/
|
|
1492
|
+
async verifyCapability(token, requiredPermission, scope) {
|
|
1493
|
+
return crypto.verifyCapability(token, requiredPermission, scope);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
// === Social Protocol Operations ===
|
|
1497
|
+
|
|
1498
|
+
/**
|
|
1499
|
+
* Publishes a Nostr event to a holon.
|
|
1500
|
+
*
|
|
1501
|
+
* @param {Object} event - Nostr event object
|
|
1502
|
+
* @param {number} event.kind - Event kind
|
|
1503
|
+
* @param {string} event.content - Event content
|
|
1504
|
+
* @param {Array} [event.tags] - Event tags
|
|
1505
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1506
|
+
* @param {string} [lensName='social'] - Name of the lens
|
|
1507
|
+
* @returns {Promise<boolean>} True if publish succeeded
|
|
1508
|
+
*/
|
|
1509
|
+
async publishNostr(event, holonId, lensName = 'social') {
|
|
1510
|
+
// Validate Nostr event format
|
|
1511
|
+
social.validateNostrEvent(event, true, true); // partial=true, throwOnError=true
|
|
1512
|
+
|
|
1513
|
+
const enrichedEvent = {
|
|
1514
|
+
...event,
|
|
1515
|
+
tags: [...(event.tags || []), ['h', holonId], ['l', lensName]],
|
|
1516
|
+
};
|
|
1517
|
+
const signedEvent = nostrUtils.signEvent(enrichedEvent, this.client.privateKey);
|
|
1518
|
+
|
|
1519
|
+
// Add protocol field for querySocial filtering
|
|
1520
|
+
const eventWithProtocol = {
|
|
1521
|
+
...signedEvent,
|
|
1522
|
+
protocol: 'nostr',
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
const path = storage.buildPath(this.config.appName, holonId, lensName, signedEvent.id);
|
|
1526
|
+
await storage.write(this.client, path, eventWithProtocol);
|
|
1527
|
+
return true;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/**
|
|
1531
|
+
* Publishes an ActivityPub object to a holon.
|
|
1532
|
+
*
|
|
1533
|
+
* @param {Object} object - ActivityPub object
|
|
1534
|
+
* @param {string} object.type - ActivityPub type (Note, Article, etc.)
|
|
1535
|
+
* @param {string} [object.actor] - Actor ID (defaults to client public key)
|
|
1536
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1537
|
+
* @param {string} [lensName='social'] - Name of the lens
|
|
1538
|
+
* @returns {Promise<boolean>} True if publish succeeded
|
|
1539
|
+
*/
|
|
1540
|
+
async publishActivityPub(object, holonId, lensName = 'social') {
|
|
1541
|
+
// Validate ActivityPub object format
|
|
1542
|
+
social.validateActivityPubObject(object, true); // throwOnError=true
|
|
1543
|
+
|
|
1544
|
+
const activity = social.transformActivityPubObject({
|
|
1545
|
+
...object,
|
|
1546
|
+
actor: object.actor || this.client.publicKey,
|
|
1547
|
+
});
|
|
1548
|
+
return this.write(holonId, lensName, activity);
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
/**
|
|
1552
|
+
* Queries social protocol data from a holon.
|
|
1553
|
+
*
|
|
1554
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1555
|
+
* @param {Object} [options={}] - Query options
|
|
1556
|
+
* @param {string} [options.lens='social'] - Name of the lens
|
|
1557
|
+
* @param {string} [options.protocol] - Filter by protocol ('nostr', 'activitypub', 'all')
|
|
1558
|
+
* @param {string} [options.type] - Filter by content type
|
|
1559
|
+
* @param {number} [options.since] - Filter events after this timestamp
|
|
1560
|
+
* @param {number} [options.until] - Filter events before this timestamp
|
|
1561
|
+
* @returns {Promise<Array>} Array of matching social items
|
|
1562
|
+
*/
|
|
1563
|
+
async querySocial(holonId, options = {}) {
|
|
1564
|
+
const lensName = options.lens || 'social';
|
|
1565
|
+
const data = await this.read(holonId, lensName);
|
|
1566
|
+
|
|
1567
|
+
if (!data) return [];
|
|
1568
|
+
const items = Array.isArray(data) ? data : [data];
|
|
1569
|
+
|
|
1570
|
+
return items.filter(item => {
|
|
1571
|
+
// 'all' means don't filter by protocol
|
|
1572
|
+
if (options.protocol && options.protocol !== 'all' && item.protocol !== options.protocol) return false;
|
|
1573
|
+
if (options.type && item.type !== options.type) return false;
|
|
1574
|
+
if (options.since && item.created_at < options.since) return false;
|
|
1575
|
+
if (options.until && item.created_at > options.until) return false;
|
|
1576
|
+
return true;
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/**
|
|
1581
|
+
* Verifies a Nostr event signature.
|
|
1582
|
+
*
|
|
1583
|
+
* @param {Object} event - Nostr event to verify
|
|
1584
|
+
* @param {string} event.id - Event ID
|
|
1585
|
+
* @param {string} event.pubkey - Author public key
|
|
1586
|
+
* @param {number} event.created_at - Creation timestamp
|
|
1587
|
+
* @param {number} event.kind - Event kind
|
|
1588
|
+
* @param {Array} event.tags - Event tags
|
|
1589
|
+
* @param {string} event.content - Event content
|
|
1590
|
+
* @param {string} event.sig - Event signature
|
|
1591
|
+
* @returns {Promise<boolean>} True if event signature is valid
|
|
1592
|
+
*/
|
|
1593
|
+
async verifyNostrEvent(event) {
|
|
1594
|
+
// Extract only standard Nostr event fields for verification
|
|
1595
|
+
// (nostr-tools can't serialize events with extra properties like 'protocol')
|
|
1596
|
+
const { id, pubkey, created_at, kind, tags, content, sig } = event;
|
|
1597
|
+
const standardEvent = { id, pubkey, created_at, kind, tags, content, sig };
|
|
1598
|
+
return nostrUtils.verifyEvent(standardEvent);
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
// === Metrics ===
|
|
1602
|
+
|
|
1603
|
+
/**
|
|
1604
|
+
* Gets performance metrics for this HoloSphere instance.
|
|
1605
|
+
*
|
|
1606
|
+
* @returns {Object} Metrics object
|
|
1607
|
+
* @returns {number} return.reads - Number of read operations
|
|
1608
|
+
* @returns {number} return.writes - Number of write operations
|
|
1609
|
+
* @returns {number} return.deletes - Number of delete operations
|
|
1610
|
+
* @returns {number} return.federations - Number of federation operations
|
|
1611
|
+
* @returns {number} return.subscriptions - Number of active subscriptions
|
|
1612
|
+
* @returns {number} return.avgReadTime - Average read time in milliseconds
|
|
1613
|
+
* @returns {number} return.avgWriteTime - Average write time in milliseconds
|
|
1614
|
+
*/
|
|
1615
|
+
metrics() {
|
|
1616
|
+
const reads = this._metrics.reads || 0;
|
|
1617
|
+
const writes = this._metrics.writes || 0;
|
|
1618
|
+
const totalReadTime = this._metrics.totalReadTime || 0;
|
|
1619
|
+
const totalWriteTime = this._metrics.totalWriteTime || 0;
|
|
1620
|
+
|
|
1621
|
+
return {
|
|
1622
|
+
reads,
|
|
1623
|
+
writes,
|
|
1624
|
+
deletes: this._metrics.deletes || 0,
|
|
1625
|
+
federations: this._metrics.federations || 0,
|
|
1626
|
+
subscriptions: this._metrics.subscriptions || 0,
|
|
1627
|
+
avgReadTime: reads > 0 ? totalReadTime / reads : 0,
|
|
1628
|
+
avgWriteTime: writes > 0 ? totalWriteTime / writes : 0,
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
// === Aliases ===
|
|
1633
|
+
|
|
1634
|
+
/**
|
|
1635
|
+
* Alias for {@link HoloSphereBase#write}.
|
|
1636
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1637
|
+
* @param {string} lensName - Name of the lens
|
|
1638
|
+
* @param {Object} data - Data to write
|
|
1639
|
+
* @param {Object} [options] - Write options
|
|
1640
|
+
* @returns {Promise<boolean>}
|
|
1641
|
+
*/
|
|
1642
|
+
async put(holonId, lensName, data, options = {}) {
|
|
1643
|
+
return this.write(holonId, lensName, data, options);
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
/**
|
|
1647
|
+
* Alias for {@link HoloSphereBase#read}.
|
|
1648
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1649
|
+
* @param {string} lensName - Name of the lens
|
|
1650
|
+
* @param {string|null} [dataId] - Specific data ID or null
|
|
1651
|
+
* @param {Object} [options] - Read options
|
|
1652
|
+
* @returns {Promise<Object|Array|null>}
|
|
1653
|
+
*/
|
|
1654
|
+
async get(holonId, lensName, dataId = null, options = {}) {
|
|
1655
|
+
return this.read(holonId, lensName, dataId, options);
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
/**
|
|
1659
|
+
* Alias for {@link HoloSphereBase#delete}.
|
|
1660
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1661
|
+
* @param {string} lensName - Name of the lens
|
|
1662
|
+
* @param {string} dataId - Data ID to delete
|
|
1663
|
+
* @param {Object} [options] - Delete options
|
|
1664
|
+
* @returns {Promise<boolean>}
|
|
1665
|
+
*/
|
|
1666
|
+
async remove(holonId, lensName, dataId, options = {}) {
|
|
1667
|
+
return this.delete(holonId, lensName, dataId, options);
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
/**
|
|
1671
|
+
* Alias for {@link HoloSphereBase#writeGlobal}.
|
|
1672
|
+
* @param {string} table - Global table name
|
|
1673
|
+
* @param {Object} data - Data to write
|
|
1674
|
+
* @returns {Promise<boolean>}
|
|
1675
|
+
*/
|
|
1676
|
+
async putGlobal(table, data) {
|
|
1677
|
+
return this.writeGlobal(table, data);
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
/**
|
|
1681
|
+
* Alias for {@link HoloSphereBase#readGlobal}.
|
|
1682
|
+
* @param {string} table - Global table name
|
|
1683
|
+
* @param {string|null} [key] - Key to read
|
|
1684
|
+
* @returns {Promise<Object|Array|null>}
|
|
1685
|
+
*/
|
|
1686
|
+
async getGlobal(table, key = null) {
|
|
1687
|
+
return this.readGlobal(table, key);
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* Alias for {@link HoloSphereBase#deleteGlobal}.
|
|
1692
|
+
* @param {string} table - Global table name
|
|
1693
|
+
* @param {string} key - Key to delete
|
|
1694
|
+
* @returns {Promise<boolean>}
|
|
1695
|
+
*/
|
|
1696
|
+
async removeGlobal(table, key) {
|
|
1697
|
+
return this.deleteGlobal(table, key);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
/**
|
|
1701
|
+
* Alias for {@link HoloSphereBase#setSchema}.
|
|
1702
|
+
* @param {string} lensName - Lens name
|
|
1703
|
+
* @param {Object|string} schemaObj - Schema object or URI
|
|
1704
|
+
* @param {boolean} [strict] - Strict mode
|
|
1705
|
+
* @returns {Promise<void>}
|
|
1706
|
+
*/
|
|
1707
|
+
async defineSchema(lensName, schemaObj, strict = false) {
|
|
1708
|
+
return this.setSchema(lensName, schemaObj, strict);
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
/**
|
|
1712
|
+
* Alias for {@link HoloSphereBase#getSchema}.
|
|
1713
|
+
* @param {string} lensName - Lens name
|
|
1714
|
+
* @returns {Promise<Object|null>}
|
|
1715
|
+
*/
|
|
1716
|
+
async fetchSchema(lensName) {
|
|
1717
|
+
return this.getSchema(lensName);
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
/**
|
|
1721
|
+
* Alias for {@link HoloSphereBase#clearSchema}.
|
|
1722
|
+
* @param {string} lensName - Lens name
|
|
1723
|
+
* @returns {Promise<void>}
|
|
1724
|
+
*/
|
|
1725
|
+
async removeSchema(lensName) {
|
|
1726
|
+
return this.clearSchema(lensName);
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
/**
|
|
1730
|
+
* Alias for {@link HoloSphereBase#write}.
|
|
1731
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1732
|
+
* @param {string} lensName - Name of the lens
|
|
1733
|
+
* @param {Object} data - Data to write
|
|
1734
|
+
* @param {Object} [options] - Write options
|
|
1735
|
+
* @returns {Promise<boolean>}
|
|
1736
|
+
*/
|
|
1737
|
+
async store(holonId, lensName, data, options = {}) {
|
|
1738
|
+
return this.write(holonId, lensName, data, options);
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
/**
|
|
1742
|
+
* Alias for {@link HoloSphereBase#read}.
|
|
1743
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1744
|
+
* @param {string} lensName - Name of the lens
|
|
1745
|
+
* @param {string|null} [dataId] - Specific data ID or null
|
|
1746
|
+
* @param {Object} [options] - Read options
|
|
1747
|
+
* @returns {Promise<Object|Array|null>}
|
|
1748
|
+
*/
|
|
1749
|
+
async fetch(holonId, lensName, dataId = null, options = {}) {
|
|
1750
|
+
return this.read(holonId, lensName, dataId, options);
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
/**
|
|
1754
|
+
* Alias for {@link HoloSphereBase#write}.
|
|
1755
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1756
|
+
* @param {string} lensName - Name of the lens
|
|
1757
|
+
* @param {Object} data - Data to write
|
|
1758
|
+
* @param {Object} [options] - Write options
|
|
1759
|
+
* @returns {Promise<boolean>}
|
|
1760
|
+
*/
|
|
1761
|
+
async save(holonId, lensName, data, options = {}) {
|
|
1762
|
+
return this.write(holonId, lensName, data, options);
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
/**
|
|
1766
|
+
* Alias for {@link HoloSphereBase#read}.
|
|
1767
|
+
* @param {string} holonId - H3 cell ID for the holon
|
|
1768
|
+
* @param {string} lensName - Name of the lens
|
|
1769
|
+
* @param {string|null} [dataId] - Specific data ID or null
|
|
1770
|
+
* @param {Object} [options] - Read options
|
|
1771
|
+
* @returns {Promise<Object|Array|null>}
|
|
1772
|
+
*/
|
|
1773
|
+
async load(holonId, lensName, dataId = null, options = {}) {
|
|
1774
|
+
return this.read(holonId, lensName, dataId, options);
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
// === Cache ===
|
|
1778
|
+
|
|
1779
|
+
/**
|
|
1780
|
+
* Clears the internal cache.
|
|
1781
|
+
*
|
|
1782
|
+
* @param {string|null} [pattern=null] - If provided, only clear cache entries matching this pattern
|
|
1783
|
+
*/
|
|
1784
|
+
clearCache(pattern = null) {
|
|
1785
|
+
if (pattern) {
|
|
1786
|
+
for (const key of this._cache.keys()) {
|
|
1787
|
+
if (key.includes(pattern)) {
|
|
1788
|
+
this._cache.delete(key);
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
} else {
|
|
1792
|
+
this._cache.clear();
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
/**
|
|
1798
|
+
* Main HoloSphere class - composed from base + all mixins
|
|
1799
|
+
*/
|
|
1800
|
+
export const HoloSphere = withContractMethods(
|
|
1801
|
+
withFederationMethods(
|
|
1802
|
+
withAIMethods(HoloSphereBase)
|
|
1803
|
+
)
|
|
1804
|
+
);
|
|
1805
|
+
|
|
1806
|
+
// Export error classes
|
|
1807
|
+
export { AuthorizationError };
|
|
1808
|
+
export { ValidationError };
|
|
1809
|
+
|
|
1810
|
+
// Re-export AI module classes
|
|
1811
|
+
export {
|
|
1812
|
+
LLMService,
|
|
1813
|
+
SchemaExtractor,
|
|
1814
|
+
JSONOps,
|
|
1815
|
+
Embeddings,
|
|
1816
|
+
Council,
|
|
1817
|
+
TTS,
|
|
1818
|
+
VOICES,
|
|
1819
|
+
MODELS,
|
|
1820
|
+
NLQuery,
|
|
1821
|
+
Classifier,
|
|
1822
|
+
SpatialAnalysis,
|
|
1823
|
+
SmartAggregation,
|
|
1824
|
+
FederationAdvisor,
|
|
1825
|
+
RelationshipDiscovery,
|
|
1826
|
+
TaskBreakdown,
|
|
1827
|
+
H3AI,
|
|
1828
|
+
};
|
|
1829
|
+
|
|
1830
|
+
// Re-export types and utilities
|
|
1831
|
+
export { spatial, storage, schema, federation, handshake, crypto, nostrUtils, social, subscriptions, hierarchical };
|
|
1832
|
+
|
|
1833
|
+
// Re-export specific utilities used in tests
|
|
1834
|
+
export { matchScope } from './crypto/secp256k1.js';
|
|
1835
|
+
export { createHologram } from './federation/hologram.js';
|
|
1836
|
+
|
|
1837
|
+
// Export AI factory function
|
|
1838
|
+
export { createAIServices } from './ai/index.js';
|
|
1839
|
+
|
|
1840
|
+
// Export Contracts module classes for standalone use
|
|
1841
|
+
export {
|
|
1842
|
+
ChainManager,
|
|
1843
|
+
ContractDeployer,
|
|
1844
|
+
HolonContracts,
|
|
1845
|
+
ContractOperations,
|
|
1846
|
+
ContractABIs,
|
|
1847
|
+
EventListener,
|
|
1848
|
+
ContractQueries,
|
|
1849
|
+
SANKEY_EVENTS
|
|
1850
|
+
};
|
|
1851
|
+
|
|
1852
|
+
// Export network utilities
|
|
1853
|
+
export {
|
|
1854
|
+
NETWORKS,
|
|
1855
|
+
getNetwork,
|
|
1856
|
+
getNetworksByType,
|
|
1857
|
+
listNetworks,
|
|
1858
|
+
isNetworkSupported,
|
|
1859
|
+
getTxUrl,
|
|
1860
|
+
getAddressUrl
|
|
1861
|
+
} from './contracts/networks.js';
|
|
1862
|
+
|
|
1863
|
+
// Export contracts namespace
|
|
1864
|
+
export { networks };
|
|
1865
|
+
|
|
1866
|
+
// Default export for backward compatibility
|
|
1867
|
+
export default HoloSphere;
|
|
1868
|
+
</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>
|