holosphere 2.0.0-alpha1 → 2.0.0-alpha10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/CHANGELOG.md +473 -0
  2. package/FEATURES.md +431 -0
  3. package/LICENSE +29 -166
  4. package/LICENSE-AGPL.md +180 -0
  5. package/README.md +97 -16
  6. package/dist/2019-D2OG2idw.js +6680 -0
  7. package/dist/2019-D2OG2idw.js.map +1 -0
  8. package/dist/2019-EION3wKo.cjs +8 -0
  9. package/dist/2019-EION3wKo.cjs.map +1 -0
  10. package/dist/_commonjsHelpers-C37NGDzP.cjs +2 -0
  11. package/dist/_commonjsHelpers-C37NGDzP.cjs.map +1 -0
  12. package/dist/_commonjsHelpers-CUmg6egw.js +7 -0
  13. package/dist/_commonjsHelpers-CUmg6egw.js.map +1 -0
  14. package/dist/browser-BSniCNqO.js +3058 -0
  15. package/dist/browser-BSniCNqO.js.map +1 -0
  16. package/dist/browser-Cq59Ij19.cjs +2 -0
  17. package/dist/browser-Cq59Ij19.cjs.map +1 -0
  18. package/dist/cdn/holosphere.min.js +55 -0
  19. package/dist/cdn/holosphere.min.js.map +1 -0
  20. package/dist/cjs/holosphere.cjs +2 -0
  21. package/dist/cjs/holosphere.cjs.map +1 -0
  22. package/dist/esm/holosphere.js +53 -0
  23. package/dist/esm/holosphere.js.map +1 -0
  24. package/dist/index-DDGt_V9o.cjs +12 -0
  25. package/dist/index-DDGt_V9o.cjs.map +1 -0
  26. package/dist/index-DJXftyvB.js +39841 -0
  27. package/dist/index-DJXftyvB.js.map +1 -0
  28. package/dist/index-DMbdcMtK.cjs +18 -0
  29. package/dist/index-DMbdcMtK.cjs.map +1 -0
  30. package/dist/index-DeZ1xz_s.js +15104 -0
  31. package/dist/index-DeZ1xz_s.js.map +1 -0
  32. package/dist/indexeddb-storage-BFt6hMeF.js +176 -0
  33. package/dist/indexeddb-storage-BFt6hMeF.js.map +1 -0
  34. package/dist/indexeddb-storage-BK5tv4Sh.cjs +2 -0
  35. package/dist/indexeddb-storage-BK5tv4Sh.cjs.map +1 -0
  36. package/dist/memory-storage-C9HuoL2E.js +91 -0
  37. package/dist/memory-storage-C9HuoL2E.js.map +1 -0
  38. package/dist/memory-storage-Dao7jfYG.cjs +2 -0
  39. package/dist/memory-storage-Dao7jfYG.cjs.map +1 -0
  40. package/dist/secp256k1-BbKzbLtD.cjs +12 -0
  41. package/dist/secp256k1-BbKzbLtD.cjs.map +1 -0
  42. package/dist/secp256k1-CreY7Pcl.js +1890 -0
  43. package/dist/secp256k1-CreY7Pcl.js.map +1 -0
  44. package/docs/CONTRACTS.md +797 -0
  45. package/docs/FOSDEM_PROPOSAL.md +388 -0
  46. package/docs/LOCALFIRST.md +266 -0
  47. package/docs/api/ai_aggregation.js.html +333 -0
  48. package/docs/api/ai_breakdown.js.html +524 -0
  49. package/docs/api/ai_classifier.js.html +231 -0
  50. package/docs/api/ai_council.js.html +246 -0
  51. package/docs/api/ai_embeddings.js.html +304 -0
  52. package/docs/api/ai_federation-ai.js.html +338 -0
  53. package/docs/api/ai_h3-ai.js.html +970 -0
  54. package/docs/api/ai_index.js.html +124 -0
  55. package/docs/api/ai_json-ops.js.html +241 -0
  56. package/docs/api/ai_llm-service.js.html +239 -0
  57. package/docs/api/ai_nl-query.js.html +236 -0
  58. package/docs/api/ai_relationships.js.html +367 -0
  59. package/docs/api/ai_schema-extractor.js.html +235 -0
  60. package/docs/api/ai_spatial.js.html +307 -0
  61. package/docs/api/ai_tts.js.html +214 -0
  62. package/docs/api/content_social-protocols.js.html +180 -0
  63. package/docs/api/core_holosphere.js.html +757 -0
  64. package/docs/api/crypto_nostr-utils.js.html +306 -0
  65. package/docs/api/crypto_secp256k1.js.html +267 -0
  66. package/docs/api/data/search.json +1 -0
  67. package/docs/api/federation_discovery.js.html +337 -0
  68. package/docs/api/federation_handshake.js.html +478 -0
  69. package/docs/api/federation_hologram.js.html +1053 -0
  70. package/docs/api/federation_registry.js.html +389 -0
  71. package/docs/api/fonts/Inconsolata-Regular.ttf +0 -0
  72. package/docs/api/fonts/OpenSans-Regular.ttf +0 -0
  73. package/docs/api/fonts/WorkSans-Bold.ttf +0 -0
  74. package/docs/api/global.html +3 -0
  75. package/docs/api/hierarchical_upcast.js.html +128 -0
  76. package/docs/api/index.html +265 -0
  77. package/docs/api/index.js.html +1868 -0
  78. package/docs/api/lib_ai-methods.js.html +660 -0
  79. package/docs/api/lib_contract-methods.js.html +445 -0
  80. package/docs/api/lib_errors.js.html +56 -0
  81. package/docs/api/lib_federation-methods.js.html +348 -0
  82. package/docs/api/lib_index.js.html +33 -0
  83. package/docs/api/module-ai.html +5 -0
  84. package/docs/api/module-ai_aggregation-SmartAggregation.html +6 -0
  85. package/docs/api/module-ai_aggregation.SmartAggregation.html +3 -0
  86. package/docs/api/module-ai_aggregation.html +3 -0
  87. package/docs/api/module-ai_breakdown-TaskBreakdown.html +5 -0
  88. package/docs/api/module-ai_breakdown.TaskBreakdown.html +3 -0
  89. package/docs/api/module-ai_breakdown.html +3 -0
  90. package/docs/api/module-ai_classifier-Classifier.html +6 -0
  91. package/docs/api/module-ai_classifier.Classifier.html +3 -0
  92. package/docs/api/module-ai_classifier.html +3 -0
  93. package/docs/api/module-ai_council-Council.html +6 -0
  94. package/docs/api/module-ai_council.Council.html +3 -0
  95. package/docs/api/module-ai_council.html +3 -0
  96. package/docs/api/module-ai_embeddings-Embeddings.html +5 -0
  97. package/docs/api/module-ai_embeddings.Embeddings.html +3 -0
  98. package/docs/api/module-ai_embeddings.html +3 -0
  99. package/docs/api/module-ai_federation-ai-FederationAdvisor.html +6 -0
  100. package/docs/api/module-ai_federation-ai.FederationAdvisor.html +3 -0
  101. package/docs/api/module-ai_federation-ai.html +3 -0
  102. package/docs/api/module-ai_h3-ai-H3AI.html +6 -0
  103. package/docs/api/module-ai_h3-ai.H3AI.html +3 -0
  104. package/docs/api/module-ai_h3-ai.html +3 -0
  105. package/docs/api/module-ai_json-ops-JSONOps.html +5 -0
  106. package/docs/api/module-ai_json-ops.JSONOps.html +3 -0
  107. package/docs/api/module-ai_json-ops.html +3 -0
  108. package/docs/api/module-ai_llm-service-LLMService.html +5 -0
  109. package/docs/api/module-ai_llm-service.LLMService.html +3 -0
  110. package/docs/api/module-ai_llm-service.html +3 -0
  111. package/docs/api/module-ai_nl-query-NLQuery.html +5 -0
  112. package/docs/api/module-ai_nl-query.NLQuery.html +3 -0
  113. package/docs/api/module-ai_nl-query.html +3 -0
  114. package/docs/api/module-ai_relationships-RelationshipDiscovery.html +6 -0
  115. package/docs/api/module-ai_relationships.RelationshipDiscovery.html +3 -0
  116. package/docs/api/module-ai_relationships.html +3 -0
  117. package/docs/api/module-ai_schema-extractor-SchemaExtractor.html +5 -0
  118. package/docs/api/module-ai_schema-extractor.SchemaExtractor.html +3 -0
  119. package/docs/api/module-ai_schema-extractor.html +3 -0
  120. package/docs/api/module-ai_spatial-SpatialAnalysis.html +6 -0
  121. package/docs/api/module-ai_spatial.SpatialAnalysis.html +3 -0
  122. package/docs/api/module-ai_spatial.html +3 -0
  123. package/docs/api/module-ai_tts-TTS.html +5 -0
  124. package/docs/api/module-ai_tts.TTS.html +3 -0
  125. package/docs/api/module-ai_tts.html +3 -0
  126. package/docs/api/module-content_social-protocols.html +3 -0
  127. package/docs/api/module-core_holosphere-HoloSphere.html +6 -0
  128. package/docs/api/module-core_holosphere.HoloSphere.html +3 -0
  129. package/docs/api/module-core_holosphere.html +3 -0
  130. package/docs/api/module-crypto_nostr-utils.html +3 -0
  131. package/docs/api/module-crypto_secp256k1.html +3 -0
  132. package/docs/api/module-federation_hologram.html +3 -0
  133. package/docs/api/module-hierarchical_upcast.html +3 -0
  134. package/docs/api/module-holosphere-HoloSphereBase.html +3 -0
  135. package/docs/api/module-holosphere.html +3 -0
  136. package/docs/api/module-lib_ai-methods.html +3 -0
  137. package/docs/api/module-lib_contract-methods.html +3 -0
  138. package/docs/api/module-lib_errors-AuthorizationError.html +3 -0
  139. package/docs/api/module-lib_errors-ValidationError.html +3 -0
  140. package/docs/api/module-lib_errors.AuthorizationError.html +3 -0
  141. package/docs/api/module-lib_errors.ValidationError.html +3 -0
  142. package/docs/api/module-lib_errors.html +3 -0
  143. package/docs/api/module-lib_federation-methods.html +3 -0
  144. package/docs/api/module-lib_index.html +3 -0
  145. package/docs/api/module-schema_validator-ValidationError.html +3 -0
  146. package/docs/api/module-schema_validator.ValidationError.html +3 -0
  147. package/docs/api/module-schema_validator.html +3 -0
  148. package/docs/api/module-spatial_h3-operations.html +4 -0
  149. package/docs/api/module-storage_backend-factory.BackendFactory.html +3 -0
  150. package/docs/api/module-storage_backend-factory.html +3 -0
  151. package/docs/api/module-storage_backend-interface-StorageBackend.html +3 -0
  152. package/docs/api/module-storage_backend-interface.StorageBackend.html +3 -0
  153. package/docs/api/module-storage_backend-interface.html +3 -0
  154. package/docs/api/module-storage_backends_activitypub-backend-ActivityPubBackend.html +7 -0
  155. package/docs/api/module-storage_backends_activitypub-backend.ActivityPubBackend.html +3 -0
  156. package/docs/api/module-storage_backends_activitypub-backend.html +3 -0
  157. package/docs/api/module-storage_backends_activitypub_server-ActivityPubServer.html +8 -0
  158. package/docs/api/module-storage_backends_activitypub_server.ActivityPubServer.html +3 -0
  159. package/docs/api/module-storage_backends_activitypub_server.html +3 -0
  160. package/docs/api/module-storage_backends_gundb-backend-GunDBBackend.html +7 -0
  161. package/docs/api/module-storage_backends_gundb-backend.GunDBBackend.html +3 -0
  162. package/docs/api/module-storage_backends_gundb-backend.html +3 -0
  163. package/docs/api/module-storage_backends_nostr-backend-NostrBackend.html +8 -0
  164. package/docs/api/module-storage_backends_nostr-backend.NostrBackend.html +3 -0
  165. package/docs/api/module-storage_backends_nostr-backend.html +3 -0
  166. package/docs/api/module-storage_filesystem-storage-FileSystemStorage.html +5 -0
  167. package/docs/api/module-storage_filesystem-storage-browser-FileSystemStorage.html +3 -0
  168. package/docs/api/module-storage_filesystem-storage-browser.FileSystemStorage.html +3 -0
  169. package/docs/api/module-storage_filesystem-storage-browser.html +3 -0
  170. package/docs/api/module-storage_filesystem-storage.FileSystemStorage.html +3 -0
  171. package/docs/api/module-storage_filesystem-storage.html +3 -0
  172. package/docs/api/module-storage_global-tables.html +3 -0
  173. package/docs/api/module-storage_gun-async.html +3 -0
  174. package/docs/api/module-storage_gun-auth-GunAuth.html +5 -0
  175. package/docs/api/module-storage_gun-auth.GunAuth.html +3 -0
  176. package/docs/api/module-storage_gun-auth.html +3 -0
  177. package/docs/api/module-storage_gun-federation.html +3 -0
  178. package/docs/api/module-storage_gun-references-GunReferenceHandler.html +5 -0
  179. package/docs/api/module-storage_gun-references.GunReferenceHandler.html +3 -0
  180. package/docs/api/module-storage_gun-references.html +3 -0
  181. package/docs/api/module-storage_gun-schema-GunSchemaValidator.html +5 -0
  182. package/docs/api/module-storage_gun-schema.GunSchemaValidator.html +3 -0
  183. package/docs/api/module-storage_gun-schema.html +3 -0
  184. package/docs/api/module-storage_gun-wrapper.html +11 -0
  185. package/docs/api/module-storage_indexeddb-storage-IndexedDBStorage.html +5 -0
  186. package/docs/api/module-storage_indexeddb-storage.IndexedDBStorage.html +3 -0
  187. package/docs/api/module-storage_indexeddb-storage.html +3 -0
  188. package/docs/api/module-storage_key-storage-simple.html +3 -0
  189. package/docs/api/module-storage_key-storage.html +4 -0
  190. package/docs/api/module-storage_memory-storage-MemoryStorage.html +5 -0
  191. package/docs/api/module-storage_memory-storage.MemoryStorage.html +3 -0
  192. package/docs/api/module-storage_memory-storage.html +3 -0
  193. package/docs/api/module-storage_migration-MigrationTool.html +6 -0
  194. package/docs/api/module-storage_migration.MigrationTool.html +3 -0
  195. package/docs/api/module-storage_migration.html +3 -0
  196. package/docs/api/module-storage_nostr-async.html +18 -0
  197. package/docs/api/module-storage_nostr-client-LRUCache.html +3 -0
  198. package/docs/api/module-storage_nostr-client-NostrClient.html +7 -0
  199. package/docs/api/module-storage_nostr-client.NostrClient.html +15 -0
  200. package/docs/api/module-storage_nostr-client.html +6 -0
  201. package/docs/api/module-storage_nostr-wrapper.html +3 -0
  202. package/docs/api/module-storage_outbox-queue-OutboxQueue.html +4 -0
  203. package/docs/api/module-storage_outbox-queue.OutboxQueue.html +3 -0
  204. package/docs/api/module-storage_outbox-queue.html +3 -0
  205. package/docs/api/module-storage_persistent-storage-PersistentStorage.html +3 -0
  206. package/docs/api/module-storage_persistent-storage.html +4 -0
  207. package/docs/api/module-storage_sync-service-SyncService.html +5 -0
  208. package/docs/api/module-storage_sync-service.SyncService.html +3 -0
  209. package/docs/api/module-storage_sync-service.html +3 -0
  210. package/docs/api/module-storage_unified-storage.html +3 -0
  211. package/docs/api/module-subscriptions_manager.SubscriptionRegistry.html +3 -0
  212. package/docs/api/module-subscriptions_manager.html +3 -0
  213. package/docs/api/schema_validator.js.html +113 -0
  214. package/docs/api/scripts/core.js +726 -0
  215. package/docs/api/scripts/core.min.js +23 -0
  216. package/docs/api/scripts/resize.js +90 -0
  217. package/docs/api/scripts/search.js +265 -0
  218. package/docs/api/scripts/search.min.js +6 -0
  219. package/docs/api/scripts/third-party/Apache-License-2.0.txt +202 -0
  220. package/docs/api/scripts/third-party/fuse.js +9 -0
  221. package/docs/api/scripts/third-party/hljs-line-num-original.js +369 -0
  222. package/docs/api/scripts/third-party/hljs-line-num.js +1 -0
  223. package/docs/api/scripts/third-party/hljs-original.js +5171 -0
  224. package/docs/api/scripts/third-party/hljs.js +1 -0
  225. package/docs/api/scripts/third-party/popper.js +5 -0
  226. package/docs/api/scripts/third-party/tippy.js +1 -0
  227. package/docs/api/scripts/third-party/tocbot.js +672 -0
  228. package/docs/api/scripts/third-party/tocbot.min.js +1 -0
  229. package/docs/api/spatial_h3-operations.js.html +129 -0
  230. package/docs/api/storage_backend-factory.js.html +133 -0
  231. package/docs/api/storage_backend-interface.js.html +164 -0
  232. package/docs/api/storage_backends_activitypub-backend.js.html +298 -0
  233. package/docs/api/storage_backends_activitypub_server.js.html +678 -0
  234. package/docs/api/storage_backends_gundb-backend.js.html +878 -0
  235. package/docs/api/storage_backends_nostr-backend.js.html +254 -0
  236. package/docs/api/storage_filesystem-storage-browser.js.html +83 -0
  237. package/docs/api/storage_filesystem-storage.js.html +207 -0
  238. package/docs/api/storage_global-tables.js.html +116 -0
  239. package/docs/api/storage_gun-async.js.html +344 -0
  240. package/docs/api/storage_gun-auth.js.html +376 -0
  241. package/docs/api/storage_gun-federation.js.html +788 -0
  242. package/docs/api/storage_gun-references.js.html +212 -0
  243. package/docs/api/storage_gun-schema.js.html +309 -0
  244. package/docs/api/storage_gun-wrapper.js.html +645 -0
  245. package/docs/api/storage_indexeddb-storage.js.html +224 -0
  246. package/docs/api/storage_key-storage-simple.js.html +102 -0
  247. package/docs/api/storage_key-storage.js.html +171 -0
  248. package/docs/api/storage_memory-storage.js.html +128 -0
  249. package/docs/api/storage_migration.js.html +354 -0
  250. package/docs/api/storage_nostr-async.js.html +1076 -0
  251. package/docs/api/storage_nostr-client.js.html +1598 -0
  252. package/docs/api/storage_nostr-wrapper.js.html +218 -0
  253. package/docs/api/storage_outbox-queue.js.html +248 -0
  254. package/docs/api/storage_persistent-storage.js.html +160 -0
  255. package/docs/api/storage_sync-service.js.html +201 -0
  256. package/docs/api/storage_unified-storage.js.html +157 -0
  257. package/docs/api/styles/clean-jsdoc-theme-base.css +1159 -0
  258. package/docs/api/styles/clean-jsdoc-theme-dark.css +412 -0
  259. package/docs/api/styles/clean-jsdoc-theme-light.css +482 -0
  260. package/docs/api/styles/clean-jsdoc-theme-scrollbar.css +30 -0
  261. package/docs/api/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
  262. package/docs/api/styles/clean-jsdoc-theme.min.css +1 -0
  263. package/docs/api/subscriptions_manager.js.html +162 -0
  264. package/docs/contracts/api-interface.md +793 -0
  265. package/docs/data-model.md +476 -0
  266. package/docs/gun-async-usage.md +338 -0
  267. package/docs/plan.md +349 -0
  268. package/docs/quickstart.md +674 -0
  269. package/docs/research.md +362 -0
  270. package/docs/spec.md +244 -0
  271. package/docs/storage-backends.md +326 -0
  272. package/docs/tasks.md +947 -0
  273. package/examples/demo.html +47 -0
  274. package/examples/holosphere-widget.js +1242 -0
  275. package/examples/widget-demo.html +274 -0
  276. package/examples/widget.html +703 -0
  277. package/jsdoc.json +26 -0
  278. package/package.json +25 -7
  279. package/src/ai/aggregation.js +13 -2
  280. package/src/ai/breakdown.js +12 -2
  281. package/src/ai/classifier.js +14 -3
  282. package/src/ai/council.js +22 -7
  283. package/src/ai/embeddings.js +37 -15
  284. package/src/ai/federation-ai.js +13 -2
  285. package/src/ai/h3-ai.js +14 -2
  286. package/src/ai/index.js +16 -7
  287. package/src/ai/json-ops.js +18 -5
  288. package/src/ai/llm-service.js +62 -31
  289. package/src/ai/nl-query.js +12 -2
  290. package/src/ai/relationships.js +13 -2
  291. package/src/ai/schema-extractor.js +24 -10
  292. package/src/ai/spatial.js +13 -2
  293. package/src/ai/tts.js +25 -8
  294. package/src/cdn-entry.js +22 -0
  295. package/src/content/social-protocols.js +34 -25
  296. package/src/contracts/abis/Appreciative.json +1280 -0
  297. package/src/contracts/abis/AppreciativeFactory.json +101 -0
  298. package/src/contracts/abis/Bundle.json +1438 -0
  299. package/src/contracts/abis/BundleFactory.json +106 -0
  300. package/src/contracts/abis/Holon.json +881 -0
  301. package/src/contracts/abis/Holons.json +330 -0
  302. package/src/contracts/abis/Managed.json +1262 -0
  303. package/src/contracts/abis/ManagedFactory.json +149 -0
  304. package/src/contracts/abis/Membrane.json +261 -0
  305. package/src/contracts/abis/Splitter.json +1624 -0
  306. package/src/contracts/abis/SplitterFactory.json +220 -0
  307. package/src/contracts/abis/TestToken.json +321 -0
  308. package/src/contracts/abis/Zoned.json +1461 -0
  309. package/src/contracts/abis/ZonedFactory.json +154 -0
  310. package/src/contracts/chain-manager.js +403 -0
  311. package/src/contracts/deployer.js +500 -0
  312. package/src/contracts/event-listener.js +539 -0
  313. package/src/contracts/holon-contracts.js +359 -0
  314. package/src/contracts/index.js +82 -0
  315. package/src/contracts/networks.js +229 -0
  316. package/src/contracts/operations.js +687 -0
  317. package/src/contracts/queries.js +638 -0
  318. package/src/core/holosphere.js +487 -6
  319. package/src/crypto/nostr-utils.js +303 -0
  320. package/src/crypto/secp256k1.js +7 -2
  321. package/src/federation/handshake.js +475 -0
  322. package/src/federation/hologram.js +117 -3
  323. package/src/hierarchical/upcast.js +40 -25
  324. package/src/index.js +1501 -1909
  325. package/src/lib/ai-methods.js +657 -0
  326. package/src/lib/contract-methods.js +442 -0
  327. package/src/lib/errors.js +53 -0
  328. package/src/lib/federation-methods.js +345 -0
  329. package/src/lib/index.js +30 -0
  330. package/src/schema/validator.js +22 -3
  331. package/src/spatial/h3-operations.js +19 -3
  332. package/src/storage/backend-factory.js +7 -2
  333. package/src/storage/backend-interface.js +21 -2
  334. package/src/storage/backends/activitypub/server.js +25 -3
  335. package/src/storage/backends/activitypub-backend.js +25 -2
  336. package/src/storage/backends/gundb-backend.js +692 -50
  337. package/src/storage/backends/nostr-backend.js +116 -1
  338. package/src/storage/filesystem-storage-browser.js +42 -2
  339. package/src/storage/filesystem-storage.js +72 -5
  340. package/src/storage/global-tables.js +35 -3
  341. package/src/storage/gun-async.js +75 -15
  342. package/src/storage/gun-auth.js +373 -0
  343. package/src/storage/gun-federation.js +785 -0
  344. package/src/storage/gun-references.js +209 -0
  345. package/src/storage/gun-schema.js +306 -0
  346. package/src/storage/gun-wrapper.js +475 -54
  347. package/src/storage/indexeddb-storage.js +112 -13
  348. package/src/storage/key-storage-simple.js +32 -9
  349. package/src/storage/key-storage.js +45 -13
  350. package/src/storage/memory-storage.js +68 -2
  351. package/src/storage/migration.js +20 -7
  352. package/src/storage/nostr-async.js +412 -122
  353. package/src/storage/nostr-client.js +749 -76
  354. package/src/storage/nostr-wrapper.js +6 -2
  355. package/src/storage/outbox-queue.js +55 -18
  356. package/src/storage/persistent-storage.js +62 -14
  357. package/src/storage/sync-service.js +51 -17
  358. package/src/storage/unified-storage.js +154 -0
  359. package/src/subscriptions/manager.js +34 -17
  360. package/types/index.d.ts +133 -0
  361. package/vite.config.cdn.js +60 -0
  362. package/tests/unit/ai/aggregation.test.js +0 -295
  363. package/tests/unit/ai/breakdown.test.js +0 -446
  364. package/tests/unit/ai/classifier.test.js +0 -294
  365. package/tests/unit/ai/council.test.js +0 -262
  366. package/tests/unit/ai/embeddings.test.js +0 -384
  367. package/tests/unit/ai/federation-ai.test.js +0 -344
  368. package/tests/unit/ai/h3-ai.test.js +0 -458
  369. package/tests/unit/ai/index.test.js +0 -304
  370. package/tests/unit/ai/json-ops.test.js +0 -307
  371. package/tests/unit/ai/llm-service.test.js +0 -390
  372. package/tests/unit/ai/nl-query.test.js +0 -383
  373. package/tests/unit/ai/relationships.test.js +0 -311
  374. package/tests/unit/ai/schema-extractor.test.js +0 -384
  375. package/tests/unit/ai/spatial.test.js +0 -279
  376. package/tests/unit/ai/tts.test.js +0 -279
  377. package/tests/unit/content.test.js +0 -332
  378. package/tests/unit/contract/core.test.js +0 -88
  379. package/tests/unit/contract/crypto.test.js +0 -198
  380. package/tests/unit/contract/data.test.js +0 -223
  381. package/tests/unit/contract/federation.test.js +0 -181
  382. package/tests/unit/contract/hierarchical.test.js +0 -113
  383. package/tests/unit/contract/schema.test.js +0 -114
  384. package/tests/unit/contract/social.test.js +0 -217
  385. package/tests/unit/contract/spatial.test.js +0 -110
  386. package/tests/unit/contract/subscriptions.test.js +0 -128
  387. package/tests/unit/contract/utils.test.js +0 -159
  388. package/tests/unit/core.test.js +0 -152
  389. package/tests/unit/crypto.test.js +0 -328
  390. package/tests/unit/federation.test.js +0 -234
  391. package/tests/unit/gun-async.test.js +0 -252
  392. package/tests/unit/hierarchical.test.js +0 -399
  393. package/tests/unit/integration/scenario-01-geographic-storage.test.js +0 -74
  394. package/tests/unit/integration/scenario-02-federation.test.js +0 -76
  395. package/tests/unit/integration/scenario-03-subscriptions.test.js +0 -102
  396. package/tests/unit/integration/scenario-04-validation.test.js +0 -129
  397. package/tests/unit/integration/scenario-05-hierarchy.test.js +0 -125
  398. package/tests/unit/integration/scenario-06-social.test.js +0 -135
  399. package/tests/unit/integration/scenario-07-persistence.test.js +0 -130
  400. package/tests/unit/integration/scenario-08-authorization.test.js +0 -161
  401. package/tests/unit/integration/scenario-09-cross-dimensional.test.js +0 -139
  402. package/tests/unit/integration/scenario-10-cross-holosphere-capabilities.test.js +0 -357
  403. package/tests/unit/integration/scenario-11-cross-holosphere-federation.test.js +0 -410
  404. package/tests/unit/integration/scenario-12-capability-federated-read.test.js +0 -719
  405. package/tests/unit/performance/benchmark.test.js +0 -85
  406. package/tests/unit/schema.test.js +0 -213
  407. package/tests/unit/spatial.test.js +0 -158
  408. package/tests/unit/storage.test.js +0 -195
  409. package/tests/unit/subscriptions.test.js +0 -328
  410. package/tests/unit/test-data-permanence-debug.js +0 -197
  411. package/tests/unit/test-data-permanence.js +0 -340
  412. package/tests/unit/test-key-persistence-fixed.js +0 -148
  413. package/tests/unit/test-key-persistence.js +0 -172
  414. package/tests/unit/test-relay-permanence.js +0 -376
  415. package/tests/unit/test-second-node.js +0 -95
  416. package/tests/unit/test-simple-write.js +0 -89
  417. /package/{cleanup-test-data.js → scripts/cleanup-test-data.js} +0 -0
  418. /package/{test-ai-real-api.js → scripts/test-ai-real-api.js} +0 -0
@@ -1,39 +1,112 @@
1
1
  /**
2
- * GunDB Storage Backend
3
- * Wraps existing gun-wrapper.js as a StorageBackend
2
+ * @fileoverview GunDB storage backend with authentication, schema validation, references, and global tables.
3
+ * Provides full-featured P2P data storage using GunDB with write caching for immediate consistency.
4
+ * @module storage/backends/gundb-backend
4
5
  */
5
6
 
6
7
  import { StorageBackend } from '../backend-interface.js';
7
8
  import * as wrapper from '../gun-wrapper.js';
8
9
  import { gunPromise, gunPut, gunMap, gunCollect } from '../gun-async.js';
10
+ import { GunReferenceHandler } from '../gun-references.js';
11
+ import { GunAuth } from '../gun-auth.js';
12
+ import { GunSchemaValidator } from '../gun-schema.js';
9
13
 
14
+ /**
15
+ * GunDB storage backend implementation with advanced features.
16
+ * Supports authentication, schema validation, references, global tables,
17
+ * and write caching for immediate consistency.
18
+ *
19
+ * @class GunDBBackend
20
+ * @extends StorageBackend
21
+ * @example
22
+ * const backend = await BackendFactory.create('gundb', {
23
+ * appName: 'myapp',
24
+ * peers: ['wss://gun-server.example.com/gun'],
25
+ * radisk: true
26
+ * });
27
+ */
10
28
  export class GunDBBackend extends StorageBackend {
29
+ /**
30
+ * Create a new GunDB backend instance.
31
+ * @param {Object} config - Backend configuration
32
+ * @param {string} [config.appName='holosphere'] - Application namespace
33
+ * @param {string[]} [config.peers=[]] - Array of peer URLs
34
+ * @param {boolean} [config.radisk=true] - Enable radisk persistence
35
+ * @param {boolean} [config.localStorage=true] - Enable localStorage
36
+ * @param {string} [config.dataDir='radata'] - Data directory for Node.js
37
+ * @param {string} [config.privateKey] - Optional existing private key
38
+ * @param {string} [config.publicKey] - Optional existing public key
39
+ * @param {boolean} [config.strict=false] - Enable strict schema validation
40
+ */
11
41
  constructor(config) {
12
42
  super(config);
13
43
  this.gun = null;
14
44
  this.keyPair = null;
45
+ this.appName = config.appName || 'holosphere';
46
+
47
+ // New modules
48
+ this.references = null;
49
+ this.auth = null;
50
+ this.schemaValidator = null;
51
+
52
+ // Subscription tracking
53
+ this.subscriptions = new Map();
54
+ this.subscriptionCounter = 0;
55
+
56
+ // Write cache for immediate consistency
57
+ // Gun's readAll/map().once() doesn't immediately see new writes - this cache bridges that gap
58
+ this.writeCache = new Map(); // path -> Map(id -> {data, timestamp})
59
+ this.writeCacheTTL = 300000; // Cache entries expire after 5 minutes (increased from 30s)
60
+
61
+ // Pending writes queue for retry
62
+ this.pendingWrites = new Map(); // path -> {data, retries, lastAttempt}
63
+ this.maxWriteRetries = 5;
64
+ this.writeRetryInterval = 10000; // 10 seconds between retries
15
65
  }
16
66
 
17
67
  async init() {
18
68
  // Dynamically import Gun to avoid issues if not installed
19
69
  let Gun;
20
70
  try {
71
+ console.log('[gundb-backend] Importing Gun...');
21
72
  const gunModule = await import('gun');
22
73
  Gun = gunModule.default || gunModule;
74
+ console.log('[gundb-backend] Gun imported:', typeof Gun);
23
75
  } catch (error) {
24
76
  throw new Error(
25
77
  'GunDB backend requires the "gun" package. Install it with: npm install gun'
26
78
  );
27
79
  }
28
80
 
81
+ // In Node.js, Gun needs a file path for radisk persistence
82
+ // Default to 'radata' if not specified
83
+ const dataDir = this.config.dataDir || 'radata';
84
+
29
85
  const gunConfig = {
30
86
  peers: this.config.peers || [],
31
87
  radisk: this.config.radisk !== false,
32
88
  localStorage: this.config.localStorage !== false,
33
- file: this.config.dataDir,
89
+ file: dataDir,
34
90
  };
35
91
 
92
+ console.log('[gundb-backend] Gun config:', JSON.stringify(gunConfig));
93
+
36
94
  this.gun = Gun(gunConfig);
95
+ console.log('[gundb-backend] Gun instance created:', !!this.gun);
96
+
97
+ // Test basic Gun functionality
98
+ try {
99
+ const testKey = `_test_${Date.now()}`;
100
+ this.gun.get(testKey).put({ test: true }, (ack) => {
101
+ console.log('[gundb-backend] Gun test write ack:', ack);
102
+ });
103
+ console.log('[gundb-backend] Gun test write initiated');
104
+ } catch (e) {
105
+ console.error('[gundb-backend] Gun test write failed:', e.message);
106
+ }
107
+
108
+ // Add a small delay to let Gun initialize
109
+ await new Promise(resolve => setTimeout(resolve, 500));
37
110
 
38
111
  // Generate or use provided key pair using Gun's SEA
39
112
  try {
@@ -50,28 +123,253 @@ export class GunDBBackend extends StorageBackend {
50
123
  }
51
124
  } else {
52
125
  // SEA not available, use simple identifier
53
- this.publicKey = this.config.appName || 'gundb-user';
126
+ this.publicKey = this.appName;
54
127
  }
55
128
  } catch (error) {
56
129
  // SEA might not be loaded
57
- this.publicKey = this.config.appName || 'gundb-user';
130
+ this.publicKey = this.appName;
131
+ }
132
+
133
+ // Initialize modules
134
+ this.references = new GunReferenceHandler(this.appName);
135
+ this.auth = new GunAuth(this.gun, this.appName);
136
+ this.schemaValidator = new GunSchemaValidator({
137
+ strict: this.config.strict || false,
138
+ cacheMaxAge: this.config.schemaCacheMaxAge || 3600000
139
+ });
140
+
141
+ // Try to initialize schema validator (may fail if AJV not installed)
142
+ await this.schemaValidator.init();
143
+ }
144
+
145
+ // ============================================================================
146
+ // WRITE CACHE (for immediate consistency)
147
+ // ============================================================================
148
+
149
+ /**
150
+ * Add item to the local write cache for immediate consistency
151
+ * @private
152
+ */
153
+ _addToWriteCache(path, data) {
154
+ if (!data || !data.id) return;
155
+
156
+ // Extract the parent path (without the data id)
157
+ const parentPath = path.substring(0, path.lastIndexOf('/'));
158
+ if (!parentPath) return;
159
+
160
+ if (!this.writeCache.has(parentPath)) {
161
+ this.writeCache.set(parentPath, new Map());
162
+ }
163
+
164
+ const pathCache = this.writeCache.get(parentPath);
165
+ pathCache.set(data.id.toString(), {
166
+ data: data,
167
+ timestamp: Date.now()
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Remove item from write cache (e.g., on delete)
173
+ * @private
174
+ */
175
+ _removeFromWriteCache(path, id) {
176
+ // Extract the parent path
177
+ const parentPath = path.substring(0, path.lastIndexOf('/'));
178
+ const pathCache = this.writeCache.get(parentPath);
179
+ if (pathCache) {
180
+ pathCache.delete(id.toString());
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Get cached writes for a path, filtering out expired entries
186
+ * @private
187
+ */
188
+ _getWriteCacheEntries(path) {
189
+ const pathCache = this.writeCache.get(path);
190
+ if (!pathCache) return [];
191
+
192
+ const now = Date.now();
193
+ const validEntries = [];
194
+
195
+ for (const [id, entry] of pathCache) {
196
+ if (now - entry.timestamp < this.writeCacheTTL) {
197
+ validEntries.push(entry.data);
198
+ } else {
199
+ // Clean up expired entries
200
+ pathCache.delete(id);
201
+ }
202
+ }
203
+
204
+ return validEntries;
205
+ }
206
+
207
+ /**
208
+ * Merge cached writes with results from Gun
209
+ * @private
210
+ */
211
+ _mergeWithWriteCache(path, gunResults) {
212
+ const cachedWrites = this._getWriteCacheEntries(path);
213
+ if (cachedWrites.length === 0) return gunResults;
214
+
215
+ // Create a map by ID for deduplication
216
+ const resultMap = new Map();
217
+
218
+ // Add Gun results first
219
+ for (const item of gunResults) {
220
+ if (item && item.id) {
221
+ resultMap.set(item.id.toString(), item);
222
+ }
223
+ }
224
+
225
+ // Overlay cached writes (they're more recent)
226
+ for (const item of cachedWrites) {
227
+ if (item && item.id && !item._deleted) {
228
+ resultMap.set(item.id.toString(), item);
229
+ } else if (item && item.id && item._deleted) {
230
+ // Remove deleted items
231
+ resultMap.delete(item.id.toString());
232
+ }
233
+ }
234
+
235
+ return Array.from(resultMap.values());
236
+ }
237
+
238
+ /**
239
+ * Clear write cache for a specific path or all paths
240
+ * @param {string} [path] - Optional path to clear, clears all if not provided
241
+ */
242
+ clearWriteCache(path = null) {
243
+ if (path) {
244
+ this.writeCache.delete(path);
245
+ } else {
246
+ this.writeCache.clear();
58
247
  }
59
248
  }
60
249
 
250
+ // ============================================================================
251
+ // PATH BUILDING
252
+ // ============================================================================
253
+
61
254
  buildPath(appName, holonId, lensName, key = null) {
62
255
  return wrapper.buildPath(appName, holonId, lensName, key);
63
256
  }
64
257
 
258
+ buildGlobalPath(tableName, key = null) {
259
+ return wrapper.buildGlobalPath(this.appName, tableName, key);
260
+ }
261
+
262
+ // ============================================================================
263
+ // BASIC CRUD OPERATIONS
264
+ // ============================================================================
265
+
65
266
  async write(path, data, options = {}) {
66
- return wrapper.write(this.gun, path, data);
267
+ // Validate against schema if strict mode
268
+ if (this.schemaValidator && this.schemaValidator.isStrict()) {
269
+ const pathParts = path.split('/');
270
+ if (pathParts.length >= 3) {
271
+ const lens = pathParts[2];
272
+ // Skip validation for references
273
+ if (!this.isReference(data)) {
274
+ const result = await this.schemaValidator.validateData(
275
+ this.gun, this.appName, lens, data
276
+ );
277
+ if (!result.valid) {
278
+ throw new Error(`Schema validation failed: ${JSON.stringify(result.errors)}`);
279
+ }
280
+ }
281
+ }
282
+ }
283
+
284
+ // Add to write cache FIRST for immediate consistency
285
+ // This ensures readAll returns the new data even if Gun write is slow/times out
286
+ this._addToWriteCache(path, data);
287
+
288
+ // Try to write to Gun with retry on timeout
289
+ const result = await this._writeWithRetry(path, data);
290
+
291
+ return result;
292
+ }
293
+
294
+ /**
295
+ * Write to Gun with automatic retry on timeout
296
+ * @private
297
+ */
298
+ async _writeWithRetry(path, data, attempt = 0) {
299
+ const result = await wrapper.write(this.gun, path, data);
300
+
301
+ if (result.timeout && attempt < this.maxWriteRetries) {
302
+ // Queue for background retry
303
+ this.pendingWrites.set(path, {
304
+ data,
305
+ retries: attempt + 1,
306
+ lastAttempt: Date.now()
307
+ });
308
+
309
+ // Schedule retry
310
+ this._scheduleRetry(path);
311
+ } else if (!result.timeout) {
312
+ // Success - remove from pending
313
+ this.pendingWrites.delete(path);
314
+ }
315
+
316
+ return result;
317
+ }
318
+
319
+ /**
320
+ * Schedule a background retry for a pending write
321
+ * @private
322
+ */
323
+ _scheduleRetry(path) {
324
+ setTimeout(async () => {
325
+ const pending = this.pendingWrites.get(path);
326
+ if (!pending) return;
327
+
328
+ if (pending.retries >= this.maxWriteRetries) {
329
+ console.warn(`[gundb-backend] Max retries reached for: ${path}`);
330
+ this.pendingWrites.delete(path);
331
+ return;
332
+ }
333
+
334
+ console.log(`[gundb-backend] Retrying write (attempt ${pending.retries + 1}): ${path}`);
335
+ await this._writeWithRetry(path, pending.data, pending.retries);
336
+ }, this.writeRetryInterval);
67
337
  }
68
338
 
69
339
  async read(path, options = {}) {
70
- return wrapper.read(this.gun, path);
340
+ const data = await wrapper.read(this.gun, path);
341
+
342
+ // Resolve references if requested
343
+ if (data && options.resolveReferences && this.isReference(data)) {
344
+ return this.resolveReference(data);
345
+ }
346
+
347
+ return data;
71
348
  }
72
349
 
73
350
  async readAll(path, options = {}) {
74
- return wrapper.readAll(this.gun, path);
351
+ const gunItems = await wrapper.readAll(this.gun, path);
352
+
353
+ // Merge with write cache for immediate consistency
354
+ const items = this._mergeWithWriteCache(path, gunItems);
355
+
356
+ // Resolve references if requested
357
+ if (options.resolveReferences) {
358
+ const resolved = [];
359
+ for (const item of items) {
360
+ if (this.isReference(item)) {
361
+ const resolvedItem = await this.resolveReference(item);
362
+ if (resolvedItem) {
363
+ resolved.push(resolvedItem);
364
+ }
365
+ } else {
366
+ resolved.push(item);
367
+ }
368
+ }
369
+ return resolved;
370
+ }
371
+
372
+ return items;
75
373
  }
76
374
 
77
375
  async update(path, updates) {
@@ -79,11 +377,27 @@ export class GunDBBackend extends StorageBackend {
79
377
  }
80
378
 
81
379
  async delete(path) {
82
- return wrapper.deleteData(this.gun, path);
380
+ const result = await wrapper.deleteData(this.gun, path);
381
+
382
+ // Extract id from path and mark as deleted in cache
383
+ const pathParts = path.split('/');
384
+ const id = pathParts[pathParts.length - 1];
385
+ if (id) {
386
+ // Add tombstone to cache so readAll doesn't return this item
387
+ const parentPath = path.substring(0, path.lastIndexOf('/'));
388
+ if (!this.writeCache.has(parentPath)) {
389
+ this.writeCache.set(parentPath, new Map());
390
+ }
391
+ this.writeCache.get(parentPath).set(id.toString(), {
392
+ data: { id, _deleted: true },
393
+ timestamp: Date.now()
394
+ });
395
+ }
396
+
397
+ return result;
83
398
  }
84
399
 
85
400
  async deleteAll(path) {
86
- // Gun doesn't have a native deleteAll, so we iterate and delete
87
401
  const items = await this.readAll(path);
88
402
  let count = 0;
89
403
 
@@ -98,58 +412,343 @@ export class GunDBBackend extends StorageBackend {
98
412
  return { success: true, count };
99
413
  }
100
414
 
415
+ // ============================================================================
416
+ // GLOBAL TABLE OPERATIONS
417
+ // ============================================================================
418
+
419
+ async writeGlobal(tableName, data) {
420
+ // Add to write cache FIRST for immediate consistency
421
+ // This ensures readAllGlobal returns the new data even if Gun write is slow/times out
422
+ const path = this.buildGlobalPath(tableName, data.id);
423
+ this._addToWriteCache(path, data);
424
+
425
+ // Try to write to Gun with retry on timeout
426
+ const result = await this._writeGlobalWithRetry(tableName, data);
427
+
428
+ return result;
429
+ }
430
+
431
+ /**
432
+ * Write to global table with automatic retry on timeout
433
+ * @private
434
+ */
435
+ async _writeGlobalWithRetry(tableName, data, attempt = 0) {
436
+ const path = this.buildGlobalPath(tableName, data.id);
437
+ const result = await wrapper.writeGlobal(this.gun, this.appName, tableName, data);
438
+
439
+ if (result.timeout && attempt < this.maxWriteRetries) {
440
+ // Queue for background retry
441
+ this.pendingWrites.set(path, {
442
+ data: { tableName, data },
443
+ isGlobal: true,
444
+ retries: attempt + 1,
445
+ lastAttempt: Date.now()
446
+ });
447
+
448
+ // Schedule retry
449
+ this._scheduleGlobalRetry(path, tableName);
450
+ } else if (!result.timeout) {
451
+ // Success - remove from pending
452
+ this.pendingWrites.delete(path);
453
+ }
454
+
455
+ return result;
456
+ }
457
+
458
+ /**
459
+ * Schedule a background retry for a pending global write
460
+ * @private
461
+ */
462
+ _scheduleGlobalRetry(path, tableName) {
463
+ setTimeout(async () => {
464
+ const pending = this.pendingWrites.get(path);
465
+ if (!pending || !pending.isGlobal) return;
466
+
467
+ if (pending.retries >= this.maxWriteRetries) {
468
+ console.warn(`[gundb-backend] Max retries reached for global: ${path}`);
469
+ this.pendingWrites.delete(path);
470
+ return;
471
+ }
472
+
473
+ console.log(`[gundb-backend] Retrying global write (attempt ${pending.retries + 1}): ${path}`);
474
+ await this._writeGlobalWithRetry(tableName, pending.data.data, pending.retries);
475
+ }, this.writeRetryInterval);
476
+ }
477
+
478
+ async readGlobal(tableName, key) {
479
+ return wrapper.readGlobal(this.gun, this.appName, tableName, key);
480
+ }
481
+
482
+ async readAllGlobal(tableName, timeout = 5000) {
483
+ const gunItems = await wrapper.readAllGlobal(this.gun, this.appName, tableName, timeout);
484
+
485
+ // Merge with write cache for immediate consistency
486
+ const path = this.buildGlobalPath(tableName);
487
+ return this._mergeWithWriteCache(path, gunItems);
488
+ }
489
+
490
+ async deleteGlobal(tableName, key) {
491
+ const result = await wrapper.deleteGlobal(this.gun, this.appName, tableName, key);
492
+
493
+ // Mark as deleted in cache
494
+ const path = this.buildGlobalPath(tableName);
495
+ if (!this.writeCache.has(path)) {
496
+ this.writeCache.set(path, new Map());
497
+ }
498
+ this.writeCache.get(path).set(key.toString(), {
499
+ data: { id: key, _deleted: true },
500
+ timestamp: Date.now()
501
+ });
502
+
503
+ return result;
504
+ }
505
+
506
+ async deleteAllGlobal(tableName) {
507
+ return wrapper.deleteAllGlobal(this.gun, this.appName, tableName);
508
+ }
509
+
510
+ // ============================================================================
511
+ // REFERENCE OPERATIONS
512
+ // ============================================================================
513
+
514
+ /**
515
+ * Create a reference to data
516
+ */
517
+ createReference(holon, lens, data) {
518
+ return this.references.createReference(holon, lens, data);
519
+ }
520
+
521
+ /**
522
+ * Check if data is a reference
523
+ */
524
+ isReference(data) {
525
+ return this.references.isReference(data);
526
+ }
527
+
528
+ /**
529
+ * Resolve a reference to get actual data
530
+ */
531
+ async resolveReference(reference, options = {}) {
532
+ return this.references.resolveReference(this.gun, reference, options);
533
+ }
534
+
535
+ /**
536
+ * Parse a soul path
537
+ */
538
+ parseSoulPath(soul) {
539
+ return this.references.parseSoulPath(soul);
540
+ }
541
+
542
+ /**
543
+ * Get soul for data
544
+ */
545
+ getSoul(holon, lens, key) {
546
+ return this.references.getSoul(holon, lens, key);
547
+ }
548
+
549
+ // ============================================================================
550
+ // AUTHENTICATION OPERATIONS
551
+ // ============================================================================
552
+
553
+ /**
554
+ * Authenticate for a holon
555
+ */
556
+ async authenticate(holonId, password) {
557
+ return this.auth.authenticate(holonId, password);
558
+ }
559
+
560
+ /**
561
+ * Create a new user
562
+ */
563
+ async createUser(holonId, password) {
564
+ return this.auth.createUser(holonId, password);
565
+ }
566
+
567
+ /**
568
+ * Logout current user
569
+ */
570
+ logout() {
571
+ this.auth.logout();
572
+ }
573
+
574
+ /**
575
+ * Check if authenticated
576
+ */
577
+ isAuthenticated() {
578
+ return this.auth.isAuthenticated();
579
+ }
580
+
581
+ /**
582
+ * Write to private storage
583
+ */
584
+ async writePrivate(lens, key, data) {
585
+ return this.auth.writePrivate(lens, key, data);
586
+ }
587
+
588
+ /**
589
+ * Read from private storage
590
+ */
591
+ async readPrivate(lens, key) {
592
+ return this.auth.readPrivate(lens, key);
593
+ }
594
+
595
+ /**
596
+ * Read all from private lens
597
+ */
598
+ async readAllPrivate(lens, timeout = 2000) {
599
+ return this.auth.readAllPrivate(lens, timeout);
600
+ }
601
+
602
+ /**
603
+ * Delete from private storage
604
+ */
605
+ async deletePrivate(lens, key) {
606
+ return this.auth.deletePrivate(lens, key);
607
+ }
608
+
609
+ // ============================================================================
610
+ // SCHEMA OPERATIONS
611
+ // ============================================================================
612
+
613
+ /**
614
+ * Set a schema for a lens
615
+ */
616
+ async setSchema(lens, schema) {
617
+ return this.schemaValidator.setSchema(this.gun, this.appName, lens, schema);
618
+ }
619
+
620
+ /**
621
+ * Get a schema for a lens
622
+ */
623
+ async getSchema(lens, options = {}) {
624
+ return this.schemaValidator.getSchema(this.gun, this.appName, lens, options);
625
+ }
626
+
627
+ /**
628
+ * Get all schemas
629
+ */
630
+ async getAllSchemas() {
631
+ return this.schemaValidator.getAllSchemas(this.gun, this.appName);
632
+ }
633
+
634
+ /**
635
+ * Delete a schema
636
+ */
637
+ async deleteSchema(lens) {
638
+ return this.schemaValidator.deleteSchema(this.gun, this.appName, lens);
639
+ }
640
+
641
+ /**
642
+ * Validate data against a schema
643
+ */
644
+ validate(schema, data) {
645
+ return this.schemaValidator.validate(schema, data);
646
+ }
647
+
648
+ /**
649
+ * Validate data against a lens schema
650
+ */
651
+ async validateData(lens, data) {
652
+ return this.schemaValidator.validateData(this.gun, this.appName, lens, data);
653
+ }
654
+
655
+ /**
656
+ * Clear schema cache
657
+ */
658
+ clearSchemaCache(lens = null) {
659
+ this.schemaValidator.clearCache(lens);
660
+ }
661
+
662
+ // ============================================================================
663
+ // SUBSCRIPTIONS
664
+ // ============================================================================
665
+
101
666
  async subscribe(path, callback, options = {}) {
102
- // Determine if this is a prefix subscription (no key) or single item
667
+ const subscriptionId = ++this.subscriptionCounter;
103
668
  const pathParts = path.split('/');
104
669
  const isPrefix = pathParts.length <= 3;
105
670
 
671
+ const subscription = {
672
+ id: subscriptionId,
673
+ path,
674
+ active: true,
675
+ gunRef: null
676
+ };
677
+
106
678
  if (isPrefix) {
107
- // Subscribe to all items under this prefix
108
679
  const ref = this.gun.get(path);
109
- const handlers = [];
680
+ subscription.gunRef = ref;
681
+
682
+ ref.map().on(async (data, key) => {
683
+ if (!this.subscriptions.get(subscriptionId)?.active) return;
684
+ if (!data || key.startsWith('_') || data._deleted) return;
685
+
686
+ // Parse data
687
+ let parsed = wrapper.parse(data);
688
+ if (!parsed) return;
689
+
690
+ // Resolve references if requested
691
+ if (options.resolveReferences && this.isReference(parsed)) {
692
+ parsed = await this.resolveReference(parsed);
693
+ }
110
694
 
111
- ref.map().on((data, key) => {
112
- if (data && !key.startsWith('_') && !data._deleted) {
113
- callback(data, key);
695
+ if (parsed) {
696
+ callback(parsed, key);
114
697
  }
115
698
  });
699
+ } else {
700
+ const ref = this.gun.get(path);
701
+ subscription.gunRef = ref;
116
702
 
117
- // Store reference for cleanup
118
- handlers.push(ref);
703
+ ref.on(async (data, key) => {
704
+ if (!this.subscriptions.get(subscriptionId)?.active) return;
705
+ if (!data) return;
119
706
 
120
- return {
121
- unsubscribe: () => {
122
- handlers.forEach(h => {
123
- try {
124
- h.off();
125
- } catch (e) {
126
- // Ignore cleanup errors
127
- }
128
- });
129
- },
130
- };
131
- } else {
132
- // Subscribe to single item
133
- const unsubFn = wrapper.subscribe(this.gun, path, callback);
134
- return {
135
- unsubscribe: typeof unsubFn === 'function' ? unsubFn : () => {},
136
- };
707
+ let parsed = wrapper.parse(data);
708
+ if (!parsed || parsed._deleted) return;
709
+
710
+ if (options.resolveReferences && this.isReference(parsed)) {
711
+ parsed = await this.resolveReference(parsed);
712
+ }
713
+
714
+ if (parsed) {
715
+ callback(parsed, key);
716
+ }
717
+ });
137
718
  }
719
+
720
+ this.subscriptions.set(subscriptionId, subscription);
721
+
722
+ return {
723
+ id: subscriptionId,
724
+ unsubscribe: () => {
725
+ const sub = this.subscriptions.get(subscriptionId);
726
+ if (sub) {
727
+ sub.active = false;
728
+ if (sub.gunRef) {
729
+ try {
730
+ sub.gunRef.off();
731
+ } catch (e) {}
732
+ }
733
+ this.subscriptions.delete(subscriptionId);
734
+ }
735
+ }
736
+ };
138
737
  }
139
738
 
739
+ // ============================================================================
740
+ // EXPORT/IMPORT
741
+ // ============================================================================
742
+
140
743
  async exportData(pathPrefix = '') {
141
744
  const records = [];
142
-
143
- // Get the app-level data
144
- const appName = this.config.appName || 'holosphere';
145
- const basePath = pathPrefix || appName;
745
+ const basePath = pathPrefix || this.appName;
146
746
 
147
747
  try {
148
748
  const items = await gunMap(this.gun.get(basePath), 2000);
149
749
 
150
750
  for (const [key, data] of Object.entries(items)) {
151
751
  if (!key.startsWith('_') && data && typeof data === 'object' && !data._deleted) {
152
- // Recursively collect nested data
153
752
  await this._collectRecords(basePath, key, data, records);
154
753
  }
155
754
  }
@@ -164,14 +763,12 @@ export class GunDBBackend extends StorageBackend {
164
763
  const currentPath = `${basePath}/${key}`;
165
764
 
166
765
  if (data.id) {
167
- // This is a leaf data node
168
766
  records.push({
169
767
  path: currentPath,
170
768
  data: this._cleanGunData(data),
171
769
  timestamp: data._meta?.timestamp || Date.now(),
172
770
  });
173
771
  } else {
174
- // This might be a nested structure, explore further
175
772
  try {
176
773
  const nested = await gunMap(this.gun.get(currentPath), 500);
177
774
  for (const [nestedKey, nestedData] of Object.entries(nested)) {
@@ -179,14 +776,11 @@ export class GunDBBackend extends StorageBackend {
179
776
  await this._collectRecords(currentPath, nestedKey, nestedData, records);
180
777
  }
181
778
  }
182
- } catch (e) {
183
- // Ignore nested exploration errors
184
- }
779
+ } catch (e) {}
185
780
  }
186
781
  }
187
782
 
188
783
  _cleanGunData(data) {
189
- // Remove Gun's internal metadata
190
784
  const cleaned = { ...data };
191
785
  delete cleaned['_'];
192
786
  return cleaned;
@@ -208,14 +802,59 @@ export class GunDBBackend extends StorageBackend {
208
802
  return results;
209
803
  }
210
804
 
805
+ // ============================================================================
806
+ // LIFECYCLE
807
+ // ============================================================================
808
+
211
809
  close() {
212
- // Gun doesn't have explicit close, but we can try to clean up
810
+ // 1. Unsubscribe all active subscriptions
811
+ for (const [id, subscription] of this.subscriptions) {
812
+ if (subscription.active) {
813
+ subscription.active = false;
814
+ if (subscription.gunRef) {
815
+ try {
816
+ subscription.gunRef.off();
817
+ } catch (e) {}
818
+ }
819
+ }
820
+ }
821
+ this.subscriptions.clear();
822
+
823
+ // 2. Clear schema cache
824
+ if (this.schemaValidator) {
825
+ this.schemaValidator.clearCache();
826
+ }
827
+
828
+ // 3. Clear write cache
829
+ this.writeCache.clear();
830
+
831
+ // 4. Logout auth
832
+ if (this.auth) {
833
+ this.auth.logout();
834
+ }
835
+
836
+ // 5. Clean up Gun connections
213
837
  if (this.gun) {
214
838
  try {
215
- // Attempt to close any connections
839
+ // Clean up mesh connections
840
+ const mesh = this.gun.back('opt.mesh');
841
+ if (mesh) {
842
+ if (mesh.way) {
843
+ Object.values(mesh.way).forEach(conn => {
844
+ if (conn?.wire?.close) conn.wire.close();
845
+ });
846
+ }
847
+ if (mesh.opt?.peers) mesh.opt.peers = {};
848
+ }
849
+
850
+ // Close web server if present
851
+ const server = this.gun.back('opt.web');
852
+ if (server?.close) server.close();
853
+
854
+ // Turn off all listeners
216
855
  this.gun.off();
217
- } catch (e) {
218
- // Ignore cleanup errors
856
+ } catch (error) {
857
+ console.warn('Error during Gun cleanup:', error);
219
858
  }
220
859
  }
221
860
  }
@@ -226,6 +865,9 @@ export class GunDBBackend extends StorageBackend {
226
865
  publicKey: this.publicKey,
227
866
  peers: this.config.peers || [],
228
867
  connected: !!this.gun,
868
+ authenticated: this.isAuthenticated(),
869
+ subscriptionCount: this.subscriptions.size,
870
+ schemaValidationEnabled: this.schemaValidator?.isStrict() || false
229
871
  };
230
872
  }
231
873
  }