holosphere 2.0.0-alpha8 → 2.0.0-alpha9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +446 -0
- package/FEATURES.md +431 -0
- package/LICENSE +29 -166
- package/LICENSE-AGPL.md +180 -0
- package/dist/cdn/holosphere.min.js +55 -0
- package/dist/cdn/holosphere.min.js.map +1 -0
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +1 -1
- package/dist/{index-CKffQDmQ.cjs → index-DDGt_V9o.cjs} +2 -2
- package/dist/{index-CKffQDmQ.cjs.map → index-DDGt_V9o.cjs.map} +1 -1
- package/dist/{index-4XHHKe6S.js → index-DJXftyvB.js} +1905 -337
- package/dist/index-DJXftyvB.js.map +1 -0
- package/dist/{index-Dz5kOZMI.cjs → index-DMbdcMtK.cjs} +17 -4
- package/dist/index-DMbdcMtK.cjs.map +1 -0
- package/dist/{index-BjP1TXGz.js → index-DeZ1xz_s.js} +2 -2
- package/dist/{index-BjP1TXGz.js.map → index-DeZ1xz_s.js.map} +1 -1
- package/dist/{indexeddb-storage-lExjjFlV.js → indexeddb-storage-BFt6hMeF.js} +48 -4
- package/dist/indexeddb-storage-BFt6hMeF.js.map +1 -0
- package/dist/{indexeddb-storage-DD7EFBVc.cjs → indexeddb-storage-BK5tv4Sh.cjs} +2 -2
- package/dist/indexeddb-storage-BK5tv4Sh.cjs.map +1 -0
- package/dist/{memory-storage-C68adso2.js → memory-storage-C9HuoL2E.js} +44 -4
- package/dist/memory-storage-C9HuoL2E.js.map +1 -0
- package/dist/{memory-storage-DD_6yyXT.cjs → memory-storage-Dao7jfYG.cjs} +2 -2
- package/dist/memory-storage-Dao7jfYG.cjs.map +1 -0
- package/dist/{secp256k1-DYELiqgx.cjs → secp256k1-BbKzbLtD.cjs} +2 -2
- package/dist/{secp256k1-DYELiqgx.cjs.map → secp256k1-BbKzbLtD.cjs.map} +1 -1
- package/dist/{secp256k1-OM8siPyy.js → secp256k1-CreY7Pcl.js} +2 -2
- package/dist/{secp256k1-OM8siPyy.js.map → secp256k1-CreY7Pcl.js.map} +1 -1
- package/docs/api/ai_aggregation.js.html +333 -0
- package/docs/api/ai_breakdown.js.html +524 -0
- package/docs/api/ai_classifier.js.html +231 -0
- package/docs/api/ai_council.js.html +246 -0
- package/docs/api/ai_embeddings.js.html +304 -0
- package/docs/api/ai_federation-ai.js.html +338 -0
- package/docs/api/ai_h3-ai.js.html +970 -0
- package/docs/api/ai_index.js.html +124 -0
- package/docs/api/ai_json-ops.js.html +241 -0
- package/docs/api/ai_llm-service.js.html +239 -0
- package/docs/api/ai_nl-query.js.html +236 -0
- package/docs/api/ai_relationships.js.html +367 -0
- package/docs/api/ai_schema-extractor.js.html +235 -0
- package/docs/api/ai_spatial.js.html +307 -0
- package/docs/api/ai_tts.js.html +214 -0
- package/docs/api/content_social-protocols.js.html +180 -0
- package/docs/api/core_holosphere.js.html +757 -0
- package/docs/api/crypto_nostr-utils.js.html +306 -0
- package/docs/api/crypto_secp256k1.js.html +267 -0
- package/docs/api/data/search.json +1 -0
- package/docs/api/federation_discovery.js.html +337 -0
- package/docs/api/federation_handshake.js.html +478 -0
- package/docs/api/federation_hologram.js.html +1053 -0
- package/docs/api/federation_registry.js.html +389 -0
- package/docs/api/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/api/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/api/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/api/global.html +3 -0
- package/docs/api/hierarchical_upcast.js.html +128 -0
- package/docs/api/index.html +265 -0
- package/docs/api/index.js.html +1868 -0
- package/docs/api/lib_ai-methods.js.html +660 -0
- package/docs/api/lib_contract-methods.js.html +445 -0
- package/docs/api/lib_errors.js.html +56 -0
- package/docs/api/lib_federation-methods.js.html +348 -0
- package/docs/api/lib_index.js.html +33 -0
- package/docs/api/module-ai.html +5 -0
- package/docs/api/module-ai_aggregation-SmartAggregation.html +6 -0
- package/docs/api/module-ai_aggregation.SmartAggregation.html +3 -0
- package/docs/api/module-ai_aggregation.html +3 -0
- package/docs/api/module-ai_breakdown-TaskBreakdown.html +5 -0
- package/docs/api/module-ai_breakdown.TaskBreakdown.html +3 -0
- package/docs/api/module-ai_breakdown.html +3 -0
- package/docs/api/module-ai_classifier-Classifier.html +6 -0
- package/docs/api/module-ai_classifier.Classifier.html +3 -0
- package/docs/api/module-ai_classifier.html +3 -0
- package/docs/api/module-ai_council-Council.html +6 -0
- package/docs/api/module-ai_council.Council.html +3 -0
- package/docs/api/module-ai_council.html +3 -0
- package/docs/api/module-ai_embeddings-Embeddings.html +5 -0
- package/docs/api/module-ai_embeddings.Embeddings.html +3 -0
- package/docs/api/module-ai_embeddings.html +3 -0
- package/docs/api/module-ai_federation-ai-FederationAdvisor.html +6 -0
- package/docs/api/module-ai_federation-ai.FederationAdvisor.html +3 -0
- package/docs/api/module-ai_federation-ai.html +3 -0
- package/docs/api/module-ai_h3-ai-H3AI.html +6 -0
- package/docs/api/module-ai_h3-ai.H3AI.html +3 -0
- package/docs/api/module-ai_h3-ai.html +3 -0
- package/docs/api/module-ai_json-ops-JSONOps.html +5 -0
- package/docs/api/module-ai_json-ops.JSONOps.html +3 -0
- package/docs/api/module-ai_json-ops.html +3 -0
- package/docs/api/module-ai_llm-service-LLMService.html +5 -0
- package/docs/api/module-ai_llm-service.LLMService.html +3 -0
- package/docs/api/module-ai_llm-service.html +3 -0
- package/docs/api/module-ai_nl-query-NLQuery.html +5 -0
- package/docs/api/module-ai_nl-query.NLQuery.html +3 -0
- package/docs/api/module-ai_nl-query.html +3 -0
- package/docs/api/module-ai_relationships-RelationshipDiscovery.html +6 -0
- package/docs/api/module-ai_relationships.RelationshipDiscovery.html +3 -0
- package/docs/api/module-ai_relationships.html +3 -0
- package/docs/api/module-ai_schema-extractor-SchemaExtractor.html +5 -0
- package/docs/api/module-ai_schema-extractor.SchemaExtractor.html +3 -0
- package/docs/api/module-ai_schema-extractor.html +3 -0
- package/docs/api/module-ai_spatial-SpatialAnalysis.html +6 -0
- package/docs/api/module-ai_spatial.SpatialAnalysis.html +3 -0
- package/docs/api/module-ai_spatial.html +3 -0
- package/docs/api/module-ai_tts-TTS.html +5 -0
- package/docs/api/module-ai_tts.TTS.html +3 -0
- package/docs/api/module-ai_tts.html +3 -0
- package/docs/api/module-content_social-protocols.html +3 -0
- package/docs/api/module-core_holosphere-HoloSphere.html +6 -0
- package/docs/api/module-core_holosphere.HoloSphere.html +3 -0
- package/docs/api/module-core_holosphere.html +3 -0
- package/docs/api/module-crypto_nostr-utils.html +3 -0
- package/docs/api/module-crypto_secp256k1.html +3 -0
- package/docs/api/module-federation_hologram.html +3 -0
- package/docs/api/module-hierarchical_upcast.html +3 -0
- package/docs/api/module-holosphere-HoloSphereBase.html +3 -0
- package/docs/api/module-holosphere.html +3 -0
- package/docs/api/module-lib_ai-methods.html +3 -0
- package/docs/api/module-lib_contract-methods.html +3 -0
- package/docs/api/module-lib_errors-AuthorizationError.html +3 -0
- package/docs/api/module-lib_errors-ValidationError.html +3 -0
- package/docs/api/module-lib_errors.AuthorizationError.html +3 -0
- package/docs/api/module-lib_errors.ValidationError.html +3 -0
- package/docs/api/module-lib_errors.html +3 -0
- package/docs/api/module-lib_federation-methods.html +3 -0
- package/docs/api/module-lib_index.html +3 -0
- package/docs/api/module-schema_validator-ValidationError.html +3 -0
- package/docs/api/module-schema_validator.ValidationError.html +3 -0
- package/docs/api/module-schema_validator.html +3 -0
- package/docs/api/module-spatial_h3-operations.html +4 -0
- package/docs/api/module-storage_backend-factory.BackendFactory.html +3 -0
- package/docs/api/module-storage_backend-factory.html +3 -0
- package/docs/api/module-storage_backend-interface-StorageBackend.html +3 -0
- package/docs/api/module-storage_backend-interface.StorageBackend.html +3 -0
- package/docs/api/module-storage_backend-interface.html +3 -0
- package/docs/api/module-storage_backends_activitypub-backend-ActivityPubBackend.html +7 -0
- package/docs/api/module-storage_backends_activitypub-backend.ActivityPubBackend.html +3 -0
- package/docs/api/module-storage_backends_activitypub-backend.html +3 -0
- package/docs/api/module-storage_backends_activitypub_server-ActivityPubServer.html +8 -0
- package/docs/api/module-storage_backends_activitypub_server.ActivityPubServer.html +3 -0
- package/docs/api/module-storage_backends_activitypub_server.html +3 -0
- package/docs/api/module-storage_backends_gundb-backend-GunDBBackend.html +7 -0
- package/docs/api/module-storage_backends_gundb-backend.GunDBBackend.html +3 -0
- package/docs/api/module-storage_backends_gundb-backend.html +3 -0
- package/docs/api/module-storage_backends_nostr-backend-NostrBackend.html +8 -0
- package/docs/api/module-storage_backends_nostr-backend.NostrBackend.html +3 -0
- package/docs/api/module-storage_backends_nostr-backend.html +3 -0
- package/docs/api/module-storage_filesystem-storage-FileSystemStorage.html +5 -0
- package/docs/api/module-storage_filesystem-storage-browser-FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage-browser.FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage-browser.html +3 -0
- package/docs/api/module-storage_filesystem-storage.FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage.html +3 -0
- package/docs/api/module-storage_global-tables.html +3 -0
- package/docs/api/module-storage_gun-async.html +3 -0
- package/docs/api/module-storage_gun-auth-GunAuth.html +5 -0
- package/docs/api/module-storage_gun-auth.GunAuth.html +3 -0
- package/docs/api/module-storage_gun-auth.html +3 -0
- package/docs/api/module-storage_gun-federation.html +3 -0
- package/docs/api/module-storage_gun-references-GunReferenceHandler.html +5 -0
- package/docs/api/module-storage_gun-references.GunReferenceHandler.html +3 -0
- package/docs/api/module-storage_gun-references.html +3 -0
- package/docs/api/module-storage_gun-schema-GunSchemaValidator.html +5 -0
- package/docs/api/module-storage_gun-schema.GunSchemaValidator.html +3 -0
- package/docs/api/module-storage_gun-schema.html +3 -0
- package/docs/api/module-storage_gun-wrapper.html +11 -0
- package/docs/api/module-storage_indexeddb-storage-IndexedDBStorage.html +5 -0
- package/docs/api/module-storage_indexeddb-storage.IndexedDBStorage.html +3 -0
- package/docs/api/module-storage_indexeddb-storage.html +3 -0
- package/docs/api/module-storage_key-storage-simple.html +3 -0
- package/docs/api/module-storage_key-storage.html +4 -0
- package/docs/api/module-storage_memory-storage-MemoryStorage.html +5 -0
- package/docs/api/module-storage_memory-storage.MemoryStorage.html +3 -0
- package/docs/api/module-storage_memory-storage.html +3 -0
- package/docs/api/module-storage_migration-MigrationTool.html +6 -0
- package/docs/api/module-storage_migration.MigrationTool.html +3 -0
- package/docs/api/module-storage_migration.html +3 -0
- package/docs/api/module-storage_nostr-async.html +18 -0
- package/docs/api/module-storage_nostr-client-LRUCache.html +3 -0
- package/docs/api/module-storage_nostr-client-NostrClient.html +7 -0
- package/docs/api/module-storage_nostr-client.NostrClient.html +15 -0
- package/docs/api/module-storage_nostr-client.html +6 -0
- package/docs/api/module-storage_nostr-wrapper.html +3 -0
- package/docs/api/module-storage_outbox-queue-OutboxQueue.html +4 -0
- package/docs/api/module-storage_outbox-queue.OutboxQueue.html +3 -0
- package/docs/api/module-storage_outbox-queue.html +3 -0
- package/docs/api/module-storage_persistent-storage-PersistentStorage.html +3 -0
- package/docs/api/module-storage_persistent-storage.html +4 -0
- package/docs/api/module-storage_sync-service-SyncService.html +5 -0
- package/docs/api/module-storage_sync-service.SyncService.html +3 -0
- package/docs/api/module-storage_sync-service.html +3 -0
- package/docs/api/module-storage_unified-storage.html +3 -0
- package/docs/api/module-subscriptions_manager.SubscriptionRegistry.html +3 -0
- package/docs/api/module-subscriptions_manager.html +3 -0
- package/docs/api/schema_validator.js.html +113 -0
- package/docs/api/scripts/core.js +726 -0
- package/docs/api/scripts/core.min.js +23 -0
- package/docs/api/scripts/resize.js +90 -0
- package/docs/api/scripts/search.js +265 -0
- package/docs/api/scripts/search.min.js +6 -0
- package/docs/api/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/api/scripts/third-party/fuse.js +9 -0
- package/docs/api/scripts/third-party/hljs-line-num-original.js +369 -0
- package/docs/api/scripts/third-party/hljs-line-num.js +1 -0
- package/docs/api/scripts/third-party/hljs-original.js +5171 -0
- package/docs/api/scripts/third-party/hljs.js +1 -0
- package/docs/api/scripts/third-party/popper.js +5 -0
- package/docs/api/scripts/third-party/tippy.js +1 -0
- package/docs/api/scripts/third-party/tocbot.js +672 -0
- package/docs/api/scripts/third-party/tocbot.min.js +1 -0
- package/docs/api/spatial_h3-operations.js.html +129 -0
- package/docs/api/storage_backend-factory.js.html +133 -0
- package/docs/api/storage_backend-interface.js.html +164 -0
- package/docs/api/storage_backends_activitypub-backend.js.html +298 -0
- package/docs/api/storage_backends_activitypub_server.js.html +678 -0
- package/docs/api/storage_backends_gundb-backend.js.html +878 -0
- package/docs/api/storage_backends_nostr-backend.js.html +254 -0
- package/docs/api/storage_filesystem-storage-browser.js.html +83 -0
- package/docs/api/storage_filesystem-storage.js.html +207 -0
- package/docs/api/storage_global-tables.js.html +116 -0
- package/docs/api/storage_gun-async.js.html +344 -0
- package/docs/api/storage_gun-auth.js.html +376 -0
- package/docs/api/storage_gun-federation.js.html +788 -0
- package/docs/api/storage_gun-references.js.html +212 -0
- package/docs/api/storage_gun-schema.js.html +309 -0
- package/docs/api/storage_gun-wrapper.js.html +645 -0
- package/docs/api/storage_indexeddb-storage.js.html +224 -0
- package/docs/api/storage_key-storage-simple.js.html +102 -0
- package/docs/api/storage_key-storage.js.html +171 -0
- package/docs/api/storage_memory-storage.js.html +128 -0
- package/docs/api/storage_migration.js.html +354 -0
- package/docs/api/storage_nostr-async.js.html +1076 -0
- package/docs/api/storage_nostr-client.js.html +1598 -0
- package/docs/api/storage_nostr-wrapper.js.html +218 -0
- package/docs/api/storage_outbox-queue.js.html +248 -0
- package/docs/api/storage_persistent-storage.js.html +160 -0
- package/docs/api/storage_sync-service.js.html +201 -0
- package/docs/api/storage_unified-storage.js.html +157 -0
- package/docs/api/styles/clean-jsdoc-theme-base.css +1159 -0
- package/docs/api/styles/clean-jsdoc-theme-dark.css +412 -0
- package/docs/api/styles/clean-jsdoc-theme-light.css +482 -0
- package/docs/api/styles/clean-jsdoc-theme-scrollbar.css +30 -0
- package/docs/api/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
- package/docs/api/styles/clean-jsdoc-theme.min.css +1 -0
- package/docs/api/subscriptions_manager.js.html +162 -0
- package/jsdoc.json +26 -0
- package/package.json +14 -3
- package/src/ai/aggregation.js +13 -2
- package/src/ai/breakdown.js +12 -2
- package/src/ai/classifier.js +14 -3
- package/src/ai/council.js +22 -7
- package/src/ai/embeddings.js +37 -15
- package/src/ai/federation-ai.js +13 -2
- package/src/ai/h3-ai.js +14 -2
- package/src/ai/index.js +16 -7
- package/src/ai/json-ops.js +18 -5
- package/src/ai/llm-service.js +62 -31
- package/src/ai/nl-query.js +12 -2
- package/src/ai/relationships.js +13 -2
- package/src/ai/schema-extractor.js +24 -10
- package/src/ai/spatial.js +13 -2
- package/src/ai/tts.js +25 -8
- package/src/content/social-protocols.js +34 -25
- package/src/contracts/chain-manager.js +68 -40
- package/src/contracts/deployer.js +70 -42
- package/src/contracts/event-listener.js +61 -29
- package/src/contracts/holon-contracts.js +46 -31
- package/src/contracts/index.js +5 -6
- package/src/contracts/networks.js +19 -14
- package/src/contracts/operations.js +58 -41
- package/src/contracts/queries.js +54 -20
- package/src/core/holosphere.js +35 -6
- package/src/crypto/nostr-utils.js +82 -76
- package/src/crypto/secp256k1.js +7 -2
- package/src/federation/handshake.js +7 -7
- package/src/federation/hologram.js +9 -1
- package/src/hierarchical/upcast.js +34 -20
- package/src/index.js +655 -5
- package/src/lib/ai-methods.js +352 -3
- package/src/lib/contract-methods.js +152 -3
- package/src/lib/errors.js +31 -1
- package/src/lib/federation-methods.js +110 -3
- package/src/lib/index.js +9 -5
- package/src/schema/validator.js +22 -3
- package/src/spatial/h3-operations.js +17 -1
- package/src/storage/backend-factory.js +7 -2
- package/src/storage/backend-interface.js +21 -2
- package/src/storage/backends/activitypub/server.js +25 -3
- package/src/storage/backends/activitypub-backend.js +25 -2
- package/src/storage/backends/gundb-backend.js +29 -2
- package/src/storage/backends/nostr-backend.js +116 -1
- package/src/storage/filesystem-storage-browser.js +42 -2
- package/src/storage/filesystem-storage.js +72 -5
- package/src/storage/global-tables.js +7 -2
- package/src/storage/gun-async.js +20 -11
- package/src/storage/gun-auth.js +15 -4
- package/src/storage/gun-federation.js +14 -5
- package/src/storage/gun-references.js +16 -5
- package/src/storage/gun-schema.js +25 -10
- package/src/storage/gun-wrapper.js +99 -36
- package/src/storage/indexeddb-storage.js +65 -4
- package/src/storage/key-storage-simple.js +32 -9
- package/src/storage/key-storage.js +45 -13
- package/src/storage/memory-storage.js +65 -4
- package/src/storage/migration.js +20 -7
- package/src/storage/nostr-async.js +157 -67
- package/src/storage/nostr-client.js +173 -49
- package/src/storage/nostr-wrapper.js +6 -2
- package/src/storage/outbox-queue.js +55 -18
- package/src/storage/persistent-storage.js +56 -13
- package/src/storage/sync-service.js +51 -17
- package/src/storage/unified-storage.js +7 -2
- package/src/subscriptions/manager.js +33 -16
- package/dist/index-4XHHKe6S.js.map +0 -1
- package/dist/index-Dz5kOZMI.cjs.map +0 -1
- package/dist/indexeddb-storage-DD7EFBVc.cjs.map +0 -1
- package/dist/indexeddb-storage-lExjjFlV.js.map +0 -1
- package/dist/memory-storage-C68adso2.js.map +0 -1
- package/dist/memory-storage-DD_6yyXT.cjs.map +0 -1
- /package/{cleanup-test-data.js → scripts/cleanup-test-data.js} +0 -0
- /package/{test-ai-real-api.js → scripts/test-ai-real-api.js} +0 -0
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Key Storage - Universal API
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview Key Storage - Universal API.
|
|
3
|
+
*
|
|
4
|
+
* Automatically uses Node.js or Browser implementation for storing private keys.
|
|
5
|
+
* In Node.js, keys are stored in the filesystem (~/.config/holosphere/keys).
|
|
6
|
+
* In browsers, keys are stored in localStorage.
|
|
7
|
+
*
|
|
8
|
+
* @module storage/key-storage
|
|
4
9
|
*/
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
|
-
* Lazy-loaded Node.js modules
|
|
12
|
+
* Lazy-loaded Node.js modules.
|
|
13
|
+
* @private
|
|
8
14
|
*/
|
|
9
15
|
let nodeModules = null;
|
|
10
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Get or initialize Node.js modules for filesystem access.
|
|
19
|
+
*
|
|
20
|
+
* @private
|
|
21
|
+
* @returns {Object|null} Node.js modules or null if unavailable
|
|
22
|
+
*/
|
|
11
23
|
function getNodeModules() {
|
|
12
24
|
if (!nodeModules) {
|
|
13
25
|
try {
|
|
@@ -36,10 +48,17 @@ function getNodeModules() {
|
|
|
36
48
|
}
|
|
37
49
|
|
|
38
50
|
/**
|
|
39
|
-
* Load private key from storage
|
|
51
|
+
* Load private key from storage.
|
|
52
|
+
*
|
|
53
|
+
* Attempts to load from localStorage (browser) or filesystem (Node.js).
|
|
54
|
+
*
|
|
40
55
|
* @param {string} appName - Application name
|
|
41
|
-
* @param {Object} options - Options
|
|
42
|
-
* @
|
|
56
|
+
* @param {Object} [options={}] - Options
|
|
57
|
+
* @param {string} [options.keyDir] - Custom key directory (Node.js only)
|
|
58
|
+
* @returns {string|null} Private key (hex) or null if not found
|
|
59
|
+
* @example
|
|
60
|
+
* const key = loadPrivateKey('myapp');
|
|
61
|
+
* if (key) console.log('Loaded existing key');
|
|
43
62
|
*/
|
|
44
63
|
export function loadPrivateKey(appName, options = {}) {
|
|
45
64
|
// Browser environment
|
|
@@ -70,11 +89,18 @@ export function loadPrivateKey(appName, options = {}) {
|
|
|
70
89
|
}
|
|
71
90
|
|
|
72
91
|
/**
|
|
73
|
-
* Save private key to storage
|
|
92
|
+
* Save private key to storage.
|
|
93
|
+
*
|
|
94
|
+
* Saves to localStorage (browser) or filesystem (Node.js) with secure permissions.
|
|
95
|
+
*
|
|
74
96
|
* @param {string} appName - Application name
|
|
75
|
-
* @param {string} privateKey - Private key (hex)
|
|
76
|
-
* @param {Object} options - Options
|
|
77
|
-
* @
|
|
97
|
+
* @param {string} privateKey - Private key (64-character hex string)
|
|
98
|
+
* @param {Object} [options={}] - Options
|
|
99
|
+
* @param {string} [options.keyDir] - Custom key directory (Node.js only)
|
|
100
|
+
* @returns {boolean} True if saved successfully
|
|
101
|
+
* @throws {Error} If private key format is invalid
|
|
102
|
+
* @example
|
|
103
|
+
* const success = savePrivateKey('myapp', '1a2b3c...');
|
|
78
104
|
*/
|
|
79
105
|
export function savePrivateKey(appName, privateKey, options = {}) {
|
|
80
106
|
if (!/^[0-9a-f]{64}$/i.test(privateKey)) {
|
|
@@ -113,11 +139,17 @@ export function savePrivateKey(appName, privateKey, options = {}) {
|
|
|
113
139
|
}
|
|
114
140
|
|
|
115
141
|
/**
|
|
116
|
-
* Get or create private key for an app
|
|
142
|
+
* Get or create private key for an app.
|
|
143
|
+
*
|
|
144
|
+
* Loads existing key or generates and saves a new one.
|
|
145
|
+
*
|
|
117
146
|
* @param {string} appName - Application name
|
|
118
|
-
* @param {Function} generateFn - Function to generate new key
|
|
119
|
-
* @param {Object} options - Options
|
|
147
|
+
* @param {Function} generateFn - Function to generate new key (returns hex string)
|
|
148
|
+
* @param {Object} [options={}] - Options
|
|
149
|
+
* @param {string} [options.keyDir] - Custom key directory (Node.js only)
|
|
120
150
|
* @returns {string} Private key (hex)
|
|
151
|
+
* @example
|
|
152
|
+
* const key = getOrCreatePrivateKey('myapp', () => generateSecureKey());
|
|
121
153
|
*/
|
|
122
154
|
export function getOrCreatePrivateKey(appName, generateFn, options = {}) {
|
|
123
155
|
const existingKey = loadPrivateKey(appName, options);
|
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Memory-only storage adapter (fallback, no actual persistence)
|
|
2
|
+
* @fileoverview Memory-only storage adapter (fallback, no actual persistence).
|
|
3
|
+
*
|
|
4
|
+
* Provides in-memory storage for testing or when persistent storage is unavailable.
|
|
5
|
+
* Data is shared across instances with the same namespace but lost on process restart.
|
|
6
|
+
*
|
|
7
|
+
* @module storage/memory-storage
|
|
3
8
|
*/
|
|
4
9
|
|
|
5
10
|
import { PersistentStorage } from './persistent-storage.js';
|
|
6
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Memory-only storage adapter.
|
|
14
|
+
*
|
|
15
|
+
* Stores data in memory with no persistence across restarts.
|
|
16
|
+
* Uses a global store to share data across instances with same namespace.
|
|
17
|
+
*
|
|
18
|
+
* @class MemoryStorage
|
|
19
|
+
* @extends PersistentStorage
|
|
20
|
+
* @example
|
|
21
|
+
* const storage = new MemoryStorage();
|
|
22
|
+
* await storage.init('myapp');
|
|
23
|
+
* await storage.put('key1', { id: 'event1' });
|
|
24
|
+
*/
|
|
7
25
|
export class MemoryStorage extends PersistentStorage {
|
|
26
|
+
/**
|
|
27
|
+
* Create a new MemoryStorage instance.
|
|
28
|
+
*/
|
|
8
29
|
constructor() {
|
|
9
30
|
super();
|
|
10
31
|
this.data = new Map();
|
|
11
32
|
this.namespace = null;
|
|
12
33
|
}
|
|
13
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Initialize storage with namespace.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} namespace - Storage namespace
|
|
39
|
+
* @returns {Promise<void>}
|
|
40
|
+
*/
|
|
14
41
|
async init(namespace) {
|
|
15
42
|
this.namespace = namespace;
|
|
16
43
|
// Check if there's existing data for this namespace
|
|
@@ -23,18 +50,33 @@ export class MemoryStorage extends PersistentStorage {
|
|
|
23
50
|
this.data = MemoryStorage._globalStore.get(namespace);
|
|
24
51
|
}
|
|
25
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Store an event.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} key - Storage key
|
|
57
|
+
* @param {Object} event - Event data
|
|
58
|
+
* @returns {Promise<void>}
|
|
59
|
+
*/
|
|
26
60
|
async put(key, event) {
|
|
27
61
|
this.data.set(key, JSON.parse(JSON.stringify(event))); // Deep clone
|
|
28
62
|
}
|
|
29
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Retrieve an event.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} key - Storage key
|
|
68
|
+
* @returns {Promise<Object|null>} Event data or null
|
|
69
|
+
*/
|
|
30
70
|
async get(key) {
|
|
31
71
|
const data = this.data.get(key);
|
|
32
72
|
return data ? JSON.parse(JSON.stringify(data)) : null; // Deep clone
|
|
33
73
|
}
|
|
34
74
|
|
|
35
75
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
76
|
+
* Retrieve all events matching a prefix.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} prefix - Key prefix to match
|
|
79
|
+
* @returns {Promise<any[]>} Array of matching events
|
|
38
80
|
*/
|
|
39
81
|
async getAll(prefix) {
|
|
40
82
|
/** @type {any[]} */
|
|
@@ -47,18 +89,37 @@ export class MemoryStorage extends PersistentStorage {
|
|
|
47
89
|
return results;
|
|
48
90
|
}
|
|
49
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Delete an event.
|
|
94
|
+
*
|
|
95
|
+
* @param {string} key - Storage key
|
|
96
|
+
* @returns {Promise<void>}
|
|
97
|
+
*/
|
|
50
98
|
async delete(key) {
|
|
51
99
|
this.data.delete(key);
|
|
52
100
|
}
|
|
53
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Clear all stored events.
|
|
104
|
+
*
|
|
105
|
+
* @returns {Promise<void>}
|
|
106
|
+
*/
|
|
54
107
|
async clear() {
|
|
55
108
|
this.data.clear();
|
|
56
109
|
}
|
|
57
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Close storage (no-op for memory storage).
|
|
113
|
+
*
|
|
114
|
+
* @returns {Promise<void>}
|
|
115
|
+
*/
|
|
58
116
|
async close() {
|
|
59
117
|
// Nothing to close for memory storage
|
|
60
118
|
}
|
|
61
119
|
}
|
|
62
120
|
|
|
63
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Global store shared across instances with same namespace.
|
|
123
|
+
* @private
|
|
124
|
+
*/
|
|
64
125
|
MemoryStorage._globalStore = null;
|
package/src/storage/migration.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Migration
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* - Import data to any backend from the portable format
|
|
7
|
-
* - Direct migration between backends
|
|
8
|
-
* - Validation of migrated data
|
|
2
|
+
* @fileoverview Migration tool for HoloSphere storage backends.
|
|
3
|
+
* Enables data migration between different storage backends (Nostr, GunDB, ActivityPub)
|
|
4
|
+
* with export/import functionality, direct migration, and validation.
|
|
5
|
+
* @module storage/migration
|
|
9
6
|
*/
|
|
10
7
|
|
|
11
8
|
import { BackendFactory } from './backend-factory.js';
|
|
@@ -38,9 +35,25 @@ import { BackendFactory } from './backend-factory.js';
|
|
|
38
35
|
* @property {Object[]} errors - Error details
|
|
39
36
|
*/
|
|
40
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Migration tool for transferring data between HoloSphere storage backends.
|
|
40
|
+
* Supports export/import to portable format, direct migration, and validation.
|
|
41
|
+
*
|
|
42
|
+
* @class MigrationTool
|
|
43
|
+
* @example
|
|
44
|
+
* const tool = new MigrationTool();
|
|
45
|
+
* await tool.setSource('nostr', { relays: ['wss://...'] });
|
|
46
|
+
* await tool.setTarget('gundb', { peers: ['wss://...'] });
|
|
47
|
+
* const results = await tool.migrate();
|
|
48
|
+
*/
|
|
41
49
|
export class MigrationTool {
|
|
50
|
+
/**
|
|
51
|
+
* Create a new MigrationTool instance.
|
|
52
|
+
*/
|
|
42
53
|
constructor() {
|
|
54
|
+
/** @type {StorageBackend|null} */
|
|
43
55
|
this.sourceBackend = null;
|
|
56
|
+
/** @type {StorageBackend|null} */
|
|
44
57
|
this.targetBackend = null;
|
|
45
58
|
}
|
|
46
59
|
|
|
@@ -1,34 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Nostr Async Utilities
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview Nostr Async Utilities.
|
|
3
|
+
*
|
|
4
|
+
* Provides Promise-based wrappers and async patterns for Nostr operations.
|
|
5
|
+
* Includes local-first data access, query deduplication, subscription management,
|
|
6
|
+
* and background refresh capabilities for optimal performance.
|
|
7
|
+
*
|
|
8
|
+
* @module storage/nostr-async
|
|
4
9
|
*/
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
|
-
* Global subscription manager to prevent duplicate subscriptions
|
|
12
|
+
* Global subscription manager to prevent duplicate subscriptions.
|
|
8
13
|
* Maps: subscriptionKey -> subscription object
|
|
14
|
+
* @private
|
|
9
15
|
*/
|
|
10
16
|
const globalSubscriptions = new Map();
|
|
11
17
|
|
|
12
18
|
/**
|
|
13
|
-
* Single-path subscription manager (for nostrSubscribe)
|
|
19
|
+
* Single-path subscription manager (for nostrSubscribe).
|
|
14
20
|
* Maps: subscriptionKey -> { subscription, callbacks: [] }
|
|
21
|
+
* @private
|
|
15
22
|
*/
|
|
16
23
|
const singlePathSubscriptions = new Map();
|
|
17
24
|
|
|
18
25
|
/**
|
|
19
|
-
* Query deduplication for nostrGet - prevents duplicate relay queries
|
|
26
|
+
* Query deduplication for nostrGet - prevents duplicate relay queries.
|
|
20
27
|
* Maps: queryKey -> { promise, timestamp, callbacks: [] }
|
|
28
|
+
* @private
|
|
21
29
|
*/
|
|
22
30
|
const pendingQueries = new Map();
|
|
23
|
-
const QUERY_DEDUP_WINDOW = 2000; // 2 second window for deduplication
|
|
24
31
|
|
|
25
32
|
/**
|
|
26
|
-
*
|
|
33
|
+
* Time window for query deduplication (2 seconds).
|
|
34
|
+
* @private
|
|
35
|
+
* @constant {number}
|
|
36
|
+
*/
|
|
37
|
+
const QUERY_DEDUP_WINDOW = 2000;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Write data as Nostr event (parameterized replaceable event).
|
|
41
|
+
*
|
|
27
42
|
* @param {Object} client - NostrClient instance
|
|
28
43
|
* @param {string} path - Path identifier (encoded in d-tag)
|
|
29
44
|
* @param {Object} data - Data to store
|
|
30
|
-
* @param {number} kind - Event kind (default: 30000 for parameterized replaceable)
|
|
31
|
-
* @returns {Promise<Object>} Published event result
|
|
45
|
+
* @param {number} [kind=30000] - Event kind (default: 30000 for parameterized replaceable)
|
|
46
|
+
* @returns {Promise<Object>} Published event result with relay responses
|
|
47
|
+
* @example
|
|
48
|
+
* const result = await nostrPut(client, 'myapp/holon123/items/item1', { name: 'Test' });
|
|
49
|
+
* console.log(result.event.id); // Event ID
|
|
32
50
|
*/
|
|
33
51
|
export async function nostrPut(client, path, data, kind = 30000) {
|
|
34
52
|
const dataEvent = {
|
|
@@ -45,17 +63,25 @@ export async function nostrPut(client, path, data, kind = 30000) {
|
|
|
45
63
|
}
|
|
46
64
|
|
|
47
65
|
/**
|
|
48
|
-
* Read data from Nostr (query by d-tag)
|
|
49
|
-
*
|
|
50
|
-
*
|
|
66
|
+
* Read data from Nostr (query by d-tag).
|
|
67
|
+
*
|
|
68
|
+
* LOCAL-FIRST: Checks persistent storage first, never blocks on network.
|
|
69
|
+
* Uses query deduplication to prevent duplicate relay queries within a time window.
|
|
70
|
+
*
|
|
51
71
|
* @param {Object} client - NostrClient instance
|
|
52
72
|
* @param {string} path - Path identifier
|
|
53
|
-
* @param {number} kind - Event kind (default: 30000)
|
|
54
|
-
* @param {Object} options - Query options
|
|
55
|
-
* @param {string[]} options.authors - Array of public keys to query (default: [client.publicKey])
|
|
56
|
-
* @param {boolean} options.includeAuthor - If true, adds _author field to returned data
|
|
57
|
-
* @param {boolean} options.skipPersistent - If true, skip persistent storage check
|
|
73
|
+
* @param {number} [kind=30000] - Event kind (default: 30000)
|
|
74
|
+
* @param {Object} [options={}] - Query options
|
|
75
|
+
* @param {string[]} [options.authors] - Array of public keys to query (default: [client.publicKey])
|
|
76
|
+
* @param {boolean} [options.includeAuthor=false] - If true, adds _author field to returned data
|
|
77
|
+
* @param {boolean} [options.skipPersistent=false] - If true, skip persistent storage check
|
|
78
|
+
* @param {number} [options.timeout=30000] - Query timeout in milliseconds
|
|
58
79
|
* @returns {Promise<Object|null>} Data or null if not found
|
|
80
|
+
* @example
|
|
81
|
+
* const data = await nostrGet(client, 'myapp/holon1/items/item1');
|
|
82
|
+
* if (data) {
|
|
83
|
+
* console.log(data.name);
|
|
84
|
+
* }
|
|
59
85
|
*/
|
|
60
86
|
export async function nostrGet(client, path, kind = 30000, options = {}) {
|
|
61
87
|
const timeout = options.timeout !== undefined ? options.timeout : 30000;
|
|
@@ -72,8 +98,8 @@ export async function nostrGet(client, path, kind = 30000, options = {}) {
|
|
|
72
98
|
try {
|
|
73
99
|
const data = JSON.parse(persistedEvent.content);
|
|
74
100
|
|
|
75
|
-
// Skip deleted items
|
|
76
|
-
if (data._deleted) {
|
|
101
|
+
// Skip null/undefined or deleted items
|
|
102
|
+
if (!data || data._deleted) {
|
|
77
103
|
return null;
|
|
78
104
|
}
|
|
79
105
|
|
|
@@ -128,8 +154,16 @@ export async function nostrGet(client, path, kind = 30000, options = {}) {
|
|
|
128
154
|
}
|
|
129
155
|
|
|
130
156
|
/**
|
|
131
|
-
* Internal function to execute nostrGet query
|
|
157
|
+
* Internal function to execute nostrGet query.
|
|
158
|
+
*
|
|
132
159
|
* @private
|
|
160
|
+
* @param {Object} client - NostrClient instance
|
|
161
|
+
* @param {string} path - Path identifier
|
|
162
|
+
* @param {number} kind - Event kind
|
|
163
|
+
* @param {string[]} authors - Array of author public keys
|
|
164
|
+
* @param {number} timeout - Query timeout
|
|
165
|
+
* @param {Object} options - Query options
|
|
166
|
+
* @returns {Promise<Object|null>} Data or null
|
|
133
167
|
*/
|
|
134
168
|
async function _executeNostrGet(client, path, kind, authors, timeout, options) {
|
|
135
169
|
const filter = {
|
|
@@ -153,8 +187,8 @@ async function _executeNostrGet(client, path, kind, authors, timeout, options) {
|
|
|
153
187
|
|
|
154
188
|
try {
|
|
155
189
|
const data = JSON.parse(event.content);
|
|
156
|
-
// Skip deleted items
|
|
157
|
-
if (data._deleted) {
|
|
190
|
+
// Skip null/undefined or deleted items
|
|
191
|
+
if (!data || data._deleted) {
|
|
158
192
|
return null;
|
|
159
193
|
}
|
|
160
194
|
// Optionally include author information
|
|
@@ -169,17 +203,24 @@ async function _executeNostrGet(client, path, kind, authors, timeout, options) {
|
|
|
169
203
|
}
|
|
170
204
|
|
|
171
205
|
/**
|
|
172
|
-
* Query all events under a path prefix
|
|
173
|
-
*
|
|
174
|
-
*
|
|
206
|
+
* Query all events under a path prefix.
|
|
207
|
+
*
|
|
208
|
+
* LOCAL-FIRST: Checks persistent storage first, never blocks on network.
|
|
209
|
+
* Uses query deduplication to prevent duplicate relay queries within a time window.
|
|
210
|
+
*
|
|
175
211
|
* @param {Object} client - NostrClient instance
|
|
176
212
|
* @param {string} pathPrefix - Path prefix to match
|
|
177
|
-
* @param {number} kind - Event kind (default: 30000)
|
|
178
|
-
* @param {Object} options - Query options
|
|
179
|
-
* @param {string[]} options.authors - Array of public keys to query (default: [client.publicKey])
|
|
180
|
-
* @param {boolean} options.includeAuthor - If true, adds _author field to returned data
|
|
181
|
-
* @param {boolean} options.skipPersistent - If true, skip persistent storage check
|
|
213
|
+
* @param {number} [kind=30000] - Event kind (default: 30000)
|
|
214
|
+
* @param {Object} [options={}] - Query options
|
|
215
|
+
* @param {string[]} [options.authors] - Array of public keys to query (default: [client.publicKey])
|
|
216
|
+
* @param {boolean} [options.includeAuthor=false] - If true, adds _author field to returned data
|
|
217
|
+
* @param {boolean} [options.skipPersistent=false] - If true, skip persistent storage check
|
|
218
|
+
* @param {number} [options.timeout=30000] - Query timeout in milliseconds
|
|
219
|
+
* @param {number} [options.limit=1000] - Maximum number of events to retrieve
|
|
182
220
|
* @returns {Promise<Array>} Array of data objects
|
|
221
|
+
* @example
|
|
222
|
+
* const items = await nostrGetAll(client, 'myapp/holon1/items/');
|
|
223
|
+
* console.log(`Found ${items.length} items`);
|
|
183
224
|
*/
|
|
184
225
|
export async function nostrGetAll(client, pathPrefix, kind = 30000, options = {}) {
|
|
185
226
|
const timeout = options.timeout !== undefined ? options.timeout : 30000;
|
|
@@ -208,8 +249,8 @@ export async function nostrGetAll(client, pathPrefix, kind = 30000, options = {}
|
|
|
208
249
|
try {
|
|
209
250
|
const data = JSON.parse(event.content);
|
|
210
251
|
|
|
211
|
-
// Handle deleted items - remove from map if this is newer
|
|
212
|
-
if (data._deleted) {
|
|
252
|
+
// Handle null/undefined or deleted items - remove from map if this is newer
|
|
253
|
+
if (!data || data._deleted) {
|
|
213
254
|
byPath.delete(path);
|
|
214
255
|
continue;
|
|
215
256
|
}
|
|
@@ -266,8 +307,17 @@ export async function nostrGetAll(client, pathPrefix, kind = 30000, options = {}
|
|
|
266
307
|
}
|
|
267
308
|
|
|
268
309
|
/**
|
|
269
|
-
* Internal function to execute nostrGetAll query
|
|
310
|
+
* Internal function to execute nostrGetAll query.
|
|
311
|
+
*
|
|
270
312
|
* @private
|
|
313
|
+
* @param {Object} client - NostrClient instance
|
|
314
|
+
* @param {string} pathPrefix - Path prefix to match
|
|
315
|
+
* @param {number} kind - Event kind
|
|
316
|
+
* @param {string[]} authors - Array of author public keys
|
|
317
|
+
* @param {number} timeout - Query timeout
|
|
318
|
+
* @param {number} limit - Maximum results
|
|
319
|
+
* @param {Object} options - Query options
|
|
320
|
+
* @returns {Promise<Array>} Array of data objects
|
|
271
321
|
*/
|
|
272
322
|
async function _executeNostrGetAll(client, pathPrefix, kind, authors, timeout, limit, options) {
|
|
273
323
|
const filter = {
|
|
@@ -296,8 +346,8 @@ async function _executeNostrGetAll(client, pathPrefix, kind, authors, timeout, l
|
|
|
296
346
|
try {
|
|
297
347
|
const data = JSON.parse(event.content);
|
|
298
348
|
|
|
299
|
-
// Handle deleted items - remove from map if this is newer
|
|
300
|
-
if (data._deleted) {
|
|
349
|
+
// Handle null/undefined or deleted items - remove from map if this is newer
|
|
350
|
+
if (!data || data._deleted) {
|
|
301
351
|
byPath.delete(dTag);
|
|
302
352
|
continue;
|
|
303
353
|
}
|
|
@@ -318,14 +368,18 @@ async function _executeNostrGetAll(client, pathPrefix, kind, authors, timeout, l
|
|
|
318
368
|
}
|
|
319
369
|
|
|
320
370
|
/**
|
|
321
|
-
* Query all events under a path prefix (HYBRID MODE - local + relay)
|
|
322
|
-
*
|
|
371
|
+
* Query all events under a path prefix (HYBRID MODE - local + relay).
|
|
372
|
+
*
|
|
373
|
+
* Checks local cache first, then merges with relay data.
|
|
374
|
+
*
|
|
323
375
|
* @param {Object} client - NostrClient instance
|
|
324
376
|
* @param {string} pathPrefix - Path prefix to match
|
|
325
|
-
* @param {number} kind - Event kind (default: 30000)
|
|
326
|
-
* @param {Object} options - Query options
|
|
327
|
-
* @param {string[]} options.authors - Array of public keys to query (default: [client.publicKey])
|
|
328
|
-
* @param {boolean} options.includeAuthor - If true, adds _author field to returned data
|
|
377
|
+
* @param {number} [kind=30000] - Event kind (default: 30000)
|
|
378
|
+
* @param {Object} [options={}] - Query options
|
|
379
|
+
* @param {string[]} [options.authors] - Array of public keys to query (default: [client.publicKey])
|
|
380
|
+
* @param {boolean} [options.includeAuthor=false] - If true, adds _author field to returned data
|
|
381
|
+
* @param {number} [options.timeout=30000] - Query timeout in milliseconds
|
|
382
|
+
* @param {number} [options.limit=1000] - Maximum number of events to retrieve
|
|
329
383
|
* @returns {Promise<Array>} Array of data objects (merged from local + relay)
|
|
330
384
|
*/
|
|
331
385
|
export async function nostrGetAllHybrid(client, pathPrefix, kind = 30000, options = {}) {
|
|
@@ -386,11 +440,19 @@ export async function nostrGetAllHybrid(client, pathPrefix, kind = 30000, option
|
|
|
386
440
|
}
|
|
387
441
|
|
|
388
442
|
/**
|
|
389
|
-
* Delete data (publish deletion event - NIP-09)
|
|
443
|
+
* Delete data (publish deletion event - NIP-09).
|
|
444
|
+
*
|
|
445
|
+
* Publishes a tombstone event and a NIP-09 deletion event to mark data as deleted.
|
|
446
|
+
*
|
|
390
447
|
* @param {Object} client - NostrClient instance
|
|
391
448
|
* @param {string} path - Path identifier
|
|
392
|
-
* @param {number} kind - Original event kind (default: 30000)
|
|
393
|
-
* @returns {Promise<Object>} Deletion event result
|
|
449
|
+
* @param {number} [kind=30000] - Original event kind (default: 30000)
|
|
450
|
+
* @returns {Promise<Object>} Deletion event result with status
|
|
451
|
+
* @example
|
|
452
|
+
* const result = await nostrDelete(client, 'myapp/holon1/items/item1');
|
|
453
|
+
* if (result.reason !== 'not_found') {
|
|
454
|
+
* console.log('Item deleted successfully');
|
|
455
|
+
* }
|
|
394
456
|
*/
|
|
395
457
|
export async function nostrDelete(client, path, kind = 30000) {
|
|
396
458
|
// Read existing data first
|
|
@@ -447,11 +509,15 @@ export async function nostrDelete(client, path, kind = 30000) {
|
|
|
447
509
|
}
|
|
448
510
|
|
|
449
511
|
/**
|
|
450
|
-
* Delete all data with path prefix (publish deletion events - NIP-09)
|
|
512
|
+
* Delete all data with path prefix (publish deletion events - NIP-09).
|
|
513
|
+
*
|
|
451
514
|
* @param {Object} client - NostrClient instance
|
|
452
515
|
* @param {string} pathPrefix - Path prefix to delete all items under
|
|
453
|
-
* @param {number} kind - Original event kind (default: 30000)
|
|
454
|
-
* @returns {Promise<Object>} Deletion results
|
|
516
|
+
* @param {number} [kind=30000] - Original event kind (default: 30000)
|
|
517
|
+
* @returns {Promise<Object>} Deletion results with success count
|
|
518
|
+
* @example
|
|
519
|
+
* const result = await nostrDeleteAll(client, 'myapp/holon1/items/');
|
|
520
|
+
* console.log(`Deleted ${result.count} items`);
|
|
455
521
|
*/
|
|
456
522
|
export async function nostrDeleteAll(client, pathPrefix, kind = 30000) {
|
|
457
523
|
// Query events from relay
|
|
@@ -566,13 +632,21 @@ export async function nostrDeleteAll(client, pathPrefix, kind = 30000) {
|
|
|
566
632
|
}
|
|
567
633
|
|
|
568
634
|
/**
|
|
569
|
-
* Subscribe to path changes
|
|
570
|
-
*
|
|
635
|
+
* Subscribe to path changes.
|
|
636
|
+
*
|
|
637
|
+
* Uses subscription deduplication - multiple subscribers to same path share one relay subscription.
|
|
638
|
+
*
|
|
571
639
|
* @param {Object} client - NostrClient instance
|
|
572
640
|
* @param {string} path - Path to subscribe to
|
|
573
641
|
* @param {Function} callback - Callback function (data, event) => void
|
|
574
|
-
* @param {Object} options - Subscription options
|
|
642
|
+
* @param {Object} [options={}] - Subscription options
|
|
643
|
+
* @param {number} [options.kind=30000] - Event kind to subscribe to
|
|
575
644
|
* @returns {Object} Subscription object with unsubscribe method
|
|
645
|
+
* @example
|
|
646
|
+
* const sub = nostrSubscribe(client, 'myapp/holon1/items/item1', (data, event) => {
|
|
647
|
+
* console.log('Item updated:', data);
|
|
648
|
+
* });
|
|
649
|
+
* // Later: sub.unsubscribe();
|
|
576
650
|
*/
|
|
577
651
|
export function nostrSubscribe(client, path, callback, options = {}) {
|
|
578
652
|
const kind = options.kind || 30000;
|
|
@@ -631,8 +705,8 @@ export function nostrSubscribe(client, path, callback, options = {}) {
|
|
|
631
705
|
try {
|
|
632
706
|
const data = JSON.parse(event.content);
|
|
633
707
|
|
|
634
|
-
// Skip deleted items - don't send tombstones to subscribers
|
|
635
|
-
if (data._deleted) {
|
|
708
|
+
// Skip null/undefined or deleted items - don't send tombstones to subscribers
|
|
709
|
+
if (!data || data._deleted) {
|
|
636
710
|
return;
|
|
637
711
|
}
|
|
638
712
|
|
|
@@ -674,7 +748,7 @@ export function nostrSubscribe(client, path, callback, options = {}) {
|
|
|
674
748
|
}
|
|
675
749
|
|
|
676
750
|
/**
|
|
677
|
-
* Subscribe to path prefix (multiple paths)
|
|
751
|
+
* Subscribe to path prefix (multiple paths).
|
|
678
752
|
*
|
|
679
753
|
* Subscribes to data events and uses Page Visibility API to refresh when tab becomes visible.
|
|
680
754
|
* Note: Nostr relays do not broadcast replaceable event updates to active subscriptions.
|
|
@@ -682,8 +756,14 @@ export function nostrSubscribe(client, path, callback, options = {}) {
|
|
|
682
756
|
* @param {Object} client - NostrClient instance
|
|
683
757
|
* @param {string} pathPrefix - Path prefix to match
|
|
684
758
|
* @param {Function} callback - Callback function (data, path, event) => void
|
|
685
|
-
* @param {Object} options - Subscription options
|
|
759
|
+
* @param {Object} [options={}] - Subscription options
|
|
760
|
+
* @param {number} [options.kind=30000] - Event kind to subscribe to
|
|
686
761
|
* @returns {Promise<Object>} Subscription object with unsubscribe method
|
|
762
|
+
* @example
|
|
763
|
+
* const sub = await nostrSubscribeMany(client, 'myapp/holon1/items/', (data, path, event) => {
|
|
764
|
+
* console.log('Item event:', data);
|
|
765
|
+
* });
|
|
766
|
+
* // Later: sub.unsubscribe();
|
|
687
767
|
*/
|
|
688
768
|
export async function nostrSubscribeMany(client, pathPrefix, callback, options = {}) {
|
|
689
769
|
const kind = options.kind || 30000;
|
|
@@ -758,8 +838,8 @@ export async function nostrSubscribeMany(client, pathPrefix, callback, options =
|
|
|
758
838
|
try {
|
|
759
839
|
const data = JSON.parse(event.content);
|
|
760
840
|
|
|
761
|
-
// Skip deleted items - don't send tombstones to subscribers
|
|
762
|
-
if (data._deleted) {
|
|
841
|
+
// Skip null/undefined data or deleted items - don't send tombstones to subscribers
|
|
842
|
+
if (!data || data._deleted) {
|
|
763
843
|
return;
|
|
764
844
|
}
|
|
765
845
|
|
|
@@ -844,12 +924,16 @@ export async function nostrSubscribeMany(client, pathPrefix, callback, options =
|
|
|
844
924
|
}
|
|
845
925
|
|
|
846
926
|
/**
|
|
847
|
-
* Update data (merge with existing)
|
|
927
|
+
* Update data (merge with existing).
|
|
928
|
+
*
|
|
848
929
|
* @param {Object} client - NostrClient instance
|
|
849
930
|
* @param {string} path - Path identifier
|
|
850
931
|
* @param {Object} updates - Fields to update
|
|
851
|
-
* @param {number} kind - Event kind (default: 30000)
|
|
932
|
+
* @param {number} [kind=30000] - Event kind (default: 30000)
|
|
852
933
|
* @returns {Promise<Object>} Updated event result
|
|
934
|
+
* @throws {Error} If no data found at path
|
|
935
|
+
* @example
|
|
936
|
+
* await nostrUpdate(client, 'myapp/holon1/items/item1', { status: 'completed' });
|
|
853
937
|
*/
|
|
854
938
|
export async function nostrUpdate(client, path, updates, kind = 30000) {
|
|
855
939
|
// Read existing data
|
|
@@ -867,10 +951,11 @@ export async function nostrUpdate(client, path, updates, kind = 30000) {
|
|
|
867
951
|
}
|
|
868
952
|
|
|
869
953
|
/**
|
|
870
|
-
* Batch read multiple paths
|
|
954
|
+
* Batch read multiple paths.
|
|
955
|
+
*
|
|
871
956
|
* @param {Object} client - NostrClient instance
|
|
872
957
|
* @param {string[]} paths - Array of paths
|
|
873
|
-
* @param {number} kind - Event kind (default: 30000)
|
|
958
|
+
* @param {number} [kind=30000] - Event kind (default: 30000)
|
|
874
959
|
* @returns {Promise<Object>} Object mapping paths to data
|
|
875
960
|
*/
|
|
876
961
|
export async function nostrBatchGet(client, paths, kind = 30000) {
|
|
@@ -911,10 +996,11 @@ export async function nostrBatchGet(client, paths, kind = 30000) {
|
|
|
911
996
|
}
|
|
912
997
|
|
|
913
998
|
/**
|
|
914
|
-
* Batch write multiple paths
|
|
999
|
+
* Batch write multiple paths.
|
|
1000
|
+
*
|
|
915
1001
|
* @param {Object} client - NostrClient instance
|
|
916
1002
|
* @param {Object} pathDataMap - Object mapping paths to data
|
|
917
|
-
* @param {number} kind - Event kind (default: 30000)
|
|
1003
|
+
* @param {number} [kind=30000] - Event kind (default: 30000)
|
|
918
1004
|
* @returns {Promise<Array>} Array of publish results
|
|
919
1005
|
*/
|
|
920
1006
|
export async function nostrBatchPut(client, pathDataMap, kind = 30000) {
|
|
@@ -926,11 +1012,13 @@ export async function nostrBatchPut(client, pathDataMap, kind = 30000) {
|
|
|
926
1012
|
}
|
|
927
1013
|
|
|
928
1014
|
/**
|
|
929
|
-
* Retry operation with exponential backoff
|
|
1015
|
+
* Retry operation with exponential backoff.
|
|
1016
|
+
*
|
|
930
1017
|
* @param {Function} operation - Async function to retry
|
|
931
|
-
* @param {number} maxRetries - Max retry attempts
|
|
932
|
-
* @param {number} baseDelay - Base delay in ms
|
|
1018
|
+
* @param {number} [maxRetries=3] - Max retry attempts
|
|
1019
|
+
* @param {number} [baseDelay=100] - Base delay in ms
|
|
933
1020
|
* @returns {Promise<any>} Promise resolving to operation result
|
|
1021
|
+
* @throws {Error} Last error if all retries fail
|
|
934
1022
|
*/
|
|
935
1023
|
export async function nostrRetry(operation, maxRetries = 3, baseDelay = 100) {
|
|
936
1024
|
let lastError;
|
|
@@ -951,12 +1039,14 @@ export async function nostrRetry(operation, maxRetries = 3, baseDelay = 100) {
|
|
|
951
1039
|
}
|
|
952
1040
|
|
|
953
1041
|
/**
|
|
954
|
-
* Wait for specific condition on data
|
|
1042
|
+
* Wait for specific condition on data.
|
|
1043
|
+
*
|
|
955
1044
|
* @param {Object} client - NostrClient instance
|
|
956
1045
|
* @param {string} path - Path to watch
|
|
957
1046
|
* @param {Function} predicate - Condition function (data) => boolean
|
|
958
|
-
* @param {number} timeout - Timeout in ms
|
|
1047
|
+
* @param {number} [timeout=5000] - Timeout in ms
|
|
959
1048
|
* @returns {Promise<any>} Promise resolving when condition is met
|
|
1049
|
+
* @throws {Error} If timeout occurs before condition is met
|
|
960
1050
|
*/
|
|
961
1051
|
export async function nostrWaitFor(client, path, predicate, timeout = 5000) {
|
|
962
1052
|
return new Promise((resolve, reject) => {
|