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,17 +1,30 @@
1
1
  /**
2
- * GunDB Storage Wrapper with radisk persistence
3
- * Handles path construction and CRUD operations
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
4
9
  */
5
10
 
6
11
  import { gunPromise, gunPut, gunCollect } from './gun-async.js';
7
12
 
13
+ // ============================================================================
14
+ // PATH BUILDERS
15
+ // ============================================================================
16
+
8
17
  /**
9
- * Build Gun path from components
18
+ * Build Gun path from components.
19
+ *
10
20
  * @param {string} appname - Application namespace
11
21
  * @param {string} holon - Holon ID (H3 or URI)
12
22
  * @param {string} lens - Lens name
13
- * @param {string} key - Data key (optional)
23
+ * @param {string} [key=null] - Data key (optional)
14
24
  * @returns {string} Gun path
25
+ * @example
26
+ * const path = buildPath('myapp', 'holon123', 'items', 'item1');
27
+ * // Returns: 'myapp/holon123/items/item1'
15
28
  */
16
29
  export function buildPath(appname, holon, lens, key = null) {
17
30
  // Encode components to handle special characters
@@ -26,39 +39,207 @@ export function buildPath(appname, holon, lens, key = null) {
26
39
  }
27
40
 
28
41
  /**
29
- * Encode path component to handle special characters
42
+ * Build Gun path for global tables (app-wide data not tied to holons).
43
+ *
44
+ * @param {string} appname - Application namespace
45
+ * @param {string} tableName - Global table name (e.g., 'schemas', 'federation')
46
+ * @param {string} [key=null] - Data key (optional)
47
+ * @returns {string} Gun path
48
+ * @example
49
+ * const path = buildGlobalPath('myapp', 'schemas', 'user');
50
+ * // Returns: 'myapp/schemas/user'
51
+ */
52
+ export function buildGlobalPath(appname, tableName, key = null) {
53
+ const encodedTable = encodePathComponent(tableName);
54
+ if (key) {
55
+ const encodedKey = encodePathComponent(key);
56
+ return `${appname}/${encodedTable}/${encodedKey}`;
57
+ }
58
+ return `${appname}/${encodedTable}`;
59
+ }
60
+
61
+ /**
62
+ * Encode path component to handle special characters.
63
+ *
30
64
  * @private
65
+ * @param {string} component - Component to encode
66
+ * @returns {string} Encoded component
31
67
  */
32
68
  function encodePathComponent(component) {
33
69
  return encodeURIComponent(component).replace(/%2F/g, '/');
34
70
  }
35
71
 
36
72
  /**
37
- * Write data to Gun with radisk persistence
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
+ *
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
101
+ */
102
+ function serializeForGun(data) {
103
+ return JSON.stringify(data);
104
+ }
105
+
106
+ /**
107
+ * Deserialize data from GunDB storage.
108
+ *
109
+ * Handles multiple formats:
110
+ * - Direct JSON string (holosphere original - now default)
111
+ * - _json wrapped format (holosphere2 legacy)
112
+ * - Gun internal references (_["#"])
113
+ * - Gun node data (_[">"])
114
+ * - Plain objects
115
+ *
116
+ * @private
117
+ * @param {*} data - Raw data from Gun
118
+ * @returns {Object|null} Parsed data or null
119
+ */
120
+ function deserializeFromGun(data) {
121
+ if (!data) {
122
+ return null;
123
+ }
124
+
125
+ try {
126
+ // Format 1: String data (holosphere original stores JSON as string directly)
127
+ if (typeof data === 'string') {
128
+ try {
129
+ return JSON.parse(data);
130
+ } catch (e) {
131
+ // Not JSON, return as-is
132
+ return data;
133
+ }
134
+ }
135
+
136
+ // Format 2: _json wrapped format (holosphere2 default)
137
+ if (data._json && typeof data._json === 'string') {
138
+ try {
139
+ return JSON.parse(data._json);
140
+ } catch (e) {
141
+ console.warn('Failed to parse _json field:', e);
142
+ return null;
143
+ }
144
+ }
145
+
146
+ // Format 3: Gun internal reference (_["#"]) - this indicates a Gun reference
147
+ // The actual data retrieval should happen via resolveReference, we just identify it here
148
+ if (data._ && data._['#']) {
149
+ // This is a Gun reference - return as-is for reference resolution
150
+ // The caller should check isReference() and handle appropriately
151
+ return data;
152
+ }
153
+
154
+ // Format 4: Gun node data with timestamps (_[">"])
155
+ // Gun stores metadata in _.> - find the actual value
156
+ if (data._ && data._['>']) {
157
+ const nodeValue = Object.entries(data).find(([k, v]) => k !== '_' && typeof v === 'string');
158
+ if (nodeValue) {
159
+ try {
160
+ return JSON.parse(nodeValue[1]);
161
+ } catch (e) {
162
+ return nodeValue[1];
163
+ }
164
+ }
165
+ }
166
+
167
+ // Format 5: Plain object - clean Gun metadata and return
168
+ if (typeof data === 'object' && data !== null) {
169
+ const cleaned = { ...data };
170
+ delete cleaned['_'];
171
+
172
+ // Check if any remaining keys - if empty after removing _, return null
173
+ if (Object.keys(cleaned).length === 0) {
174
+ return null;
175
+ }
176
+
177
+ return cleaned;
178
+ }
179
+
180
+ return data;
181
+ } catch (error) {
182
+ console.warn('Error deserializing Gun data:', error);
183
+ return data; // Return raw data as fallback
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Write data to Gun with radisk persistence.
189
+ *
38
190
  * @param {Object} gun - Gun instance
39
191
  * @param {string} path - Gun path
40
192
  * @param {Object} data - Data to write
41
- * @returns {Promise<boolean>} Success indicator
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');
42
197
  */
43
198
  export async function write(gun, path, data) {
44
199
  try {
45
- await gunPut(gun.get(path), data, 2000);
46
- // Delay to allow Gun to propagate the write (50ms for better reliability)
47
- await new Promise(resolve => setTimeout(resolve, 50));
48
- return true;
200
+ const serialized = serializeForGun(data);
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 };
49
214
  } catch (error) {
215
+ console.error('[gun-wrapper] write error:', error);
50
216
  throw error;
51
217
  }
52
218
  }
53
219
 
54
220
  /**
55
- * Read data from Gun
221
+ * Read data from Gun.
222
+ *
56
223
  * @param {Object} gun - Gun instance
57
224
  * @param {string} path - Gun path
58
- * @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);
59
229
  */
60
230
  export async function read(gun, path) {
61
- const data = await gunPromise(gun.get(path), 2000);
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');
237
+
238
+ if (!rawData) {
239
+ return null;
240
+ }
241
+
242
+ const data = deserializeFromGun(rawData);
62
243
 
63
244
  // Return null if deleted or not found
64
245
  if (!data || data._deleted) {
@@ -69,48 +250,158 @@ export async function read(gun, path) {
69
250
  }
70
251
 
71
252
  /**
72
- * Read all data under a path (lens query)
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
+ *
73
257
  * @param {Object} gun - Gun instance
74
258
  * @param {string} path - Gun path
259
+ * @param {number} [timeout=5000] - Maximum timeout in ms
75
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`);
76
264
  */
77
- export async function readAll(gun, path) {
78
- const results = await gunCollect(gun.get(path), 1000);
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
+
269
+ return new Promise((resolve) => {
270
+ const output = new Map();
271
+ let settled = false;
272
+ let expectedCount = 0;
273
+ let receivedCount = 0;
274
+
275
+ const ref = getGunPath(gun, path);
276
+ console.log('[gun-wrapper] readAll ref soul:', ref?._.get);
277
+
278
+ const tryResolve = () => {
279
+ if (settled) return;
280
+ if (expectedCount > 0 && receivedCount >= expectedCount) {
281
+ settled = true;
282
+ console.log('[gun-wrapper] readAll resolved with', output.size, 'items');
283
+ resolve(Array.from(output.values()));
284
+ }
285
+ };
286
+
287
+ const parseItem = (data) => {
288
+ return deserializeFromGun(data);
289
+ };
290
+
291
+ // Step 1: Get the parent data to count expected items
292
+ ref.once((parentData) => {
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);
297
+
298
+ if (!parentData) {
299
+ settled = true;
300
+ console.log('[gun-wrapper] readAll: no parent data, returning empty');
301
+ resolve([]);
302
+ return;
303
+ }
304
+
305
+ // Get all keys except Gun metadata
306
+ const keys = Object.keys(parentData).filter(k => k !== '_');
307
+ console.log('[gun-wrapper] readAll keys:', keys);
308
+
309
+ if (keys.length === 0) {
310
+ settled = true;
311
+ console.log('[gun-wrapper] readAll: no keys, returning empty');
312
+ resolve([]);
313
+ return;
314
+ }
315
+
316
+ // Count expected items and check for inline data
317
+ const referenceKeys = [];
318
+
319
+ for (const key of keys) {
320
+ const rawItem = parentData[key];
321
+ if (!rawItem) continue;
322
+
323
+ // Check if it's a Gun reference (soul) - need to fetch separately
324
+ if (typeof rawItem === 'object' && rawItem['#']) {
325
+ referenceKeys.push(key);
326
+ continue;
327
+ }
328
+
329
+ // Try to parse inline data (don't count yet - will count in map().once() phase)
330
+ const item = parseItem(rawItem);
331
+ if (item && item.id && !item._deleted) {
332
+ output.set(item.id, item);
333
+ }
334
+ }
335
+
336
+ // Set expected count: ALL keys that could have data (references + inline)
337
+ // We use total keys because map().once() will fire for all of them
338
+ expectedCount = keys.length;
339
+
340
+ // If no keys, we're done (shouldn't happen but be safe)
341
+ if (expectedCount === 0) {
342
+ settled = true;
343
+ resolve(Array.from(output.values()));
344
+ return;
345
+ }
346
+
347
+ // Step 2: Use map().once() to resolve all items, counting as we go
348
+ ref.map().once((data, key) => {
349
+ if (settled || !data || key === '_') return;
350
+
351
+ const item = parseItem(data);
352
+ if (item && item.id && !item._deleted) {
353
+ // Add to output if not already there (inline items already added)
354
+ if (!output.has(item.id)) {
355
+ output.set(item.id, item);
356
+ }
357
+ }
358
+ // Count every item received (inline or reference)
359
+ receivedCount++;
360
+ tryResolve();
361
+ });
362
+ });
79
363
 
80
- // Filter out deleted items and Gun metadata
81
- return results
82
- .filter(({ data, key }) => {
83
- if (!data || typeof data !== 'object') return false;
84
- if (key.startsWith('_')) return false;
85
- if (data._deleted) return false;
86
- return true;
87
- })
88
- .map(({ data }) => data);
364
+ // Fallback timeout in case count-based resolution fails
365
+ setTimeout(() => {
366
+ if (!settled) {
367
+ settled = true;
368
+ resolve(Array.from(output.values()));
369
+ }
370
+ }, timeout);
371
+ });
89
372
  }
90
373
 
91
374
  /**
92
- * Update data (merge fields)
375
+ * Update data (merge fields).
376
+ *
93
377
  * @param {Object} gun - Gun instance
94
378
  * @param {string} path - Gun path
95
379
  * @param {Object} updates - Fields to update
96
380
  * @returns {Promise<boolean>} Success indicator
381
+ * @example
382
+ * const success = await update(gun, 'myapp/holon1/items/item1', { status: 'active' });
97
383
  */
98
384
  export async function update(gun, path, updates) {
99
- const existing = await gunPromise(gun.get(path));
385
+ const rawData = await gunPromise(getGunPath(gun, path));
100
386
 
101
- if (!existing || !existing.id || existing._deleted) {
102
- return false; // Not found or deleted
387
+ if (!rawData) {
388
+ return false; // Not found
103
389
  }
104
390
 
105
- // Remove Gun metadata before merging
106
- const cleanExisting = { ...existing };
107
- delete cleanExisting['_'];
391
+ // Deserialize existing data
392
+ const existing = deserializeFromGun(rawData);
393
+ if (!existing || !existing.id || existing._deleted) {
394
+ return false;
395
+ }
108
396
 
109
397
  // Merge updates
110
- const merged = { ...cleanExisting, ...updates };
398
+ const merged = { ...existing, ...updates };
111
399
 
112
400
  try {
113
- await gunPut(gun.get(path), merged);
401
+ const serialized = serializeForGun(merged);
402
+ await gunPut(getGunPath(gun, path), serialized, 2000);
403
+ // Add delay for propagation
404
+ await new Promise(resolve => setTimeout(resolve, 200));
114
405
  return true;
115
406
  } catch (error) {
116
407
  throw error;
@@ -118,28 +409,34 @@ export async function update(gun, path, updates) {
118
409
  }
119
410
 
120
411
  /**
121
- * Delete data (tombstone)
412
+ * Delete data (tombstone).
413
+ *
122
414
  * @param {Object} gun - Gun instance
123
415
  * @param {string} path - Gun path
124
416
  * @returns {Promise<boolean>} Success indicator
417
+ * @example
418
+ * const deleted = await deleteData(gun, 'myapp/holon1/items/item1');
125
419
  */
126
420
  export async function deleteData(gun, path) {
127
421
  try {
128
- // Gun requires tombstone to be an object with _deleted flag
129
- // First read existing data to preserve metadata
130
- const existing = await gunPromise(gun.get(path));
131
- if (!existing) {
422
+ // First read existing data to get the id
423
+ const rawData = await gunPromise(getGunPath(gun, path));
424
+ if (!rawData) {
132
425
  return true; // Already deleted/doesn't exist
133
426
  }
134
427
 
135
- // Create tombstone object
428
+ const existing = deserializeFromGun(rawData);
429
+
430
+ // Create tombstone object and serialize it
136
431
  const tombstone = {
137
- id: existing.id,
432
+ id: existing?.id,
138
433
  _deleted: true,
139
434
  _deletedAt: Date.now()
140
435
  };
141
436
 
142
- await gunPut(gun.get(path), tombstone);
437
+ await gunPut(getGunPath(gun, path), serializeForGun(tombstone), 2000);
438
+ // Add delay for propagation
439
+ await new Promise(resolve => setTimeout(resolve, 200));
143
440
  return true;
144
441
  } catch (error) {
145
442
  throw error;
@@ -147,7 +444,8 @@ export async function deleteData(gun, path) {
147
444
  }
148
445
 
149
446
  /**
150
- * Delete all data under path prefix (tombstone)
447
+ * Delete all data under path prefix (tombstone).
448
+ *
151
449
  * @param {Object} gun - Gun instance
152
450
  * @param {string} path - Gun path prefix
153
451
  * @returns {Promise<Object>} Deletion results { success: boolean, count: number }
@@ -168,13 +466,19 @@ export async function deleteAll(gun, path) {
168
466
  }
169
467
 
170
468
  /**
171
- * Subscribe to data changes
469
+ * Subscribe to data changes.
470
+ *
172
471
  * @param {Object} gun - Gun instance
173
472
  * @param {string} path - Gun path
174
- * @param {Function} callback - Called on data changes
175
- * @param {Object} options - Subscription options
176
- * @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)
177
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();
178
482
  */
179
483
  export function subscribe(gun, path, callback, options = {}) {
180
484
  // Detect if this is a prefix subscription
@@ -183,11 +487,14 @@ export function subscribe(gun, path, callback, options = {}) {
183
487
 
184
488
  if (isPrefix) {
185
489
  // Subscribe to all items under this prefix
186
- const ref = gun.get(path);
490
+ const ref = getGunPath(gun, path);
187
491
 
188
492
  ref.map().on((data, key) => {
189
- if (data && !key.startsWith('_') && !data._deleted) {
190
- callback(data, key);
493
+ if (data && !key.startsWith('_')) {
494
+ const deserialized = deserializeFromGun(data);
495
+ if (deserialized && !deserialized._deleted) {
496
+ callback(deserialized, key);
497
+ }
191
498
  }
192
499
  });
193
500
 
@@ -202,9 +509,12 @@ export function subscribe(gun, path, callback, options = {}) {
202
509
  };
203
510
  } else {
204
511
  // Subscribe to single item
205
- const listener = gun.get(path).on((data, key) => {
206
- if (data && !data._deleted) {
207
- callback(data, key);
512
+ const listener = getGunPath(gun, path).on((data, key) => {
513
+ if (data) {
514
+ const deserialized = deserializeFromGun(data);
515
+ if (deserialized && !deserialized._deleted) {
516
+ callback(deserialized, key);
517
+ }
208
518
  }
209
519
  });
210
520
 
@@ -219,3 +529,114 @@ export function subscribe(gun, path, callback, options = {}) {
219
529
  };
220
530
  }
221
531
  }
532
+
533
+ // ============================================================================
534
+ // GLOBAL TABLE OPERATIONS
535
+ // ============================================================================
536
+
537
+ /**
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
+ *
542
+ * @param {Object} gun - Gun instance
543
+ * @param {string} appname - Application namespace
544
+ * @param {string} tableName - Global table name
545
+ * @param {Object} data - Data to write (must have 'id' field)
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' });
550
+ */
551
+ export async function writeGlobal(gun, appname, tableName, data) {
552
+ if (!data || !data.id) {
553
+ throw new Error('writeGlobal: data must have an id field');
554
+ }
555
+ const path = buildGlobalPath(appname, tableName, data.id);
556
+ // Use write function which includes the propagation delay
557
+ return write(gun, path, data);
558
+ }
559
+
560
+ /**
561
+ * Read data from a global table.
562
+ *
563
+ * @param {Object} gun - Gun instance
564
+ * @param {string} appname - Application namespace
565
+ * @param {string} tableName - Global table name
566
+ * @param {string} key - Data key
567
+ * @returns {Promise<Object|null>} Data or null if not found
568
+ */
569
+ export async function readGlobal(gun, appname, tableName, key) {
570
+ const path = buildGlobalPath(appname, tableName, key);
571
+ return read(gun, path);
572
+ }
573
+
574
+ /**
575
+ * Read all data from a global table.
576
+ *
577
+ * Uses same approach as readAll.
578
+ *
579
+ * @param {Object} gun - Gun instance
580
+ * @param {string} appname - Application namespace
581
+ * @param {string} tableName - Global table name
582
+ * @param {number} [timeout=2000] - Timeout in ms
583
+ * @returns {Promise<Object[]>} Array of data objects
584
+ */
585
+ export async function readAllGlobal(gun, appname, tableName, timeout = 2000) {
586
+ const path = buildGlobalPath(appname, tableName);
587
+ return readAll(gun, path);
588
+ }
589
+
590
+ /**
591
+ * Delete data from a global table
592
+ * @param {Object} gun - Gun instance
593
+ * @param {string} appname - Application namespace
594
+ * @param {string} tableName - Global table name
595
+ * @param {string} key - Data key
596
+ * @returns {Promise<boolean>} Success indicator
597
+ */
598
+ export async function deleteGlobal(gun, appname, tableName, key) {
599
+ const path = buildGlobalPath(appname, tableName, key);
600
+ return deleteData(gun, path);
601
+ }
602
+
603
+ /**
604
+ * Delete all data from a global table
605
+ * @param {Object} gun - Gun instance
606
+ * @param {string} appname - Application namespace
607
+ * @param {string} tableName - Global table name
608
+ * @returns {Promise<Object>} Deletion results { success: boolean, count: number }
609
+ */
610
+ export async function deleteAllGlobal(gun, appname, tableName) {
611
+ const path = buildGlobalPath(appname, tableName);
612
+ return deleteAll(gun, path);
613
+ }
614
+
615
+ // ============================================================================
616
+ // DATA PARSING UTILITIES
617
+ // ============================================================================
618
+
619
+ /**
620
+ * Parse data from Gun storage, handling various formats.
621
+ *
622
+ * Handles:
623
+ * - JSON string in _json field
624
+ * - Legacy object format
625
+ * - Gun references
626
+ *
627
+ * @param {*} rawData - Raw data from Gun
628
+ * @returns {Object|null} Parsed data or null
629
+ */
630
+ export function parse(rawData) {
631
+ return deserializeFromGun(rawData);
632
+ }
633
+
634
+ /**
635
+ * Serialize data for Gun storage.
636
+ *
637
+ * @param {Object} data - Data to serialize
638
+ * @returns {string} JSON string
639
+ */
640
+ export function serialize(data) {
641
+ return serializeForGun(data);
642
+ }