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,19 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Nostr Client - SimplePool wrapper for relay management
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview Nostr Client - SimplePool wrapper for relay management.
|
|
3
|
+
*
|
|
4
|
+
* Provides connection pooling, relay management, event caching, persistent storage,
|
|
5
|
+
* outbox queue for guaranteed delivery, and background sync services.
|
|
6
|
+
*
|
|
7
|
+
* @module storage/nostr-client
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
10
|
import { SimplePool, finalizeEvent, getPublicKey } from 'nostr-tools';
|
|
7
11
|
import { OutboxQueue } from './outbox-queue.js';
|
|
8
12
|
import { SyncService } from './sync-service.js';
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Global pool singleton - reuse connections across NostrClient instances.
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
11
18
|
let globalPool = null;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Set of relays used by the global pool.
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
12
24
|
let globalPoolRelays = new Set();
|
|
13
25
|
|
|
14
26
|
/**
|
|
15
|
-
* Get or create global SimplePool singleton
|
|
16
|
-
* This ensures WebSocket connections are reused across all operations
|
|
27
|
+
* Get or create global SimplePool singleton.
|
|
28
|
+
* This ensures WebSocket connections are reused across all operations.
|
|
29
|
+
*
|
|
30
|
+
* @private
|
|
31
|
+
* @param {Object} [config={}] - Pool configuration
|
|
32
|
+
* @param {boolean} [config.enableReconnect=true] - Enable auto-reconnect
|
|
33
|
+
* @param {boolean} [config.enablePing=true] - Enable ping/pong
|
|
34
|
+
* @returns {SimplePool} The global SimplePool instance
|
|
17
35
|
*/
|
|
18
36
|
function getGlobalPool(config = {}) {
|
|
19
37
|
if (!globalPool) {
|
|
@@ -25,40 +43,93 @@ function getGlobalPool(config = {}) {
|
|
|
25
43
|
return globalPool;
|
|
26
44
|
}
|
|
27
45
|
|
|
28
|
-
|
|
29
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Global pending queries map for deduplication.
|
|
48
|
+
* Key: JSON-stringified filter, Value: { promise, timestamp }
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
30
51
|
const pendingQueries = new Map();
|
|
31
|
-
const PENDING_QUERY_TIMEOUT = 5000; // 5 seconds
|
|
32
52
|
|
|
33
|
-
|
|
34
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Pending query timeout (5 seconds).
|
|
55
|
+
* @private
|
|
56
|
+
* @constant {number}
|
|
57
|
+
*/
|
|
58
|
+
const PENDING_QUERY_TIMEOUT = 5000;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Global active subscriptions map for subscription deduplication.
|
|
62
|
+
* Key: JSON-stringified filter, Value: { subscription, callbacks: Set, refCount }
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
35
65
|
const activeSubscriptions = new Map();
|
|
36
66
|
|
|
37
|
-
|
|
38
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Throttle background refreshes to avoid flooding the relay.
|
|
69
|
+
* Key: path, Value: timestamp of last refresh
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
39
72
|
const backgroundRefreshThrottle = new Map();
|
|
40
|
-
const BACKGROUND_REFRESH_INTERVAL = 30000; // Only refresh same path every 30 seconds
|
|
41
73
|
|
|
42
|
-
|
|
43
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Background refresh interval (30 seconds).
|
|
76
|
+
* @private
|
|
77
|
+
* @constant {number}
|
|
78
|
+
*/
|
|
79
|
+
const BACKGROUND_REFRESH_INTERVAL = 30000;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Write debouncing for rapid updates to the same path.
|
|
83
|
+
* Key: d-tag path, Value: { event, timer, resolve, reject }
|
|
84
|
+
* @private
|
|
85
|
+
*/
|
|
44
86
|
const pendingWrites = new Map();
|
|
45
|
-
const WRITE_DEBOUNCE_MS = 500; // Debounce writes within 500ms window
|
|
46
87
|
|
|
47
|
-
|
|
48
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Write debounce window (500ms).
|
|
90
|
+
* @private
|
|
91
|
+
* @constant {number}
|
|
92
|
+
*/
|
|
93
|
+
const WRITE_DEBOUNCE_MS = 500;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Long-lived subscription manager - keeps ONE subscription per author for real-time updates.
|
|
97
|
+
* Key: pubkey, Value: { subscription, lastEventTime, initialized }
|
|
98
|
+
* @private
|
|
99
|
+
*/
|
|
49
100
|
const authorSubscriptions = new Map();
|
|
50
|
-
const AUTHOR_SUB_INIT_TIMEOUT = 5000; // Wait up to 5s for initial data load
|
|
51
101
|
|
|
52
102
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
103
|
+
* Author subscription initialization timeout (5 seconds).
|
|
104
|
+
* @private
|
|
105
|
+
* @constant {number}
|
|
106
|
+
*/
|
|
107
|
+
const AUTHOR_SUB_INIT_TIMEOUT = 5000;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Simple LRU Cache implementation.
|
|
111
|
+
* Automatically evicts least recently used entries when max size is reached.
|
|
112
|
+
*
|
|
113
|
+
* @private
|
|
114
|
+
* @class LRUCache
|
|
55
115
|
*/
|
|
56
116
|
class LRUCache {
|
|
117
|
+
/**
|
|
118
|
+
* Create a new LRU cache.
|
|
119
|
+
*
|
|
120
|
+
* @param {number} [maxSize=500] - Maximum number of entries
|
|
121
|
+
*/
|
|
57
122
|
constructor(maxSize = 500) {
|
|
58
123
|
this.maxSize = maxSize;
|
|
59
124
|
this.cache = new Map();
|
|
60
125
|
}
|
|
61
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Get an entry from the cache.
|
|
129
|
+
*
|
|
130
|
+
* @param {string} key - Cache key
|
|
131
|
+
* @returns {*} Cached value or undefined
|
|
132
|
+
*/
|
|
62
133
|
get(key) {
|
|
63
134
|
if (!this.cache.has(key)) return undefined;
|
|
64
135
|
|
|
@@ -140,17 +211,35 @@ function ensureWebSocket() {
|
|
|
140
211
|
import { createPersistentStorage } from './persistent-storage.js';
|
|
141
212
|
|
|
142
213
|
/**
|
|
143
|
-
* NostrClient - Manages connections to Nostr relays
|
|
214
|
+
* NostrClient - Manages connections to Nostr relays.
|
|
215
|
+
*
|
|
216
|
+
* Provides event publishing, querying, subscription management, persistent caching,
|
|
217
|
+
* and guaranteed delivery via outbox queue.
|
|
218
|
+
*
|
|
219
|
+
* @class NostrClient
|
|
220
|
+
* @example
|
|
221
|
+
* const client = new NostrClient({
|
|
222
|
+
* relays: ['wss://relay.example.com'],
|
|
223
|
+
* appName: 'myapp',
|
|
224
|
+
* persistence: true
|
|
225
|
+
* });
|
|
144
226
|
*/
|
|
145
227
|
export class NostrClient {
|
|
146
228
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
* @param {
|
|
150
|
-
* @param {
|
|
151
|
-
* @param {
|
|
152
|
-
* @param {
|
|
153
|
-
* @param {boolean} config.
|
|
229
|
+
* Create a new NostrClient.
|
|
230
|
+
*
|
|
231
|
+
* @param {Object} [config={}] - Configuration options
|
|
232
|
+
* @param {string[]} [config.relays=[]] - Array of relay URLs
|
|
233
|
+
* @param {string} [config.privateKey] - Private key for signing (hex format)
|
|
234
|
+
* @param {boolean} [config.enableReconnect=true] - Auto-reconnect on disconnect
|
|
235
|
+
* @param {boolean} [config.enablePing=true] - Auto-ping relays
|
|
236
|
+
* @param {string} [config.appName] - Application name for storage namespace
|
|
237
|
+
* @param {boolean} [config.persistence=true] - Enable persistent storage
|
|
238
|
+
* @param {number} [config.cacheSize=500] - Maximum cache size
|
|
239
|
+
* @param {number} [config.persistBatchMs=100] - Batch persist writes within this window
|
|
240
|
+
* @param {boolean} [config.backgroundSync=true] - Enable background sync service
|
|
241
|
+
* @param {string} [config.dataDir] - Data directory for persistent storage
|
|
242
|
+
* @throws {Error} If relays is not an array
|
|
154
243
|
*/
|
|
155
244
|
constructor(config = {}) {
|
|
156
245
|
if (config.relays && !Array.isArray(config.relays)) {
|
|
@@ -181,8 +270,10 @@ export class NostrClient {
|
|
|
181
270
|
}
|
|
182
271
|
|
|
183
272
|
/**
|
|
184
|
-
* Initialize WebSocket polyfill and pool
|
|
273
|
+
* Initialize WebSocket polyfill and pool.
|
|
274
|
+
*
|
|
185
275
|
* @private
|
|
276
|
+
* @returns {Promise<void>}
|
|
186
277
|
*/
|
|
187
278
|
async _initialize() {
|
|
188
279
|
// Ensure WebSocket is available before initializing pool
|
|
@@ -422,13 +513,21 @@ export class NostrClient {
|
|
|
422
513
|
}
|
|
423
514
|
|
|
424
515
|
/**
|
|
425
|
-
* Publish event to relays
|
|
426
|
-
*
|
|
516
|
+
* Publish event to relays.
|
|
517
|
+
*
|
|
518
|
+
* Supports debouncing for replaceable events (kind 30000-39999) to avoid rapid updates.
|
|
519
|
+
*
|
|
427
520
|
* @param {Object} event - Unsigned event object
|
|
428
|
-
* @param {Object} options - Publish options
|
|
429
|
-
* @param {boolean} options.waitForRelays - Wait for relay confirmation
|
|
430
|
-
* @param {boolean} options.debounce - Debounce rapid writes to same d-tag
|
|
521
|
+
* @param {Object} [options={}] - Publish options
|
|
522
|
+
* @param {boolean} [options.waitForRelays=false] - Wait for relay confirmation
|
|
523
|
+
* @param {boolean} [options.debounce=true] - Debounce rapid writes to same d-tag
|
|
431
524
|
* @returns {Promise<Object>} Signed event with relay publish results
|
|
525
|
+
* @example
|
|
526
|
+
* const result = await client.publish({
|
|
527
|
+
* kind: 30000,
|
|
528
|
+
* tags: [['d', 'mypath']],
|
|
529
|
+
* content: JSON.stringify({ name: 'Test' })
|
|
530
|
+
* });
|
|
432
531
|
*/
|
|
433
532
|
async publish(event, options = {}) {
|
|
434
533
|
// Ensure initialization is complete
|
|
@@ -590,14 +689,22 @@ export class NostrClient {
|
|
|
590
689
|
}
|
|
591
690
|
|
|
592
691
|
/**
|
|
593
|
-
* Query events from relays
|
|
594
|
-
*
|
|
692
|
+
* Query events from relays.
|
|
693
|
+
*
|
|
694
|
+
* Uses long-lived subscription for cache updates - avoids polling.
|
|
695
|
+
*
|
|
595
696
|
* @param {Object} filter - Nostr filter object
|
|
596
|
-
* @param {Object} options - Query options
|
|
597
|
-
* @param {number} options.timeout - Query timeout in ms (
|
|
598
|
-
* @param {boolean} options.localFirst - Return local cache immediately, refresh in background
|
|
599
|
-
* @param {boolean} options.forceRelay - Force relay query even if subscription cache is available
|
|
697
|
+
* @param {Object} [options={}] - Query options
|
|
698
|
+
* @param {number} [options.timeout=30000] - Query timeout in ms (set to 0 for no timeout)
|
|
699
|
+
* @param {boolean} [options.localFirst=true] - Return local cache immediately, refresh in background
|
|
700
|
+
* @param {boolean} [options.forceRelay=false] - Force relay query even if subscription cache is available
|
|
600
701
|
* @returns {Promise<Array>} Array of events
|
|
702
|
+
* @example
|
|
703
|
+
* const events = await client.query({
|
|
704
|
+
* kinds: [30000],
|
|
705
|
+
* authors: [client.publicKey],
|
|
706
|
+
* '#d': ['mypath']
|
|
707
|
+
* });
|
|
601
708
|
*/
|
|
602
709
|
async query(filter, options = {}) {
|
|
603
710
|
// Ensure initialization is complete
|
|
@@ -994,12 +1101,21 @@ export class NostrClient {
|
|
|
994
1101
|
}
|
|
995
1102
|
|
|
996
1103
|
/**
|
|
997
|
-
* Subscribe to events
|
|
998
|
-
*
|
|
1104
|
+
* Subscribe to events.
|
|
1105
|
+
*
|
|
1106
|
+
* Uses subscription deduplication to avoid creating multiple identical subscriptions.
|
|
1107
|
+
*
|
|
999
1108
|
* @param {Object} filter - Nostr filter object
|
|
1000
1109
|
* @param {Function} onEvent - Callback for each event
|
|
1001
|
-
* @param {Object} options - Subscription options
|
|
1002
|
-
* @
|
|
1110
|
+
* @param {Object} [options={}] - Subscription options
|
|
1111
|
+
* @param {Function} [options.onEOSE] - Callback when End Of Stored Events is received
|
|
1112
|
+
* @returns {Promise<Object>} Subscription object with unsubscribe method and id
|
|
1113
|
+
* @example
|
|
1114
|
+
* const sub = await client.subscribe(
|
|
1115
|
+
* { kinds: [30000], authors: [client.publicKey] },
|
|
1116
|
+
* (event) => console.log('Event:', event)
|
|
1117
|
+
* );
|
|
1118
|
+
* // Later: sub.unsubscribe();
|
|
1003
1119
|
*/
|
|
1004
1120
|
async subscribe(filter, onEvent, options = {}) {
|
|
1005
1121
|
// Ensure initialization is complete
|
|
@@ -1403,9 +1519,11 @@ export class NostrClient {
|
|
|
1403
1519
|
}
|
|
1404
1520
|
|
|
1405
1521
|
/**
|
|
1406
|
-
* Close all connections and subscriptions
|
|
1407
|
-
*
|
|
1408
|
-
* @param {
|
|
1522
|
+
* Close all connections and subscriptions.
|
|
1523
|
+
*
|
|
1524
|
+
* @param {Object} [options={}] - Close options
|
|
1525
|
+
* @param {boolean} [options.flush=true] - Flush pending writes before closing
|
|
1526
|
+
* @returns {Promise<void>}
|
|
1409
1527
|
*/
|
|
1410
1528
|
async close(options = {}) {
|
|
1411
1529
|
const shouldFlush = options.flush !== false;
|
|
@@ -1462,9 +1580,15 @@ export class NostrClient {
|
|
|
1462
1580
|
}
|
|
1463
1581
|
|
|
1464
1582
|
/**
|
|
1465
|
-
* Create NostrClient instance
|
|
1583
|
+
* Create NostrClient instance.
|
|
1584
|
+
*
|
|
1466
1585
|
* @param {Object} config - Configuration options
|
|
1467
1586
|
* @returns {NostrClient} Client instance
|
|
1587
|
+
* @example
|
|
1588
|
+
* const client = createClient({
|
|
1589
|
+
* relays: ['wss://relay.example.com'],
|
|
1590
|
+
* appName: 'myapp'
|
|
1591
|
+
* });
|
|
1468
1592
|
*/
|
|
1469
1593
|
export function createClient(config) {
|
|
1470
1594
|
return new NostrClient(config);
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Nostr Storage Wrapper
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview Nostr Storage Wrapper.
|
|
3
|
+
*
|
|
4
|
+
* Drop-in replacement for gun-wrapper.js providing the same API.
|
|
4
5
|
* Handles path construction and CRUD operations using Nostr relays
|
|
6
|
+
* for distributed P2P storage.
|
|
7
|
+
*
|
|
8
|
+
* @module storage/nostr-wrapper
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
import {
|
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OutboxQueue - Persistent queue for reliable relay delivery
|
|
2
|
+
* @fileoverview OutboxQueue - Persistent queue for reliable relay delivery.
|
|
3
3
|
*
|
|
4
4
|
* Implements guaranteed delivery with exponential backoff retry.
|
|
5
5
|
* Events are persisted to local storage and retried until delivered
|
|
6
6
|
* or max retries exceeded.
|
|
7
|
+
*
|
|
8
|
+
* @module storage/outbox-queue
|
|
7
9
|
*/
|
|
8
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Persistent queue for reliable event delivery to Nostr relays.
|
|
13
|
+
*
|
|
14
|
+
* Features:
|
|
15
|
+
* - Exponential backoff retry with jitter
|
|
16
|
+
* - Persistent storage across restarts
|
|
17
|
+
* - Automatic purging of old failed events
|
|
18
|
+
* - Queue statistics and monitoring
|
|
19
|
+
*
|
|
20
|
+
* @class OutboxQueue
|
|
21
|
+
* @example
|
|
22
|
+
* const queue = new OutboxQueue(storage, { maxRetries: 5 });
|
|
23
|
+
* await queue.enqueue(signedEvent, ['wss://relay1.com', 'wss://relay2.com']);
|
|
24
|
+
*/
|
|
9
25
|
export class OutboxQueue {
|
|
10
26
|
/**
|
|
27
|
+
* Create a new OutboxQueue.
|
|
28
|
+
*
|
|
11
29
|
* @param {Object} persistentStorage - Storage adapter (IndexedDB/FileSystem)
|
|
12
|
-
* @param {Object} options - Configuration options
|
|
13
|
-
* @param {number} options.maxRetries - Max retry attempts
|
|
14
|
-
* @param {number} options.baseDelay - Base delay in ms
|
|
15
|
-
* @param {number} options.maxDelay - Max delay cap in ms (
|
|
16
|
-
* @param {number} options.failedTTL - TTL for failed events in ms (
|
|
30
|
+
* @param {Object} [options={}] - Configuration options
|
|
31
|
+
* @param {number} [options.maxRetries=5] - Max retry attempts
|
|
32
|
+
* @param {number} [options.baseDelay=1000] - Base delay in ms
|
|
33
|
+
* @param {number} [options.maxDelay=60000] - Max delay cap in ms (1 minute)
|
|
34
|
+
* @param {number} [options.failedTTL=86400000] - TTL for failed events in ms (24 hours)
|
|
17
35
|
*/
|
|
18
36
|
constructor(persistentStorage, options = {}) {
|
|
19
37
|
this.storage = persistentStorage;
|
|
@@ -25,10 +43,11 @@ export class OutboxQueue {
|
|
|
25
43
|
}
|
|
26
44
|
|
|
27
45
|
/**
|
|
28
|
-
* Add an event to the outbox queue
|
|
46
|
+
* Add an event to the outbox queue.
|
|
47
|
+
*
|
|
29
48
|
* @param {Object} event - Signed Nostr event
|
|
30
49
|
* @param {string[]} relays - Target relay URLs
|
|
31
|
-
* @returns {Promise<Object>} Queue entry
|
|
50
|
+
* @returns {Promise<Object>} Queue entry with metadata
|
|
32
51
|
*/
|
|
33
52
|
async enqueue(event, relays) {
|
|
34
53
|
const entry = {
|
|
@@ -48,9 +67,13 @@ export class OutboxQueue {
|
|
|
48
67
|
}
|
|
49
68
|
|
|
50
69
|
/**
|
|
51
|
-
* Mark an event as sent
|
|
70
|
+
* Mark an event as sent.
|
|
71
|
+
*
|
|
72
|
+
* Removes from queue if at least one relay accepted, otherwise schedules retry.
|
|
73
|
+
*
|
|
52
74
|
* @param {string} eventId - Event ID
|
|
53
75
|
* @param {string[]} successfulRelays - Relays that accepted the event
|
|
76
|
+
* @returns {Promise<void>}
|
|
54
77
|
*/
|
|
55
78
|
async markSent(eventId, successfulRelays) {
|
|
56
79
|
const key = `${this.queuePrefix}${eventId}`;
|
|
@@ -67,8 +90,14 @@ export class OutboxQueue {
|
|
|
67
90
|
}
|
|
68
91
|
|
|
69
92
|
/**
|
|
70
|
-
* Schedule a retry with exponential backoff
|
|
93
|
+
* Schedule a retry with exponential backoff.
|
|
94
|
+
*
|
|
95
|
+
* Uses exponential backoff with jitter. Marks as failed if max retries exceeded.
|
|
96
|
+
*
|
|
71
97
|
* @private
|
|
98
|
+
* @param {string} key - Storage key
|
|
99
|
+
* @param {Object} entry - Queue entry
|
|
100
|
+
* @returns {Promise<void>}
|
|
72
101
|
*/
|
|
73
102
|
async _scheduleRetry(key, entry) {
|
|
74
103
|
entry.retries++;
|
|
@@ -90,7 +119,8 @@ export class OutboxQueue {
|
|
|
90
119
|
}
|
|
91
120
|
|
|
92
121
|
/**
|
|
93
|
-
* Get all pending events ready for retry
|
|
122
|
+
* Get all pending events ready for retry.
|
|
123
|
+
*
|
|
94
124
|
* @returns {Promise<Object[]>} Pending queue entries sorted by creation time
|
|
95
125
|
*/
|
|
96
126
|
async getPendingEvents() {
|
|
@@ -103,7 +133,8 @@ export class OutboxQueue {
|
|
|
103
133
|
}
|
|
104
134
|
|
|
105
135
|
/**
|
|
106
|
-
* Get all failed events (exceeded max retries)
|
|
136
|
+
* Get all failed events (exceeded max retries).
|
|
137
|
+
*
|
|
107
138
|
* @returns {Promise<Object[]>} Failed queue entries
|
|
108
139
|
*/
|
|
109
140
|
async getFailedEvents() {
|
|
@@ -112,8 +143,9 @@ export class OutboxQueue {
|
|
|
112
143
|
}
|
|
113
144
|
|
|
114
145
|
/**
|
|
115
|
-
* Get queue statistics
|
|
116
|
-
*
|
|
146
|
+
* Get queue statistics.
|
|
147
|
+
*
|
|
148
|
+
* @returns {Promise<Object>} Stats object with total, pending, failed counts and oldest timestamps
|
|
117
149
|
*/
|
|
118
150
|
async getStats() {
|
|
119
151
|
const allEntries = await this.storage.getAll(this.queuePrefix);
|
|
@@ -146,8 +178,9 @@ export class OutboxQueue {
|
|
|
146
178
|
}
|
|
147
179
|
|
|
148
180
|
/**
|
|
149
|
-
* Purge failed events older than maxAge
|
|
150
|
-
*
|
|
181
|
+
* Purge failed events older than maxAge.
|
|
182
|
+
*
|
|
183
|
+
* @param {number} [maxAge] - Max age in ms (defaults to failedTTL)
|
|
151
184
|
* @returns {Promise<number>} Number of entries purged
|
|
152
185
|
*/
|
|
153
186
|
async purgeOldFailed(maxAge = this.failedTTL) {
|
|
@@ -166,7 +199,8 @@ export class OutboxQueue {
|
|
|
166
199
|
}
|
|
167
200
|
|
|
168
201
|
/**
|
|
169
|
-
* Clear all entries from the queue
|
|
202
|
+
* Clear all entries from the queue.
|
|
203
|
+
*
|
|
170
204
|
* @returns {Promise<number>} Number of entries cleared
|
|
171
205
|
*/
|
|
172
206
|
async clear() {
|
|
@@ -184,7 +218,10 @@ export class OutboxQueue {
|
|
|
184
218
|
}
|
|
185
219
|
|
|
186
220
|
/**
|
|
187
|
-
* Manually retry a failed event
|
|
221
|
+
* Manually retry a failed event.
|
|
222
|
+
*
|
|
223
|
+
* Resets retry counter and status to allow manual retry of a failed event.
|
|
224
|
+
*
|
|
188
225
|
* @param {string} eventId - Event ID to retry
|
|
189
226
|
* @returns {Promise<Object|null>} Updated entry or null if not found
|
|
190
227
|
*/
|
|
@@ -1,69 +1,102 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Persistent Storage Interface
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview Persistent Storage Interface.
|
|
3
|
+
*
|
|
4
|
+
* Provides a unified API for local persistence across browser and Node.js.
|
|
5
|
+
* Automatically selects the appropriate storage backend:
|
|
6
|
+
* - IndexedDB in browsers
|
|
7
|
+
* - Filesystem in Node.js
|
|
8
|
+
* - Memory fallback if neither available
|
|
9
|
+
*
|
|
10
|
+
* @module storage/persistent-storage
|
|
4
11
|
*/
|
|
5
12
|
|
|
6
13
|
/**
|
|
7
|
-
* Base class for persistent storage adapters
|
|
14
|
+
* Base class for persistent storage adapters.
|
|
15
|
+
*
|
|
16
|
+
* All storage implementations must extend this class and implement all methods.
|
|
17
|
+
*
|
|
18
|
+
* @class PersistentStorage
|
|
19
|
+
* @abstract
|
|
8
20
|
*/
|
|
9
21
|
class PersistentStorage {
|
|
10
22
|
/**
|
|
11
|
-
* Initialize storage
|
|
23
|
+
* Initialize storage with namespace.
|
|
24
|
+
*
|
|
25
|
+
* @abstract
|
|
12
26
|
* @param {string} namespace - Storage namespace (appName)
|
|
13
27
|
* @returns {Promise<void>}
|
|
28
|
+
* @throws {Error} Must be implemented by subclass
|
|
14
29
|
*/
|
|
15
30
|
async init(namespace) {
|
|
16
31
|
throw new Error('init() must be implemented by subclass');
|
|
17
32
|
}
|
|
18
33
|
|
|
19
34
|
/**
|
|
20
|
-
* Store event
|
|
35
|
+
* Store event.
|
|
36
|
+
*
|
|
37
|
+
* @abstract
|
|
21
38
|
* @param {string} key - Event ID or d-tag
|
|
22
39
|
* @param {Object} event - Nostr event
|
|
23
40
|
* @returns {Promise<void>}
|
|
41
|
+
* @throws {Error} Must be implemented by subclass
|
|
24
42
|
*/
|
|
25
43
|
async put(key, event) {
|
|
26
44
|
throw new Error('put() must be implemented by subclass');
|
|
27
45
|
}
|
|
28
46
|
|
|
29
47
|
/**
|
|
30
|
-
* Retrieve event
|
|
48
|
+
* Retrieve event.
|
|
49
|
+
*
|
|
50
|
+
* @abstract
|
|
31
51
|
* @param {string} key - Event ID or d-tag
|
|
32
52
|
* @returns {Promise<Object|null>} Event or null
|
|
53
|
+
* @throws {Error} Must be implemented by subclass
|
|
33
54
|
*/
|
|
34
55
|
async get(key) {
|
|
35
56
|
throw new Error('get() must be implemented by subclass');
|
|
36
57
|
}
|
|
37
58
|
|
|
38
59
|
/**
|
|
39
|
-
* Get all events matching prefix
|
|
60
|
+
* Get all events matching prefix.
|
|
61
|
+
*
|
|
62
|
+
* @abstract
|
|
40
63
|
* @param {string} prefix - Key prefix
|
|
41
64
|
* @returns {Promise<any[]>} Array of events
|
|
65
|
+
* @throws {Error} Must be implemented by subclass
|
|
42
66
|
*/
|
|
43
67
|
async getAll(prefix) {
|
|
44
68
|
throw new Error('getAll() must be implemented by subclass');
|
|
45
69
|
}
|
|
46
70
|
|
|
47
71
|
/**
|
|
48
|
-
* Delete event
|
|
72
|
+
* Delete event.
|
|
73
|
+
*
|
|
74
|
+
* @abstract
|
|
49
75
|
* @param {string} key - Event ID or d-tag
|
|
50
76
|
* @returns {Promise<void>}
|
|
77
|
+
* @throws {Error} Must be implemented by subclass
|
|
51
78
|
*/
|
|
52
79
|
async delete(key) {
|
|
53
80
|
throw new Error('delete() must be implemented by subclass');
|
|
54
81
|
}
|
|
55
82
|
|
|
56
83
|
/**
|
|
57
|
-
* Clear all data in namespace
|
|
84
|
+
* Clear all data in namespace.
|
|
85
|
+
*
|
|
86
|
+
* @abstract
|
|
58
87
|
* @returns {Promise<void>}
|
|
88
|
+
* @throws {Error} Must be implemented by subclass
|
|
59
89
|
*/
|
|
60
90
|
async clear() {
|
|
61
91
|
throw new Error('clear() must be implemented by subclass');
|
|
62
92
|
}
|
|
63
93
|
|
|
64
94
|
/**
|
|
65
|
-
* Close storage
|
|
95
|
+
* Close storage connection.
|
|
96
|
+
*
|
|
97
|
+
* @abstract
|
|
66
98
|
* @returns {Promise<void>}
|
|
99
|
+
* @throws {Error} Must be implemented by subclass
|
|
67
100
|
*/
|
|
68
101
|
async close() {
|
|
69
102
|
throw new Error('close() must be implemented by subclass');
|
|
@@ -71,10 +104,20 @@ class PersistentStorage {
|
|
|
71
104
|
}
|
|
72
105
|
|
|
73
106
|
/**
|
|
74
|
-
* Detect environment and return appropriate storage adapter
|
|
107
|
+
* Detect environment and return appropriate storage adapter.
|
|
108
|
+
*
|
|
109
|
+
* Automatically creates:
|
|
110
|
+
* - IndexedDBStorage in browsers
|
|
111
|
+
* - FileSystemStorage in Node.js
|
|
112
|
+
* - MemoryStorage as fallback
|
|
113
|
+
*
|
|
75
114
|
* @param {string} namespace - Storage namespace
|
|
76
|
-
* @param {Object} options - Storage options
|
|
77
|
-
* @
|
|
115
|
+
* @param {Object} [options={}] - Storage options
|
|
116
|
+
* @param {string} [options.dataDir] - Custom data directory (Node.js only)
|
|
117
|
+
* @returns {Promise<PersistentStorage>} Initialized storage instance
|
|
118
|
+
* @example
|
|
119
|
+
* const storage = await createPersistentStorage('myapp');
|
|
120
|
+
* await storage.put('key1', { id: 'event1', data: 'test' });
|
|
78
121
|
*/
|
|
79
122
|
async function createPersistentStorage(namespace, options = {}) {
|
|
80
123
|
// Detect environment
|