holosphere 2.0.0-alpha7 → 2.0.0-alpha9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +446 -0
- package/FEATURES.md +431 -0
- package/LICENSE +29 -166
- package/LICENSE-AGPL.md +180 -0
- package/dist/cdn/holosphere.min.js +55 -0
- package/dist/cdn/holosphere.min.js.map +1 -0
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +1 -1
- package/dist/{index-C-IlLYlk.cjs → index-DDGt_V9o.cjs} +2 -2
- package/dist/{index-C-IlLYlk.cjs.map → index-DDGt_V9o.cjs.map} +1 -1
- package/dist/{index-d6f4RJBM.js → index-DJXftyvB.js} +2253 -387
- package/dist/index-DJXftyvB.js.map +1 -0
- package/dist/index-DMbdcMtK.cjs +18 -0
- package/dist/index-DMbdcMtK.cjs.map +1 -0
- package/dist/{index-jmTHEbR2.js → index-DeZ1xz_s.js} +2 -2
- package/dist/{index-jmTHEbR2.js.map → index-DeZ1xz_s.js.map} +1 -1
- package/dist/{indexeddb-storage-D8kOl0oK.js → indexeddb-storage-BFt6hMeF.js} +48 -4
- package/dist/indexeddb-storage-BFt6hMeF.js.map +1 -0
- package/dist/{indexeddb-storage-a8GipaDr.cjs → indexeddb-storage-BK5tv4Sh.cjs} +2 -2
- package/dist/indexeddb-storage-BK5tv4Sh.cjs.map +1 -0
- package/dist/{memory-storage-DBQK622V.js → memory-storage-C9HuoL2E.js} +44 -4
- package/dist/memory-storage-C9HuoL2E.js.map +1 -0
- package/dist/{memory-storage-gfRovk2O.cjs → memory-storage-Dao7jfYG.cjs} +2 -2
- package/dist/memory-storage-Dao7jfYG.cjs.map +1 -0
- package/dist/{secp256k1-BCAPF45D.cjs → secp256k1-BbKzbLtD.cjs} +2 -2
- package/dist/{secp256k1-BCAPF45D.cjs.map → secp256k1-BbKzbLtD.cjs.map} +1 -1
- package/dist/{secp256k1-DYm_CMqW.js → secp256k1-CreY7Pcl.js} +2 -2
- package/dist/{secp256k1-DYm_CMqW.js.map → secp256k1-CreY7Pcl.js.map} +1 -1
- package/docs/api/ai_aggregation.js.html +333 -0
- package/docs/api/ai_breakdown.js.html +524 -0
- package/docs/api/ai_classifier.js.html +231 -0
- package/docs/api/ai_council.js.html +246 -0
- package/docs/api/ai_embeddings.js.html +304 -0
- package/docs/api/ai_federation-ai.js.html +338 -0
- package/docs/api/ai_h3-ai.js.html +970 -0
- package/docs/api/ai_index.js.html +124 -0
- package/docs/api/ai_json-ops.js.html +241 -0
- package/docs/api/ai_llm-service.js.html +239 -0
- package/docs/api/ai_nl-query.js.html +236 -0
- package/docs/api/ai_relationships.js.html +367 -0
- package/docs/api/ai_schema-extractor.js.html +235 -0
- package/docs/api/ai_spatial.js.html +307 -0
- package/docs/api/ai_tts.js.html +214 -0
- package/docs/api/content_social-protocols.js.html +180 -0
- package/docs/api/core_holosphere.js.html +757 -0
- package/docs/api/crypto_nostr-utils.js.html +306 -0
- package/docs/api/crypto_secp256k1.js.html +267 -0
- package/docs/api/data/search.json +1 -0
- package/docs/api/federation_discovery.js.html +337 -0
- package/docs/api/federation_handshake.js.html +478 -0
- package/docs/api/federation_hologram.js.html +1053 -0
- package/docs/api/federation_registry.js.html +389 -0
- package/docs/api/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/api/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/api/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/api/global.html +3 -0
- package/docs/api/hierarchical_upcast.js.html +128 -0
- package/docs/api/index.html +265 -0
- package/docs/api/index.js.html +1868 -0
- package/docs/api/lib_ai-methods.js.html +660 -0
- package/docs/api/lib_contract-methods.js.html +445 -0
- package/docs/api/lib_errors.js.html +56 -0
- package/docs/api/lib_federation-methods.js.html +348 -0
- package/docs/api/lib_index.js.html +33 -0
- package/docs/api/module-ai.html +5 -0
- package/docs/api/module-ai_aggregation-SmartAggregation.html +6 -0
- package/docs/api/module-ai_aggregation.SmartAggregation.html +3 -0
- package/docs/api/module-ai_aggregation.html +3 -0
- package/docs/api/module-ai_breakdown-TaskBreakdown.html +5 -0
- package/docs/api/module-ai_breakdown.TaskBreakdown.html +3 -0
- package/docs/api/module-ai_breakdown.html +3 -0
- package/docs/api/module-ai_classifier-Classifier.html +6 -0
- package/docs/api/module-ai_classifier.Classifier.html +3 -0
- package/docs/api/module-ai_classifier.html +3 -0
- package/docs/api/module-ai_council-Council.html +6 -0
- package/docs/api/module-ai_council.Council.html +3 -0
- package/docs/api/module-ai_council.html +3 -0
- package/docs/api/module-ai_embeddings-Embeddings.html +5 -0
- package/docs/api/module-ai_embeddings.Embeddings.html +3 -0
- package/docs/api/module-ai_embeddings.html +3 -0
- package/docs/api/module-ai_federation-ai-FederationAdvisor.html +6 -0
- package/docs/api/module-ai_federation-ai.FederationAdvisor.html +3 -0
- package/docs/api/module-ai_federation-ai.html +3 -0
- package/docs/api/module-ai_h3-ai-H3AI.html +6 -0
- package/docs/api/module-ai_h3-ai.H3AI.html +3 -0
- package/docs/api/module-ai_h3-ai.html +3 -0
- package/docs/api/module-ai_json-ops-JSONOps.html +5 -0
- package/docs/api/module-ai_json-ops.JSONOps.html +3 -0
- package/docs/api/module-ai_json-ops.html +3 -0
- package/docs/api/module-ai_llm-service-LLMService.html +5 -0
- package/docs/api/module-ai_llm-service.LLMService.html +3 -0
- package/docs/api/module-ai_llm-service.html +3 -0
- package/docs/api/module-ai_nl-query-NLQuery.html +5 -0
- package/docs/api/module-ai_nl-query.NLQuery.html +3 -0
- package/docs/api/module-ai_nl-query.html +3 -0
- package/docs/api/module-ai_relationships-RelationshipDiscovery.html +6 -0
- package/docs/api/module-ai_relationships.RelationshipDiscovery.html +3 -0
- package/docs/api/module-ai_relationships.html +3 -0
- package/docs/api/module-ai_schema-extractor-SchemaExtractor.html +5 -0
- package/docs/api/module-ai_schema-extractor.SchemaExtractor.html +3 -0
- package/docs/api/module-ai_schema-extractor.html +3 -0
- package/docs/api/module-ai_spatial-SpatialAnalysis.html +6 -0
- package/docs/api/module-ai_spatial.SpatialAnalysis.html +3 -0
- package/docs/api/module-ai_spatial.html +3 -0
- package/docs/api/module-ai_tts-TTS.html +5 -0
- package/docs/api/module-ai_tts.TTS.html +3 -0
- package/docs/api/module-ai_tts.html +3 -0
- package/docs/api/module-content_social-protocols.html +3 -0
- package/docs/api/module-core_holosphere-HoloSphere.html +6 -0
- package/docs/api/module-core_holosphere.HoloSphere.html +3 -0
- package/docs/api/module-core_holosphere.html +3 -0
- package/docs/api/module-crypto_nostr-utils.html +3 -0
- package/docs/api/module-crypto_secp256k1.html +3 -0
- package/docs/api/module-federation_hologram.html +3 -0
- package/docs/api/module-hierarchical_upcast.html +3 -0
- package/docs/api/module-holosphere-HoloSphereBase.html +3 -0
- package/docs/api/module-holosphere.html +3 -0
- package/docs/api/module-lib_ai-methods.html +3 -0
- package/docs/api/module-lib_contract-methods.html +3 -0
- package/docs/api/module-lib_errors-AuthorizationError.html +3 -0
- package/docs/api/module-lib_errors-ValidationError.html +3 -0
- package/docs/api/module-lib_errors.AuthorizationError.html +3 -0
- package/docs/api/module-lib_errors.ValidationError.html +3 -0
- package/docs/api/module-lib_errors.html +3 -0
- package/docs/api/module-lib_federation-methods.html +3 -0
- package/docs/api/module-lib_index.html +3 -0
- package/docs/api/module-schema_validator-ValidationError.html +3 -0
- package/docs/api/module-schema_validator.ValidationError.html +3 -0
- package/docs/api/module-schema_validator.html +3 -0
- package/docs/api/module-spatial_h3-operations.html +4 -0
- package/docs/api/module-storage_backend-factory.BackendFactory.html +3 -0
- package/docs/api/module-storage_backend-factory.html +3 -0
- package/docs/api/module-storage_backend-interface-StorageBackend.html +3 -0
- package/docs/api/module-storage_backend-interface.StorageBackend.html +3 -0
- package/docs/api/module-storage_backend-interface.html +3 -0
- package/docs/api/module-storage_backends_activitypub-backend-ActivityPubBackend.html +7 -0
- package/docs/api/module-storage_backends_activitypub-backend.ActivityPubBackend.html +3 -0
- package/docs/api/module-storage_backends_activitypub-backend.html +3 -0
- package/docs/api/module-storage_backends_activitypub_server-ActivityPubServer.html +8 -0
- package/docs/api/module-storage_backends_activitypub_server.ActivityPubServer.html +3 -0
- package/docs/api/module-storage_backends_activitypub_server.html +3 -0
- package/docs/api/module-storage_backends_gundb-backend-GunDBBackend.html +7 -0
- package/docs/api/module-storage_backends_gundb-backend.GunDBBackend.html +3 -0
- package/docs/api/module-storage_backends_gundb-backend.html +3 -0
- package/docs/api/module-storage_backends_nostr-backend-NostrBackend.html +8 -0
- package/docs/api/module-storage_backends_nostr-backend.NostrBackend.html +3 -0
- package/docs/api/module-storage_backends_nostr-backend.html +3 -0
- package/docs/api/module-storage_filesystem-storage-FileSystemStorage.html +5 -0
- package/docs/api/module-storage_filesystem-storage-browser-FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage-browser.FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage-browser.html +3 -0
- package/docs/api/module-storage_filesystem-storage.FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage.html +3 -0
- package/docs/api/module-storage_global-tables.html +3 -0
- package/docs/api/module-storage_gun-async.html +3 -0
- package/docs/api/module-storage_gun-auth-GunAuth.html +5 -0
- package/docs/api/module-storage_gun-auth.GunAuth.html +3 -0
- package/docs/api/module-storage_gun-auth.html +3 -0
- package/docs/api/module-storage_gun-federation.html +3 -0
- package/docs/api/module-storage_gun-references-GunReferenceHandler.html +5 -0
- package/docs/api/module-storage_gun-references.GunReferenceHandler.html +3 -0
- package/docs/api/module-storage_gun-references.html +3 -0
- package/docs/api/module-storage_gun-schema-GunSchemaValidator.html +5 -0
- package/docs/api/module-storage_gun-schema.GunSchemaValidator.html +3 -0
- package/docs/api/module-storage_gun-schema.html +3 -0
- package/docs/api/module-storage_gun-wrapper.html +11 -0
- package/docs/api/module-storage_indexeddb-storage-IndexedDBStorage.html +5 -0
- package/docs/api/module-storage_indexeddb-storage.IndexedDBStorage.html +3 -0
- package/docs/api/module-storage_indexeddb-storage.html +3 -0
- package/docs/api/module-storage_key-storage-simple.html +3 -0
- package/docs/api/module-storage_key-storage.html +4 -0
- package/docs/api/module-storage_memory-storage-MemoryStorage.html +5 -0
- package/docs/api/module-storage_memory-storage.MemoryStorage.html +3 -0
- package/docs/api/module-storage_memory-storage.html +3 -0
- package/docs/api/module-storage_migration-MigrationTool.html +6 -0
- package/docs/api/module-storage_migration.MigrationTool.html +3 -0
- package/docs/api/module-storage_migration.html +3 -0
- package/docs/api/module-storage_nostr-async.html +18 -0
- package/docs/api/module-storage_nostr-client-LRUCache.html +3 -0
- package/docs/api/module-storage_nostr-client-NostrClient.html +7 -0
- package/docs/api/module-storage_nostr-client.NostrClient.html +15 -0
- package/docs/api/module-storage_nostr-client.html +6 -0
- package/docs/api/module-storage_nostr-wrapper.html +3 -0
- package/docs/api/module-storage_outbox-queue-OutboxQueue.html +4 -0
- package/docs/api/module-storage_outbox-queue.OutboxQueue.html +3 -0
- package/docs/api/module-storage_outbox-queue.html +3 -0
- package/docs/api/module-storage_persistent-storage-PersistentStorage.html +3 -0
- package/docs/api/module-storage_persistent-storage.html +4 -0
- package/docs/api/module-storage_sync-service-SyncService.html +5 -0
- package/docs/api/module-storage_sync-service.SyncService.html +3 -0
- package/docs/api/module-storage_sync-service.html +3 -0
- package/docs/api/module-storage_unified-storage.html +3 -0
- package/docs/api/module-subscriptions_manager.SubscriptionRegistry.html +3 -0
- package/docs/api/module-subscriptions_manager.html +3 -0
- package/docs/api/schema_validator.js.html +113 -0
- package/docs/api/scripts/core.js +726 -0
- package/docs/api/scripts/core.min.js +23 -0
- package/docs/api/scripts/resize.js +90 -0
- package/docs/api/scripts/search.js +265 -0
- package/docs/api/scripts/search.min.js +6 -0
- package/docs/api/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/api/scripts/third-party/fuse.js +9 -0
- package/docs/api/scripts/third-party/hljs-line-num-original.js +369 -0
- package/docs/api/scripts/third-party/hljs-line-num.js +1 -0
- package/docs/api/scripts/third-party/hljs-original.js +5171 -0
- package/docs/api/scripts/third-party/hljs.js +1 -0
- package/docs/api/scripts/third-party/popper.js +5 -0
- package/docs/api/scripts/third-party/tippy.js +1 -0
- package/docs/api/scripts/third-party/tocbot.js +672 -0
- package/docs/api/scripts/third-party/tocbot.min.js +1 -0
- package/docs/api/spatial_h3-operations.js.html +129 -0
- package/docs/api/storage_backend-factory.js.html +133 -0
- package/docs/api/storage_backend-interface.js.html +164 -0
- package/docs/api/storage_backends_activitypub-backend.js.html +298 -0
- package/docs/api/storage_backends_activitypub_server.js.html +678 -0
- package/docs/api/storage_backends_gundb-backend.js.html +878 -0
- package/docs/api/storage_backends_nostr-backend.js.html +254 -0
- package/docs/api/storage_filesystem-storage-browser.js.html +83 -0
- package/docs/api/storage_filesystem-storage.js.html +207 -0
- package/docs/api/storage_global-tables.js.html +116 -0
- package/docs/api/storage_gun-async.js.html +344 -0
- package/docs/api/storage_gun-auth.js.html +376 -0
- package/docs/api/storage_gun-federation.js.html +788 -0
- package/docs/api/storage_gun-references.js.html +212 -0
- package/docs/api/storage_gun-schema.js.html +309 -0
- package/docs/api/storage_gun-wrapper.js.html +645 -0
- package/docs/api/storage_indexeddb-storage.js.html +224 -0
- package/docs/api/storage_key-storage-simple.js.html +102 -0
- package/docs/api/storage_key-storage.js.html +171 -0
- package/docs/api/storage_memory-storage.js.html +128 -0
- package/docs/api/storage_migration.js.html +354 -0
- package/docs/api/storage_nostr-async.js.html +1076 -0
- package/docs/api/storage_nostr-client.js.html +1598 -0
- package/docs/api/storage_nostr-wrapper.js.html +218 -0
- package/docs/api/storage_outbox-queue.js.html +248 -0
- package/docs/api/storage_persistent-storage.js.html +160 -0
- package/docs/api/storage_sync-service.js.html +201 -0
- package/docs/api/storage_unified-storage.js.html +157 -0
- package/docs/api/styles/clean-jsdoc-theme-base.css +1159 -0
- package/docs/api/styles/clean-jsdoc-theme-dark.css +412 -0
- package/docs/api/styles/clean-jsdoc-theme-light.css +482 -0
- package/docs/api/styles/clean-jsdoc-theme-scrollbar.css +30 -0
- package/docs/api/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
- package/docs/api/styles/clean-jsdoc-theme.min.css +1 -0
- package/docs/api/subscriptions_manager.js.html +162 -0
- package/examples/holosphere-widget.js +1242 -0
- package/examples/widget-demo.html +274 -0
- package/examples/widget.html +703 -0
- package/jsdoc.json +26 -0
- package/package.json +16 -3
- package/src/ai/aggregation.js +13 -2
- package/src/ai/breakdown.js +12 -2
- package/src/ai/classifier.js +14 -3
- package/src/ai/council.js +22 -7
- package/src/ai/embeddings.js +37 -15
- package/src/ai/federation-ai.js +13 -2
- package/src/ai/h3-ai.js +14 -2
- package/src/ai/index.js +16 -7
- package/src/ai/json-ops.js +18 -5
- package/src/ai/llm-service.js +62 -31
- package/src/ai/nl-query.js +12 -2
- package/src/ai/relationships.js +13 -2
- package/src/ai/schema-extractor.js +24 -10
- package/src/ai/spatial.js +13 -2
- package/src/ai/tts.js +25 -8
- package/src/cdn-entry.js +22 -0
- package/src/content/social-protocols.js +34 -25
- package/src/contracts/chain-manager.js +68 -40
- package/src/contracts/deployer.js +70 -42
- package/src/contracts/event-listener.js +61 -29
- package/src/contracts/holon-contracts.js +46 -31
- package/src/contracts/index.js +5 -6
- package/src/contracts/networks.js +19 -14
- package/src/contracts/operations.js +58 -41
- package/src/contracts/queries.js +70 -21
- package/src/core/holosphere.js +37 -8
- package/src/crypto/nostr-utils.js +105 -65
- package/src/crypto/secp256k1.js +7 -2
- package/src/federation/handshake.js +23 -11
- package/src/federation/hologram.js +9 -1
- package/src/hierarchical/upcast.js +34 -20
- package/src/index.js +671 -7
- package/src/lib/ai-methods.js +352 -3
- package/src/lib/contract-methods.js +152 -3
- package/src/lib/errors.js +31 -1
- package/src/lib/federation-methods.js +110 -3
- package/src/lib/index.js +9 -5
- package/src/schema/validator.js +22 -3
- package/src/spatial/h3-operations.js +17 -1
- package/src/storage/backend-factory.js +7 -2
- package/src/storage/backend-interface.js +21 -2
- package/src/storage/backends/activitypub/server.js +25 -3
- package/src/storage/backends/activitypub-backend.js +25 -2
- package/src/storage/backends/gundb-backend.js +322 -11
- package/src/storage/backends/nostr-backend.js +116 -1
- package/src/storage/filesystem-storage-browser.js +42 -2
- package/src/storage/filesystem-storage.js +72 -5
- package/src/storage/global-tables.js +7 -2
- package/src/storage/gun-async.js +20 -11
- package/src/storage/gun-auth.js +15 -4
- package/src/storage/gun-federation.js +14 -5
- package/src/storage/gun-references.js +16 -5
- package/src/storage/gun-schema.js +25 -10
- package/src/storage/gun-wrapper.js +160 -49
- package/src/storage/indexeddb-storage.js +65 -4
- package/src/storage/key-storage-simple.js +32 -9
- package/src/storage/key-storage.js +45 -13
- package/src/storage/memory-storage.js +65 -4
- package/src/storage/migration.js +20 -7
- package/src/storage/nostr-async.js +195 -90
- package/src/storage/nostr-client.js +173 -49
- package/src/storage/nostr-wrapper.js +6 -2
- package/src/storage/outbox-queue.js +55 -18
- package/src/storage/persistent-storage.js +56 -13
- package/src/storage/sync-service.js +51 -17
- package/src/storage/unified-storage.js +38 -3
- package/src/subscriptions/manager.js +33 -16
- package/vite.config.cdn.js +60 -0
- package/dist/index-Bvwyvd0T.cjs +0 -5
- package/dist/index-Bvwyvd0T.cjs.map +0 -1
- package/dist/index-d6f4RJBM.js.map +0 -1
- package/dist/indexeddb-storage-D8kOl0oK.js.map +0 -1
- package/dist/indexeddb-storage-a8GipaDr.cjs.map +0 -1
- package/dist/memory-storage-DBQK622V.js.map +0 -1
- package/dist/memory-storage-gfRovk2O.cjs.map +0 -1
- /package/{cleanup-test-data.js → scripts/cleanup-test-data.js} +0 -0
- /package/{test-ai-real-api.js → scripts/test-ai-real-api.js} +0 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GunDB Storage Wrapper with radisk persistence
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @fileoverview GunDB Storage Wrapper with radisk persistence.
|
|
3
|
+
*
|
|
4
|
+
* Handles path construction and CRUD operations for GunDB storage backend.
|
|
5
|
+
* Note: GunDB doesn't handle nested objects well, so we store data as JSON strings.
|
|
6
|
+
* Provides both holon-specific paths and global table operations.
|
|
7
|
+
*
|
|
8
|
+
* @module storage/gun-wrapper
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
import { gunPromise, gunPut, gunCollect } from './gun-async.js';
|
|
@@ -11,12 +15,16 @@ import { gunPromise, gunPut, gunCollect } from './gun-async.js';
|
|
|
11
15
|
// ============================================================================
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
|
-
* Build Gun path from components
|
|
18
|
+
* Build Gun path from components.
|
|
19
|
+
*
|
|
15
20
|
* @param {string} appname - Application namespace
|
|
16
21
|
* @param {string} holon - Holon ID (H3 or URI)
|
|
17
22
|
* @param {string} lens - Lens name
|
|
18
|
-
* @param {string} key - Data key (optional)
|
|
23
|
+
* @param {string} [key=null] - Data key (optional)
|
|
19
24
|
* @returns {string} Gun path
|
|
25
|
+
* @example
|
|
26
|
+
* const path = buildPath('myapp', 'holon123', 'items', 'item1');
|
|
27
|
+
* // Returns: 'myapp/holon123/items/item1'
|
|
20
28
|
*/
|
|
21
29
|
export function buildPath(appname, holon, lens, key = null) {
|
|
22
30
|
// Encode components to handle special characters
|
|
@@ -31,11 +39,15 @@ export function buildPath(appname, holon, lens, key = null) {
|
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
/**
|
|
34
|
-
* Build Gun path for global tables (app-wide data not tied to holons)
|
|
42
|
+
* Build Gun path for global tables (app-wide data not tied to holons).
|
|
43
|
+
*
|
|
35
44
|
* @param {string} appname - Application namespace
|
|
36
45
|
* @param {string} tableName - Global table name (e.g., 'schemas', 'federation')
|
|
37
|
-
* @param {string} key - Data key (optional)
|
|
46
|
+
* @param {string} [key=null] - Data key (optional)
|
|
38
47
|
* @returns {string} Gun path
|
|
48
|
+
* @example
|
|
49
|
+
* const path = buildGlobalPath('myapp', 'schemas', 'user');
|
|
50
|
+
* // Returns: 'myapp/schemas/user'
|
|
39
51
|
*/
|
|
40
52
|
export function buildGlobalPath(appname, tableName, key = null) {
|
|
41
53
|
const encodedTable = encodePathComponent(tableName);
|
|
@@ -47,33 +59,63 @@ export function buildGlobalPath(appname, tableName, key = null) {
|
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
/**
|
|
50
|
-
* Encode path component to handle special characters
|
|
62
|
+
* Encode path component to handle special characters.
|
|
63
|
+
*
|
|
51
64
|
* @private
|
|
65
|
+
* @param {string} component - Component to encode
|
|
66
|
+
* @returns {string} Encoded component
|
|
52
67
|
*/
|
|
53
68
|
function encodePathComponent(component) {
|
|
54
69
|
return encodeURIComponent(component).replace(/%2F/g, '/');
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* Gun
|
|
61
|
-
*
|
|
73
|
+
* Navigate to a Gun path using chained .get() calls.
|
|
74
|
+
*
|
|
75
|
+
* Gun treats 'a/b/c' as a literal key, not a path.
|
|
76
|
+
* This function splits the path and chains .get() calls properly.
|
|
77
|
+
*
|
|
62
78
|
* @private
|
|
79
|
+
* @param {Object} gun - Gun instance
|
|
80
|
+
* @param {string} path - Path string like "appname/holon/lens/key"
|
|
81
|
+
* @returns {Object} Gun chain reference at the path
|
|
82
|
+
*/
|
|
83
|
+
function getGunPath(gun, path) {
|
|
84
|
+
const parts = path.split('/').filter(p => p.length > 0);
|
|
85
|
+
let ref = gun;
|
|
86
|
+
for (const part of parts) {
|
|
87
|
+
ref = ref.get(part);
|
|
88
|
+
}
|
|
89
|
+
return ref;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Serialize data for GunDB storage.
|
|
94
|
+
*
|
|
95
|
+
* Stores data as raw JSON string for compatibility with holosphere original.
|
|
96
|
+
* This matches the format used in holosphere v1 for better interoperability.
|
|
97
|
+
*
|
|
98
|
+
* @private
|
|
99
|
+
* @param {Object} data - Data to serialize
|
|
100
|
+
* @returns {string} JSON string
|
|
63
101
|
*/
|
|
64
102
|
function serializeForGun(data) {
|
|
65
|
-
return
|
|
103
|
+
return JSON.stringify(data);
|
|
66
104
|
}
|
|
67
105
|
|
|
68
106
|
/**
|
|
69
|
-
* Deserialize data from GunDB storage
|
|
107
|
+
* Deserialize data from GunDB storage.
|
|
108
|
+
*
|
|
70
109
|
* Handles multiple formats:
|
|
71
110
|
* - Direct JSON string (holosphere original - now default)
|
|
72
111
|
* - _json wrapped format (holosphere2 legacy)
|
|
73
112
|
* - Gun internal references (_["#"])
|
|
74
113
|
* - Gun node data (_[">"])
|
|
75
114
|
* - Plain objects
|
|
115
|
+
*
|
|
76
116
|
* @private
|
|
117
|
+
* @param {*} data - Raw data from Gun
|
|
118
|
+
* @returns {Object|null} Parsed data or null
|
|
77
119
|
*/
|
|
78
120
|
function deserializeFromGun(data) {
|
|
79
121
|
if (!data) {
|
|
@@ -143,32 +185,55 @@ function deserializeFromGun(data) {
|
|
|
143
185
|
}
|
|
144
186
|
|
|
145
187
|
/**
|
|
146
|
-
* Write data to Gun with radisk persistence
|
|
188
|
+
* Write data to Gun with radisk persistence.
|
|
189
|
+
*
|
|
147
190
|
* @param {Object} gun - Gun instance
|
|
148
191
|
* @param {string} path - Gun path
|
|
149
192
|
* @param {Object} data - Data to write
|
|
150
|
-
* @returns {Promise<
|
|
193
|
+
* @returns {Promise<Object>} Success object with ok and timeout flags
|
|
194
|
+
* @example
|
|
195
|
+
* const result = await write(gun, 'myapp/holon1/items/item1', { name: 'Test' });
|
|
196
|
+
* if (result.timeout) console.warn('Write may not be persisted');
|
|
151
197
|
*/
|
|
152
198
|
export async function write(gun, path, data) {
|
|
153
199
|
try {
|
|
154
200
|
const serialized = serializeForGun(data);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
201
|
+
const parts = path.split('/').filter(p => p.length > 0);
|
|
202
|
+
console.log('[gun-wrapper] write:', { path, parts, dataId: data?.id });
|
|
203
|
+
const ref = getGunPath(gun, path);
|
|
204
|
+
console.log('[gun-wrapper] write ref soul:', ref?._.get);
|
|
205
|
+
const ack = await gunPut(ref, serialized, 5000); // Increased timeout from 2s to 5s
|
|
206
|
+
console.log('[gun-wrapper] write ack:', { ok: ack.ok, timeout: ack.timeout });
|
|
207
|
+
if (ack.timeout) {
|
|
208
|
+
console.warn('[gun-wrapper] write timed out (data may not be persisted):', path);
|
|
209
|
+
}
|
|
210
|
+
console.log('[gun-wrapper] write complete:', path);
|
|
211
|
+
|
|
212
|
+
// Return ack info so caller can handle timeouts
|
|
213
|
+
return { ok: true, timeout: ack.timeout || false };
|
|
159
214
|
} catch (error) {
|
|
215
|
+
console.error('[gun-wrapper] write error:', error);
|
|
160
216
|
throw error;
|
|
161
217
|
}
|
|
162
218
|
}
|
|
163
219
|
|
|
164
220
|
/**
|
|
165
|
-
* Read data from Gun
|
|
221
|
+
* Read data from Gun.
|
|
222
|
+
*
|
|
166
223
|
* @param {Object} gun - Gun instance
|
|
167
224
|
* @param {string} path - Gun path
|
|
168
|
-
* @returns {Promise<Object|null>} Data or null if not found
|
|
225
|
+
* @returns {Promise<Object|null>} Data or null if not found or deleted
|
|
226
|
+
* @example
|
|
227
|
+
* const data = await read(gun, 'myapp/holon1/items/item1');
|
|
228
|
+
* if (data) console.log(data.name);
|
|
169
229
|
*/
|
|
170
230
|
export async function read(gun, path) {
|
|
171
|
-
const
|
|
231
|
+
const parts = path.split('/').filter(p => p.length > 0);
|
|
232
|
+
console.log('[gun-wrapper] read:', { path, parts });
|
|
233
|
+
const ref = getGunPath(gun, path);
|
|
234
|
+
console.log('[gun-wrapper] read ref soul:', ref?._.get);
|
|
235
|
+
const rawData = await gunPromise(ref, 2000);
|
|
236
|
+
console.log('[gun-wrapper] read rawData:', rawData ? (typeof rawData === 'string' ? rawData.substring(0, 100) : 'object') : 'null');
|
|
172
237
|
|
|
173
238
|
if (!rawData) {
|
|
174
239
|
return null;
|
|
@@ -185,26 +250,36 @@ export async function read(gun, path) {
|
|
|
185
250
|
}
|
|
186
251
|
|
|
187
252
|
/**
|
|
188
|
-
* Read all data under a path (lens query)
|
|
189
|
-
*
|
|
253
|
+
* Read all data under a path (lens query).
|
|
254
|
+
*
|
|
255
|
+
* First gets the count of expected items, then collects until count is reached.
|
|
256
|
+
*
|
|
190
257
|
* @param {Object} gun - Gun instance
|
|
191
258
|
* @param {string} path - Gun path
|
|
192
|
-
* @param {number} timeout - Maximum timeout in ms
|
|
259
|
+
* @param {number} [timeout=5000] - Maximum timeout in ms
|
|
193
260
|
* @returns {Promise<Object[]>} Array of data objects
|
|
261
|
+
* @example
|
|
262
|
+
* const items = await readAll(gun, 'myapp/holon1/items');
|
|
263
|
+
* console.log(`Found ${items.length} items`);
|
|
194
264
|
*/
|
|
195
265
|
export async function readAll(gun, path, timeout = 5000) {
|
|
266
|
+
const parts = path.split('/').filter(p => p.length > 0);
|
|
267
|
+
console.log('[gun-wrapper] readAll:', { path, parts });
|
|
268
|
+
|
|
196
269
|
return new Promise((resolve) => {
|
|
197
270
|
const output = new Map();
|
|
198
271
|
let settled = false;
|
|
199
272
|
let expectedCount = 0;
|
|
200
273
|
let receivedCount = 0;
|
|
201
274
|
|
|
202
|
-
const ref = gun
|
|
275
|
+
const ref = getGunPath(gun, path);
|
|
276
|
+
console.log('[gun-wrapper] readAll ref soul:', ref?._.get);
|
|
203
277
|
|
|
204
278
|
const tryResolve = () => {
|
|
205
279
|
if (settled) return;
|
|
206
280
|
if (expectedCount > 0 && receivedCount >= expectedCount) {
|
|
207
281
|
settled = true;
|
|
282
|
+
console.log('[gun-wrapper] readAll resolved with', output.size, 'items');
|
|
208
283
|
resolve(Array.from(output.values()));
|
|
209
284
|
}
|
|
210
285
|
};
|
|
@@ -216,18 +291,24 @@ export async function readAll(gun, path, timeout = 5000) {
|
|
|
216
291
|
// Step 1: Get the parent data to count expected items
|
|
217
292
|
ref.once((parentData) => {
|
|
218
293
|
if (settled) return;
|
|
294
|
+
console.log('[gun-wrapper] readAll parentData:', parentData);
|
|
295
|
+
console.log('[gun-wrapper] readAll parentData keys:', parentData ? Object.keys(parentData).filter(k => k !== '_') : 'null');
|
|
296
|
+
console.log('[gun-wrapper] readAll parentData type:', typeof parentData);
|
|
219
297
|
|
|
220
298
|
if (!parentData) {
|
|
221
299
|
settled = true;
|
|
300
|
+
console.log('[gun-wrapper] readAll: no parent data, returning empty');
|
|
222
301
|
resolve([]);
|
|
223
302
|
return;
|
|
224
303
|
}
|
|
225
304
|
|
|
226
305
|
// Get all keys except Gun metadata
|
|
227
306
|
const keys = Object.keys(parentData).filter(k => k !== '_');
|
|
307
|
+
console.log('[gun-wrapper] readAll keys:', keys);
|
|
228
308
|
|
|
229
309
|
if (keys.length === 0) {
|
|
230
310
|
settled = true;
|
|
311
|
+
console.log('[gun-wrapper] readAll: no keys, returning empty');
|
|
231
312
|
resolve([]);
|
|
232
313
|
return;
|
|
233
314
|
}
|
|
@@ -291,14 +372,17 @@ export async function readAll(gun, path, timeout = 5000) {
|
|
|
291
372
|
}
|
|
292
373
|
|
|
293
374
|
/**
|
|
294
|
-
* Update data (merge fields)
|
|
375
|
+
* Update data (merge fields).
|
|
376
|
+
*
|
|
295
377
|
* @param {Object} gun - Gun instance
|
|
296
378
|
* @param {string} path - Gun path
|
|
297
379
|
* @param {Object} updates - Fields to update
|
|
298
380
|
* @returns {Promise<boolean>} Success indicator
|
|
381
|
+
* @example
|
|
382
|
+
* const success = await update(gun, 'myapp/holon1/items/item1', { status: 'active' });
|
|
299
383
|
*/
|
|
300
384
|
export async function update(gun, path, updates) {
|
|
301
|
-
const rawData = await gunPromise(gun
|
|
385
|
+
const rawData = await gunPromise(getGunPath(gun, path));
|
|
302
386
|
|
|
303
387
|
if (!rawData) {
|
|
304
388
|
return false; // Not found
|
|
@@ -315,7 +399,9 @@ export async function update(gun, path, updates) {
|
|
|
315
399
|
|
|
316
400
|
try {
|
|
317
401
|
const serialized = serializeForGun(merged);
|
|
318
|
-
await gunPut(gun
|
|
402
|
+
await gunPut(getGunPath(gun, path), serialized, 2000);
|
|
403
|
+
// Add delay for propagation
|
|
404
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
319
405
|
return true;
|
|
320
406
|
} catch (error) {
|
|
321
407
|
throw error;
|
|
@@ -323,15 +409,18 @@ export async function update(gun, path, updates) {
|
|
|
323
409
|
}
|
|
324
410
|
|
|
325
411
|
/**
|
|
326
|
-
* Delete data (tombstone)
|
|
412
|
+
* Delete data (tombstone).
|
|
413
|
+
*
|
|
327
414
|
* @param {Object} gun - Gun instance
|
|
328
415
|
* @param {string} path - Gun path
|
|
329
416
|
* @returns {Promise<boolean>} Success indicator
|
|
417
|
+
* @example
|
|
418
|
+
* const deleted = await deleteData(gun, 'myapp/holon1/items/item1');
|
|
330
419
|
*/
|
|
331
420
|
export async function deleteData(gun, path) {
|
|
332
421
|
try {
|
|
333
422
|
// First read existing data to get the id
|
|
334
|
-
const rawData = await gunPromise(gun
|
|
423
|
+
const rawData = await gunPromise(getGunPath(gun, path));
|
|
335
424
|
if (!rawData) {
|
|
336
425
|
return true; // Already deleted/doesn't exist
|
|
337
426
|
}
|
|
@@ -345,7 +434,9 @@ export async function deleteData(gun, path) {
|
|
|
345
434
|
_deletedAt: Date.now()
|
|
346
435
|
};
|
|
347
436
|
|
|
348
|
-
await gunPut(gun
|
|
437
|
+
await gunPut(getGunPath(gun, path), serializeForGun(tombstone), 2000);
|
|
438
|
+
// Add delay for propagation
|
|
439
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
349
440
|
return true;
|
|
350
441
|
} catch (error) {
|
|
351
442
|
throw error;
|
|
@@ -353,7 +444,8 @@ export async function deleteData(gun, path) {
|
|
|
353
444
|
}
|
|
354
445
|
|
|
355
446
|
/**
|
|
356
|
-
* Delete all data under path prefix (tombstone)
|
|
447
|
+
* Delete all data under path prefix (tombstone).
|
|
448
|
+
*
|
|
357
449
|
* @param {Object} gun - Gun instance
|
|
358
450
|
* @param {string} path - Gun path prefix
|
|
359
451
|
* @returns {Promise<Object>} Deletion results { success: boolean, count: number }
|
|
@@ -374,13 +466,19 @@ export async function deleteAll(gun, path) {
|
|
|
374
466
|
}
|
|
375
467
|
|
|
376
468
|
/**
|
|
377
|
-
* Subscribe to data changes
|
|
469
|
+
* Subscribe to data changes.
|
|
470
|
+
*
|
|
378
471
|
* @param {Object} gun - Gun instance
|
|
379
472
|
* @param {string} path - Gun path
|
|
380
|
-
* @param {Function} callback - Called on data changes
|
|
381
|
-
* @param {Object} options - Subscription options
|
|
382
|
-
* @param {boolean} options.prefix - Subscribe to all items under path (default: auto-detect)
|
|
473
|
+
* @param {Function} callback - Called on data changes (data, key) => void
|
|
474
|
+
* @param {Object} [options={}] - Subscription options
|
|
475
|
+
* @param {boolean} [options.prefix] - Subscribe to all items under path (default: auto-detect)
|
|
383
476
|
* @returns {Object} Subscription object with unsubscribe method
|
|
477
|
+
* @example
|
|
478
|
+
* const sub = subscribe(gun, 'myapp/holon1/items', (data, key) => {
|
|
479
|
+
* console.log('Item changed:', key, data);
|
|
480
|
+
* });
|
|
481
|
+
* // Later: sub.unsubscribe();
|
|
384
482
|
*/
|
|
385
483
|
export function subscribe(gun, path, callback, options = {}) {
|
|
386
484
|
// Detect if this is a prefix subscription
|
|
@@ -389,7 +487,7 @@ export function subscribe(gun, path, callback, options = {}) {
|
|
|
389
487
|
|
|
390
488
|
if (isPrefix) {
|
|
391
489
|
// Subscribe to all items under this prefix
|
|
392
|
-
const ref = gun
|
|
490
|
+
const ref = getGunPath(gun, path);
|
|
393
491
|
|
|
394
492
|
ref.map().on((data, key) => {
|
|
395
493
|
if (data && !key.startsWith('_')) {
|
|
@@ -411,7 +509,7 @@ export function subscribe(gun, path, callback, options = {}) {
|
|
|
411
509
|
};
|
|
412
510
|
} else {
|
|
413
511
|
// Subscribe to single item
|
|
414
|
-
const listener = gun
|
|
512
|
+
const listener = getGunPath(gun, path).on((data, key) => {
|
|
415
513
|
if (data) {
|
|
416
514
|
const deserialized = deserializeFromGun(data);
|
|
417
515
|
if (deserialized && !deserialized._deleted) {
|
|
@@ -437,24 +535,31 @@ export function subscribe(gun, path, callback, options = {}) {
|
|
|
437
535
|
// ============================================================================
|
|
438
536
|
|
|
439
537
|
/**
|
|
440
|
-
* Write data to a global table
|
|
441
|
-
*
|
|
538
|
+
* Write data to a global table.
|
|
539
|
+
*
|
|
540
|
+
* Global tables are app-wide data not tied to specific holons (e.g., schemas, federation).
|
|
541
|
+
*
|
|
442
542
|
* @param {Object} gun - Gun instance
|
|
443
543
|
* @param {string} appname - Application namespace
|
|
444
544
|
* @param {string} tableName - Global table name
|
|
445
545
|
* @param {Object} data - Data to write (must have 'id' field)
|
|
446
|
-
* @returns {Promise<
|
|
546
|
+
* @returns {Promise<Object>} Success object with ok and timeout flags
|
|
547
|
+
* @throws {Error} If data doesn't have an id field
|
|
548
|
+
* @example
|
|
549
|
+
* await writeGlobal(gun, 'myapp', 'schemas', { id: 'user', type: 'object' });
|
|
447
550
|
*/
|
|
448
551
|
export async function writeGlobal(gun, appname, tableName, data) {
|
|
449
552
|
if (!data || !data.id) {
|
|
450
553
|
throw new Error('writeGlobal: data must have an id field');
|
|
451
554
|
}
|
|
452
555
|
const path = buildGlobalPath(appname, tableName, data.id);
|
|
556
|
+
// Use write function which includes the propagation delay
|
|
453
557
|
return write(gun, path, data);
|
|
454
558
|
}
|
|
455
559
|
|
|
456
560
|
/**
|
|
457
|
-
* Read data from a global table
|
|
561
|
+
* Read data from a global table.
|
|
562
|
+
*
|
|
458
563
|
* @param {Object} gun - Gun instance
|
|
459
564
|
* @param {string} appname - Application namespace
|
|
460
565
|
* @param {string} tableName - Global table name
|
|
@@ -467,12 +572,14 @@ export async function readGlobal(gun, appname, tableName, key) {
|
|
|
467
572
|
}
|
|
468
573
|
|
|
469
574
|
/**
|
|
470
|
-
* Read all data from a global table
|
|
471
|
-
*
|
|
575
|
+
* Read all data from a global table.
|
|
576
|
+
*
|
|
577
|
+
* Uses same approach as readAll.
|
|
578
|
+
*
|
|
472
579
|
* @param {Object} gun - Gun instance
|
|
473
580
|
* @param {string} appname - Application namespace
|
|
474
581
|
* @param {string} tableName - Global table name
|
|
475
|
-
* @param {number} timeout - Timeout in ms
|
|
582
|
+
* @param {number} [timeout=2000] - Timeout in ms
|
|
476
583
|
* @returns {Promise<Object[]>} Array of data objects
|
|
477
584
|
*/
|
|
478
585
|
export async function readAllGlobal(gun, appname, tableName, timeout = 2000) {
|
|
@@ -510,10 +617,13 @@ export async function deleteAllGlobal(gun, appname, tableName) {
|
|
|
510
617
|
// ============================================================================
|
|
511
618
|
|
|
512
619
|
/**
|
|
513
|
-
* Parse data from Gun storage, handling various formats
|
|
620
|
+
* Parse data from Gun storage, handling various formats.
|
|
621
|
+
*
|
|
622
|
+
* Handles:
|
|
514
623
|
* - JSON string in _json field
|
|
515
624
|
* - Legacy object format
|
|
516
625
|
* - Gun references
|
|
626
|
+
*
|
|
517
627
|
* @param {*} rawData - Raw data from Gun
|
|
518
628
|
* @returns {Object|null} Parsed data or null
|
|
519
629
|
*/
|
|
@@ -522,7 +632,8 @@ export function parse(rawData) {
|
|
|
522
632
|
}
|
|
523
633
|
|
|
524
634
|
/**
|
|
525
|
-
* Serialize data for Gun storage
|
|
635
|
+
* Serialize data for Gun storage.
|
|
636
|
+
*
|
|
526
637
|
* @param {Object} data - Data to serialize
|
|
527
638
|
* @returns {string} JSON string
|
|
528
639
|
*/
|
|
@@ -1,20 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* IndexedDB storage adapter for browsers
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview IndexedDB storage adapter for browsers.
|
|
3
|
+
*
|
|
4
|
+
* Provides persistent storage with good performance using browser IndexedDB.
|
|
5
|
+
* Uses B-tree indexes for efficient prefix queries.
|
|
6
|
+
*
|
|
7
|
+
* @module storage/indexeddb-storage
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
10
|
import { PersistentStorage } from './persistent-storage.js';
|
|
7
11
|
|
|
12
|
+
/**
|
|
13
|
+
* IndexedDB storage adapter for browsers.
|
|
14
|
+
*
|
|
15
|
+
* Provides high-performance persistent storage using IndexedDB with efficient prefix queries.
|
|
16
|
+
*
|
|
17
|
+
* @class IndexedDBStorage
|
|
18
|
+
* @extends PersistentStorage
|
|
19
|
+
* @example
|
|
20
|
+
* const storage = new IndexedDBStorage();
|
|
21
|
+
* await storage.init('myapp');
|
|
22
|
+
* await storage.put('key1', { id: 'event1', content: 'test' });
|
|
23
|
+
*/
|
|
8
24
|
export class IndexedDBStorage extends PersistentStorage {
|
|
25
|
+
/**
|
|
26
|
+
* Create a new IndexedDBStorage instance.
|
|
27
|
+
*/
|
|
9
28
|
constructor() {
|
|
10
29
|
super();
|
|
11
30
|
/** @type {IDBDatabase|null} */
|
|
12
31
|
this.db = null;
|
|
13
32
|
/** @type {string} */
|
|
14
33
|
this.dbName = '';
|
|
34
|
+
/** @type {string} */
|
|
15
35
|
this.storeName = 'events';
|
|
16
36
|
}
|
|
17
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Initialize storage with namespace.
|
|
40
|
+
*
|
|
41
|
+
* Creates or opens the IndexedDB database and object store.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} namespace - Storage namespace
|
|
44
|
+
* @returns {Promise<void>}
|
|
45
|
+
*/
|
|
18
46
|
async init(namespace) {
|
|
19
47
|
this.dbName = `holosphere_${namespace}`;
|
|
20
48
|
|
|
@@ -41,6 +69,13 @@ export class IndexedDBStorage extends PersistentStorage {
|
|
|
41
69
|
});
|
|
42
70
|
}
|
|
43
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Store an event.
|
|
74
|
+
*
|
|
75
|
+
* @param {string} key - Storage key
|
|
76
|
+
* @param {Object} event - Event data
|
|
77
|
+
* @returns {Promise<void>}
|
|
78
|
+
*/
|
|
44
79
|
async put(key, event) {
|
|
45
80
|
return new Promise((resolve, reject) => {
|
|
46
81
|
if (!this.db) {
|
|
@@ -57,6 +92,12 @@ export class IndexedDBStorage extends PersistentStorage {
|
|
|
57
92
|
});
|
|
58
93
|
}
|
|
59
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Retrieve an event.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} key - Storage key
|
|
99
|
+
* @returns {Promise<Object|null>} Event data or null
|
|
100
|
+
*/
|
|
60
101
|
async get(key) {
|
|
61
102
|
return new Promise((resolve, reject) => {
|
|
62
103
|
if (!this.db) {
|
|
@@ -77,8 +118,12 @@ export class IndexedDBStorage extends PersistentStorage {
|
|
|
77
118
|
}
|
|
78
119
|
|
|
79
120
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
121
|
+
* Retrieve all events matching a prefix.
|
|
122
|
+
*
|
|
123
|
+
* Uses IDBKeyRange for efficient B-tree index queries.
|
|
124
|
+
*
|
|
125
|
+
* @param {string} prefix - Key prefix to match
|
|
126
|
+
* @returns {Promise<any[]>} Array of matching events
|
|
82
127
|
*/
|
|
83
128
|
async getAll(prefix) {
|
|
84
129
|
return new Promise((resolve, reject) => {
|
|
@@ -119,6 +164,12 @@ export class IndexedDBStorage extends PersistentStorage {
|
|
|
119
164
|
});
|
|
120
165
|
}
|
|
121
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Delete an event.
|
|
169
|
+
*
|
|
170
|
+
* @param {string} key - Storage key
|
|
171
|
+
* @returns {Promise<void>}
|
|
172
|
+
*/
|
|
122
173
|
async delete(key) {
|
|
123
174
|
return new Promise((resolve, reject) => {
|
|
124
175
|
if (!this.db) {
|
|
@@ -135,6 +186,11 @@ export class IndexedDBStorage extends PersistentStorage {
|
|
|
135
186
|
});
|
|
136
187
|
}
|
|
137
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Clear all stored events.
|
|
191
|
+
*
|
|
192
|
+
* @returns {Promise<void>}
|
|
193
|
+
*/
|
|
138
194
|
async clear() {
|
|
139
195
|
return new Promise((resolve, reject) => {
|
|
140
196
|
if (!this.db) {
|
|
@@ -151,6 +207,11 @@ export class IndexedDBStorage extends PersistentStorage {
|
|
|
151
207
|
});
|
|
152
208
|
}
|
|
153
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Close the database connection.
|
|
212
|
+
*
|
|
213
|
+
* @returns {Promise<void>}
|
|
214
|
+
*/
|
|
154
215
|
async close() {
|
|
155
216
|
if (this.db) {
|
|
156
217
|
this.db.close();
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Simple Key Storage for Node.js
|
|
3
|
-
* Basic filesystem-based key management
|
|
2
|
+
* @fileoverview Simple Key Storage for Node.js.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Basic filesystem-based key management.
|
|
5
|
+
* NOTE: This only works in Node.js, not browsers.
|
|
6
|
+
* For browsers, keys are managed in localStorage.
|
|
7
|
+
*
|
|
8
|
+
* @module storage/key-storage-simple
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
import fs from 'fs';
|
|
@@ -11,7 +13,10 @@ import path from 'path';
|
|
|
11
13
|
import os from 'os';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
|
-
* Get key storage directory
|
|
16
|
+
* Get key storage directory.
|
|
17
|
+
*
|
|
18
|
+
* @private
|
|
19
|
+
* @returns {string} Key storage directory path
|
|
15
20
|
*/
|
|
16
21
|
function getKeyDir() {
|
|
17
22
|
const configDir = process.env.XDG_CONFIG_HOME ||
|
|
@@ -23,7 +28,11 @@ function getKeyDir() {
|
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
/**
|
|
26
|
-
* Get key file path for an app
|
|
31
|
+
* Get key file path for an app.
|
|
32
|
+
*
|
|
33
|
+
* @private
|
|
34
|
+
* @param {string} appName - Application name
|
|
35
|
+
* @returns {string} Full path to key file
|
|
27
36
|
*/
|
|
28
37
|
function getKeyPath(appName) {
|
|
29
38
|
const safeName = appName.replace(/[^a-zA-Z0-9-_]/g, '_');
|
|
@@ -31,7 +40,10 @@ function getKeyPath(appName) {
|
|
|
31
40
|
}
|
|
32
41
|
|
|
33
42
|
/**
|
|
34
|
-
* Load private key
|
|
43
|
+
* Load private key from filesystem.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} appName - Application name
|
|
46
|
+
* @returns {string|null} Private key (hex) or null if not found
|
|
35
47
|
*/
|
|
36
48
|
export function loadKey(appName) {
|
|
37
49
|
const keyPath = getKeyPath(appName);
|
|
@@ -45,7 +57,12 @@ export function loadKey(appName) {
|
|
|
45
57
|
}
|
|
46
58
|
|
|
47
59
|
/**
|
|
48
|
-
* Save private key
|
|
60
|
+
* Save private key to filesystem with secure permissions.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} appName - Application name
|
|
63
|
+
* @param {string} privateKey - Private key (64-character hex string)
|
|
64
|
+
* @returns {string} Path where key was saved
|
|
65
|
+
* @throws {Error} If private key format is invalid
|
|
49
66
|
*/
|
|
50
67
|
export function saveKey(appName, privateKey) {
|
|
51
68
|
if (!/^[0-9a-f]{64}$/i.test(privateKey)) {
|
|
@@ -64,7 +81,13 @@ export function saveKey(appName, privateKey) {
|
|
|
64
81
|
}
|
|
65
82
|
|
|
66
83
|
/**
|
|
67
|
-
* Get or create key
|
|
84
|
+
* Get or create private key.
|
|
85
|
+
*
|
|
86
|
+
* Loads existing key or generates and saves a new one.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} appName - Application name
|
|
89
|
+
* @param {Function} generateFn - Function to generate new key (returns hex string)
|
|
90
|
+
* @returns {string} Private key (hex)
|
|
68
91
|
*/
|
|
69
92
|
export function getOrCreateKey(appName, generateFn) {
|
|
70
93
|
const existing = loadKey(appName);
|