@pyric/cli 0.1.0-alpha.10 → 0.1.0-alpha.12

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 (498) hide show
  1. package/README.md.orig +2 -2
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +16 -0
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +16 -0
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/bridge/server/peer.d.ts +1 -1
  7. package/dist/bridge/server.d.ts +1 -1
  8. package/dist/bridge/server.js +1 -1
  9. package/dist/cli/index.d.ts +11 -0
  10. package/dist/cli/index.d.ts.map +1 -1
  11. package/dist/cli/index.js +13 -1
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/cli/init.d.ts +3 -3
  14. package/dist/cli/init.d.ts.map +1 -1
  15. package/dist/cli/init.js +5 -5
  16. package/dist/cli/init.js.map +1 -1
  17. package/dist/cli/serve.d.ts.map +1 -1
  18. package/dist/cli/serve.js +8 -2
  19. package/dist/cli/serve.js.map +1 -1
  20. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  21. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  22. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  23. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  24. package/dist/conformance/.generated/can-i-use.js +2 -2
  25. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  26. package/dist/conformance/.generated/conformance-docs.d.ts +12 -0
  27. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -0
  28. package/dist/conformance/.generated/conformance-docs.js +2 -0
  29. package/dist/conformance/.generated/conformance-docs.js.map +1 -0
  30. package/dist/conformance/docs.d.ts +6 -0
  31. package/dist/conformance/docs.d.ts.map +1 -0
  32. package/dist/conformance/docs.js +6 -0
  33. package/dist/conformance/docs.js.map +1 -0
  34. package/dist/remote/index.d.ts.map +1 -1
  35. package/dist/remote/index.js +1 -0
  36. package/dist/remote/index.js.map +1 -1
  37. package/dist/serve/activity-guard.d.ts +4 -0
  38. package/dist/serve/activity-guard.d.ts.map +1 -0
  39. package/dist/serve/activity-guard.js +22 -0
  40. package/dist/serve/activity-guard.js.map +1 -0
  41. package/dist/serve/activity-route.d.ts +4 -0
  42. package/dist/serve/activity-route.d.ts.map +1 -0
  43. package/dist/serve/activity-route.js +157 -0
  44. package/dist/serve/activity-route.js.map +1 -0
  45. package/dist/serve/activity-warning.d.ts +4 -0
  46. package/dist/serve/activity-warning.d.ts.map +1 -0
  47. package/dist/serve/activity-warning.js +21 -0
  48. package/dist/serve/activity-warning.js.map +1 -0
  49. package/dist/serve/bridge-mount.d.ts +5 -0
  50. package/dist/serve/bridge-mount.d.ts.map +1 -1
  51. package/dist/serve/bridge-mount.js +1 -0
  52. package/dist/serve/bridge-mount.js.map +1 -1
  53. package/dist/serve/docs-ui/404.html +3 -0
  54. package/dist/serve/docs-ui/_astro/{_slug_.DPUwShm2.css → _slug_.CXh9yTP1.css} +1 -1
  55. package/dist/serve/docs-ui/_astro/_slug_.DUci-duz.css +1 -0
  56. package/dist/serve/docs-ui/docs/_rhythm/index.html +2 -1
  57. package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +3 -2
  58. package/dist/serve/docs-ui/docs/agent/set-up-your-agent.md +1 -1
  59. package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +2 -1
  60. package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +2 -1
  61. package/dist/serve/docs-ui/docs/ai-compat/index.html +2 -1
  62. package/dist/serve/docs-ui/docs/api-reference/index.html +51 -49
  63. package/dist/serve/docs-ui/docs/api-reference.md +3 -3
  64. package/dist/serve/docs-ui/docs/app-compat/index.html +2 -1
  65. package/dist/serve/docs-ui/docs/auth-compat/index.html +2 -1
  66. package/dist/serve/docs-ui/docs/build/ai-logic/index.html +18 -3
  67. package/dist/serve/docs-ui/docs/build/ai-logic.md +30 -2
  68. package/dist/serve/docs-ui/docs/build/authentication/index.html +2 -1
  69. package/dist/serve/docs-ui/docs/build/authentication.md +1 -1
  70. package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +2 -1
  71. package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +46 -2
  72. package/dist/serve/docs-ui/docs/build/cloud-messaging.md +56 -1
  73. package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +2 -1
  74. package/dist/serve/docs-ui/docs/build/cloud-storage.md +1 -1
  75. package/dist/serve/docs-ui/docs/build/realtime-database/index.html +21 -3
  76. package/dist/serve/docs-ui/docs/build/realtime-database.md +25 -1
  77. package/dist/serve/docs-ui/docs/conformance-scores/index.html +2 -1
  78. package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +61 -28
  79. package/dist/serve/docs-ui/docs/create-pyric-reference-api.md +65 -20
  80. package/dist/serve/docs-ui/docs/database-compat/index.html +2 -1
  81. package/dist/serve/docs-ui/docs/firestore-compat/index.html +6 -5
  82. package/dist/serve/docs-ui/docs/firestore-compat.md +4 -4
  83. package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +2 -1
  84. package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +2 -1
  85. package/dist/serve/docs-ui/docs/get-started/start-building/index.html +4 -3
  86. package/dist/serve/docs-ui/docs/get-started/start-building.md +2 -2
  87. package/dist/serve/docs-ui/docs/index.json +979 -579
  88. package/dist/serve/docs-ui/docs/messaging-compat/index.html +2 -1
  89. package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +2 -1
  90. package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +2 -1
  91. package/dist/serve/docs-ui/docs/overview/index.html +2 -1
  92. package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +5 -4
  93. package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api.md +3 -4
  94. package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api/index.html +5 -4
  95. package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api.md +3 -4
  96. package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api/index.html +5 -4
  97. package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api.md +3 -4
  98. package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api/index.html +2503 -12
  99. package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api.md +2219 -8
  100. package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api/index.html +916 -0
  101. package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api.md +706 -0
  102. package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +4 -3
  103. package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api.md +2 -3
  104. package/dist/serve/docs-ui/docs/pyric-ai-reference-api/index.html +16 -11
  105. package/dist/serve/docs-ui/docs/pyric-ai-reference-api.md +14 -13
  106. package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +4 -3
  107. package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api.md +2 -3
  108. package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +7 -2
  109. package/dist/serve/docs-ui/docs/pyric-app-reference-api.md +5 -2
  110. package/dist/serve/docs-ui/docs/pyric-auth-reference-api/index.html +23 -12
  111. package/dist/serve/docs-ui/docs/pyric-auth-reference-api.md +15 -12
  112. package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +10 -48
  113. package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api.md +11 -24
  114. package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api/index.html +87 -97
  115. package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api.md +53 -65
  116. package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api/index.html +14 -15
  117. package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api.md +19 -28
  118. package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +4 -3
  119. package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api.md +2 -3
  120. package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +3 -2
  121. package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api.md +1 -2
  122. package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +51 -0
  123. package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api.md +36 -0
  124. package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +3 -2
  125. package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api.md +1 -2
  126. package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +3 -2
  127. package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api.md +1 -2
  128. package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api/index.html +3 -2
  129. package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api.md +1 -2
  130. package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +3 -2
  131. package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api.md +1 -2
  132. package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api/index.html +1067 -83
  133. package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api.md +1291 -160
  134. package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api/index.html +253 -157
  135. package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api.md +179 -85
  136. package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api/index.html +72 -7
  137. package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api.md +22 -7
  138. package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +33 -12
  139. package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api.md +15 -12
  140. package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +18 -17
  141. package/dist/serve/docs-ui/docs/pyric-database-reference-api.md +19 -22
  142. package/dist/serve/docs-ui/docs/pyric-firestore-reference-api/index.html +1512 -545
  143. package/dist/serve/docs-ui/docs/pyric-firestore-reference-api.md +1311 -316
  144. package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +5 -4
  145. package/dist/serve/docs-ui/docs/pyric-messaging-reference-api.md +3 -4
  146. package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +69 -369
  147. package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api.md +103 -216
  148. package/dist/serve/docs-ui/docs/pyric-rules-reference-api/index.html +10 -9
  149. package/dist/serve/docs-ui/docs/pyric-rules-reference-api.md +9 -10
  150. package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +8 -7
  151. package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api.md +6 -7
  152. package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +10 -9
  153. package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api.md +9 -10
  154. package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api/index.html +371 -884
  155. package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api.md +369 -883
  156. package/dist/serve/docs-ui/docs/pyric-storage-reference-api/index.html +25 -17
  157. package/dist/serve/docs-ui/docs/pyric-storage-reference-api.md +21 -19
  158. package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +3 -2
  159. package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api.md +1 -2
  160. package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +63 -776
  161. package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api.md +69 -510
  162. package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api/index.html +22 -21
  163. package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api.md +29 -30
  164. package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +15 -168
  165. package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api.md +17 -87
  166. package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api/index.html +6 -5
  167. package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api.md +5 -6
  168. package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +82 -970
  169. package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api.md +104 -479
  170. package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api/index.html +30 -29
  171. package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api.md +54 -55
  172. package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api/index.html +3 -2
  173. package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api.md +1 -2
  174. package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -4
  175. package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api.md +3 -4
  176. package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +9 -124
  177. package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api.md +7 -58
  178. package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api/index.html +24 -23
  179. package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api.md +31 -34
  180. package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +104 -1385
  181. package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api.md +133 -817
  182. package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api/index.html +34 -33
  183. package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api.md +37 -38
  184. package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +116 -1169
  185. package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api.md +142 -590
  186. package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api/index.html +4 -3
  187. package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api.md +3 -4
  188. package/dist/serve/docs-ui/docs/rules-compat/index.html +34 -1
  189. package/dist/serve/docs-ui/docs/rules-compat.md +32 -0
  190. package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +19 -2
  191. package/dist/serve/docs-ui/docs/secure/audit-your-rules.md +32 -0
  192. package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +2 -1
  193. package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +2 -1
  194. package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +2 -1
  195. package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript.md +1 -1
  196. package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +2 -1
  197. package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +2 -1
  198. package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +2 -1
  199. package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +2 -1
  200. package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +2 -1
  201. package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +2 -1
  202. package/dist/serve/docs-ui/docs/storage-compat/index.html +2 -1
  203. package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +2 -1
  204. package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +2 -1
  205. package/dist/serve/docs-ui/llms.txt +2 -1
  206. package/dist/serve/entries/ai.d.ts.map +1 -1
  207. package/dist/serve/entries/ai.js +39 -1
  208. package/dist/serve/entries/ai.js.map +1 -1
  209. package/dist/serve/entries/messaging-sw.d.ts.map +1 -1
  210. package/dist/serve/entries/messaging-sw.js +5 -1
  211. package/dist/serve/entries/messaging-sw.js.map +1 -1
  212. package/dist/serve/entries/messaging.d.ts.map +1 -1
  213. package/dist/serve/entries/messaging.js +7 -1
  214. package/dist/serve/entries/messaging.js.map +1 -1
  215. package/dist/serve/entries/runtime.d.ts.map +1 -1
  216. package/dist/serve/entries/runtime.js +20 -1
  217. package/dist/serve/entries/runtime.js.map +1 -1
  218. package/dist/serve/init-payload.d.ts +25 -0
  219. package/dist/serve/init-payload.d.ts.map +1 -1
  220. package/dist/serve/namespace.d.ts +39 -0
  221. package/dist/serve/namespace.d.ts.map +1 -1
  222. package/dist/serve/namespace.js +80 -1
  223. package/dist/serve/namespace.js.map +1 -1
  224. package/dist/serve/standalone-assets.d.ts +11 -9
  225. package/dist/serve/standalone-assets.d.ts.map +1 -1
  226. package/dist/serve/standalone-assets.js +6 -5
  227. package/dist/serve/standalone-assets.js.map +1 -1
  228. package/dist/serve/studio-ui/assets/{RulesCodeEditor-CXdSLKhO.js → RulesCodeEditor-CxVYcZXw.js} +1 -1
  229. package/dist/serve/studio-ui/assets/index-cpSfgQ7H.js +1218 -0
  230. package/dist/serve/studio-ui/assets/seed-DeuFKi4J.js +20 -0
  231. package/dist/serve/studio-ui/index.html +1 -1
  232. package/dist/serve/vite-plugin.d.ts +92 -15
  233. package/dist/serve/vite-plugin.d.ts.map +1 -1
  234. package/dist/serve/vite-plugin.js +281 -11
  235. package/dist/serve/vite-plugin.js.map +1 -1
  236. package/dist/serve/worker/activity-bootstrap.d.ts +8 -0
  237. package/dist/serve/worker/activity-bootstrap.d.ts.map +1 -0
  238. package/dist/serve/worker/activity-bootstrap.js +11 -0
  239. package/dist/serve/worker/activity-bootstrap.js.map +1 -0
  240. package/dist/serve/worker/client/connection.d.ts.map +1 -1
  241. package/dist/serve/worker/client/connection.js +17 -5
  242. package/dist/serve/worker/client/connection.js.map +1 -1
  243. package/dist/serve/worker/client/core.d.ts +2 -2
  244. package/dist/serve/worker/client/core.d.ts.map +1 -1
  245. package/dist/serve/worker/client/core.js +33 -5
  246. package/dist/serve/worker/client/core.js.map +1 -1
  247. package/dist/serve/worker/client/firestore-writes.d.ts.map +1 -1
  248. package/dist/serve/worker/client/firestore-writes.js +1 -0
  249. package/dist/serve/worker/client/firestore-writes.js.map +1 -1
  250. package/dist/serve/worker/client/messaging.d.ts +9 -1
  251. package/dist/serve/worker/client/messaging.d.ts.map +1 -1
  252. package/dist/serve/worker/client/messaging.js +15 -0
  253. package/dist/serve/worker/client/messaging.js.map +1 -1
  254. package/dist/serve/worker/client/studio.d.ts +10 -0
  255. package/dist/serve/worker/client/studio.d.ts.map +1 -1
  256. package/dist/serve/worker/client/studio.js +11 -0
  257. package/dist/serve/worker/client/studio.js.map +1 -1
  258. package/dist/serve/worker/durable-persistence.d.ts +12 -0
  259. package/dist/serve/worker/durable-persistence.d.ts.map +1 -0
  260. package/dist/serve/worker/durable-persistence.js +118 -0
  261. package/dist/serve/worker/durable-persistence.js.map +1 -0
  262. package/dist/serve/worker/entry.d.ts +7 -3
  263. package/dist/serve/worker/entry.d.ts.map +1 -1
  264. package/dist/serve/worker/entry.js +7 -3
  265. package/dist/serve/worker/entry.js.map +1 -1
  266. package/dist/serve/worker/host/core.d.ts +9 -5
  267. package/dist/serve/worker/host/core.d.ts.map +1 -1
  268. package/dist/serve/worker/host/core.js +34 -9
  269. package/dist/serve/worker/host/core.js.map +1 -1
  270. package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
  271. package/dist/serve/worker/host/dispatch.js +9 -2
  272. package/dist/serve/worker/host/dispatch.js.map +1 -1
  273. package/dist/serve/worker/host/firestore-writes.d.ts.map +1 -1
  274. package/dist/serve/worker/host/firestore-writes.js +3 -2
  275. package/dist/serve/worker/host/firestore-writes.js.map +1 -1
  276. package/dist/serve/worker/host/studio.d.ts +1 -1
  277. package/dist/serve/worker/host/studio.d.ts.map +1 -1
  278. package/dist/serve/worker/host/studio.js +36 -1
  279. package/dist/serve/worker/host/studio.js.map +1 -1
  280. package/dist/serve/worker/host/subscriptions.d.ts.map +1 -1
  281. package/dist/serve/worker/host/subscriptions.js +27 -7
  282. package/dist/serve/worker/host/subscriptions.js.map +1 -1
  283. package/dist/serve/worker/host-context.d.ts +15 -0
  284. package/dist/serve/worker/host-context.d.ts.map +1 -1
  285. package/dist/serve/worker/host-context.js +10 -0
  286. package/dist/serve/worker/host-context.js.map +1 -1
  287. package/dist/serve/worker/host-messaging.d.ts.map +1 -1
  288. package/dist/serve/worker/host-messaging.js +9 -2
  289. package/dist/serve/worker/host-messaging.js.map +1 -1
  290. package/dist/serve/worker/index.d.ts +3 -2
  291. package/dist/serve/worker/index.d.ts.map +1 -1
  292. package/dist/serve/worker/index.js +4 -1
  293. package/dist/serve/worker/index.js.map +1 -1
  294. package/dist/serve/worker/protocol.d.ts +25 -3
  295. package/dist/serve/worker/protocol.d.ts.map +1 -1
  296. package/dist/serve/worker/protocol.js +2 -2
  297. package/dist/serve/worker/protocol.js.map +1 -1
  298. package/dist/serve/worker/serve-init.d.ts +23 -37
  299. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  300. package/dist/serve/worker/serve-init.js +95 -172
  301. package/dist/serve/worker/serve-init.js.map +1 -1
  302. package/dist/vite.d.ts +4 -4
  303. package/dist/vite.d.ts.map +1 -1
  304. package/dist/vite.js +3 -3
  305. package/dist/vite.js.map +1 -1
  306. package/package.json +9 -4
  307. package/src/assurance/.generated/conformance-verdicts.ts +1090 -0
  308. package/src/assurance/attachment.ts +211 -0
  309. package/src/assurance/browser.ts +80 -0
  310. package/src/assurance/campaign.ts +496 -0
  311. package/src/assurance/capabilities.ts +446 -0
  312. package/src/assurance/cases.ts +43 -0
  313. package/src/assurance/index.ts +75 -0
  314. package/src/assurance/runner.ts +885 -0
  315. package/src/assurance/tool-names.ts +15 -0
  316. package/src/assurance/tools.ts +830 -0
  317. package/src/assurance/types.ts +352 -0
  318. package/src/assurance/validation.ts +434 -0
  319. package/src/bridge/client/bridge.ts +550 -0
  320. package/src/bridge/client/dispatch.ts +137 -0
  321. package/src/bridge/client.ts +45 -0
  322. package/src/bridge/protocol.ts +351 -0
  323. package/src/bridge/server/audit.ts +53 -0
  324. package/src/bridge/server/bridge.ts +597 -0
  325. package/src/bridge/server/headless.ts +160 -0
  326. package/src/bridge/server/json-schema-to-zod.ts +108 -0
  327. package/src/bridge/server/local-bridge.ts +66 -0
  328. package/src/bridge/server/logger.ts +50 -0
  329. package/src/bridge/server/mcp-contract.ts +93 -0
  330. package/src/bridge/server/mcp.ts +129 -0
  331. package/src/bridge/server/peer.ts +232 -0
  332. package/src/bridge/server/standalone.ts +347 -0
  333. package/src/bridge/server/tool-metadata.ts +99 -0
  334. package/src/bridge/server.ts +28 -0
  335. package/src/cli/can-i-use.ts +50 -0
  336. package/src/cli/cli.test.ts +493 -0
  337. package/src/cli/database-rules.ts +329 -0
  338. package/src/cli/dev-runner.ts +282 -0
  339. package/src/cli/firebase-json.ts +100 -0
  340. package/src/cli/firestore-indexes.ts +70 -0
  341. package/src/cli/index.ts +425 -0
  342. package/src/cli/init.ts +260 -0
  343. package/src/cli/mcp-proxy.ts +196 -0
  344. package/src/cli/parse-args.ts +80 -0
  345. package/src/cli/rules.ts +259 -0
  346. package/src/cli/scope.ts +67 -0
  347. package/src/cli/serve.ts +996 -0
  348. package/src/cli/service-commands.ts +73 -0
  349. package/src/cli/snapshot.ts +164 -0
  350. package/src/cli/storage-rules.ts +172 -0
  351. package/src/cli/verify.ts +416 -0
  352. package/src/conformance/.generated/can-i-use-browser.ts +113 -0
  353. package/src/conformance/.generated/can-i-use.ts +117 -0
  354. package/src/conformance/.generated/conformance-docs.ts +14 -0
  355. package/src/conformance/browser.ts +24 -0
  356. package/src/conformance/can-i-use-tool.ts +51 -0
  357. package/src/conformance/can-i-use.ts +18 -0
  358. package/src/conformance/docs.ts +8 -0
  359. package/src/conformance/index.ts +20 -0
  360. package/src/conformance/tools.ts +16 -0
  361. package/src/credentials/core/memoize-ttl.ts +142 -0
  362. package/src/credentials/core/types.ts +10 -0
  363. package/src/credentials/node/from-adc.ts +96 -0
  364. package/src/credentials/node/from-service-account.ts +133 -0
  365. package/src/credentials/node/index.ts +6 -0
  366. package/src/discover/concurrency.ts +127 -0
  367. package/src/discover/crawler-adapter.ts +142 -0
  368. package/src/discover/crawler.ts +1127 -0
  369. package/src/discover/credential-free.ts +27 -0
  370. package/src/discover/findCollectionGroup.ts +131 -0
  371. package/src/discover/firestore-source.ts +59 -0
  372. package/src/discover/index.ts +5 -0
  373. package/src/discover/merge.ts +523 -0
  374. package/src/discover/session.ts +402 -0
  375. package/src/discover/tools.ts +201 -0
  376. package/src/discover/types.ts +187 -0
  377. package/src/discover/wire.ts +324 -0
  378. package/src/functions-rtdb/child.ts +382 -0
  379. package/src/functions-rtdb/delivery.ts +7 -0
  380. package/src/functions-rtdb/discovery.ts +136 -0
  381. package/src/functions-rtdb/event.ts +64 -0
  382. package/src/functions-rtdb/execution.ts +111 -0
  383. package/src/functions-rtdb/in-memory-delivery.ts +40 -0
  384. package/src/functions-rtdb/project.ts +74 -0
  385. package/src/functions-rtdb/projection.ts +104 -0
  386. package/src/functions-rtdb/reference-pattern.ts +20 -0
  387. package/src/functions-rtdb/remote-delivery.ts +23 -0
  388. package/src/pkg-version.ts +49 -0
  389. package/src/register/esm-exports.ts +63 -0
  390. package/src/register/hooks.ts +30 -0
  391. package/src/register/index.ts +150 -0
  392. package/src/register/mapping.ts +33 -0
  393. package/src/remote/index.ts +1050 -0
  394. package/src/rtdb/crawl-snapshot.ts +118 -0
  395. package/src/rtdb/inspection.ts +137 -0
  396. package/src/rtdb/load-rules-document.ts +56 -0
  397. package/src/rtdb/rules-generation-tool.ts +38 -0
  398. package/src/rtdb/rules-json.ts +29 -0
  399. package/src/serve/activity-guard.ts +29 -0
  400. package/src/serve/activity-route.ts +164 -0
  401. package/src/serve/activity-warning.ts +26 -0
  402. package/src/serve/bridge-mount.ts +200 -0
  403. package/src/serve/bundler.ts +493 -0
  404. package/src/serve/capture-store.ts +65 -0
  405. package/src/serve/discovery.ts +199 -0
  406. package/src/serve/entries/ai.ts +292 -0
  407. package/src/serve/entries/app-backend.ts +4 -0
  408. package/src/serve/entries/app-client.ts +26 -0
  409. package/src/serve/entries/app-session-store.ts +47 -0
  410. package/src/serve/entries/app.ts +11 -0
  411. package/src/serve/entries/auth-helper-core.ts +181 -0
  412. package/src/serve/entries/auth-helper-dom.ts +134 -0
  413. package/src/serve/entries/auth-helper-runtime.ts +20 -0
  414. package/src/serve/entries/auth.ts +255 -0
  415. package/src/serve/entries/bridge-url.ts +31 -0
  416. package/src/serve/entries/database.ts +129 -0
  417. package/src/serve/entries/firestore.ts +232 -0
  418. package/src/serve/entries/init.ts +46 -0
  419. package/src/serve/entries/keepalive.ts +46 -0
  420. package/src/serve/entries/messaging-sw.ts +75 -0
  421. package/src/serve/entries/messaging.ts +96 -0
  422. package/src/serve/entries/runtime.ts +540 -0
  423. package/src/serve/entries/session-store.ts +97 -0
  424. package/src/serve/entries/storage.ts +92 -0
  425. package/src/serve/entries/tab-sync-wiring.ts +274 -0
  426. package/src/serve/entries/worker-runtime.ts +75 -0
  427. package/src/serve/init-payload.ts +42 -0
  428. package/src/serve/namespace.ts +675 -0
  429. package/src/serve/open-browser.ts +68 -0
  430. package/src/serve/rules.ts +272 -0
  431. package/src/serve/sandbox-marker.ts +31 -0
  432. package/src/serve/server.ts +428 -0
  433. package/src/serve/standalone-assets.ts +180 -0
  434. package/src/serve/state-store.ts +166 -0
  435. package/src/serve/studio/disk-project-store.ts +185 -0
  436. package/src/serve/studio/disk-workspace.ts +162 -0
  437. package/src/serve/studio/index.ts +20 -0
  438. package/src/serve/studio/routes.ts +237 -0
  439. package/src/serve/studio/store-types.ts +48 -0
  440. package/src/serve/studio/studio-storage.test.ts +289 -0
  441. package/src/serve/vite-plugin.ts +1102 -0
  442. package/src/serve/worker/activity-bootstrap.ts +24 -0
  443. package/src/serve/worker/client/admin-firestore.ts +38 -0
  444. package/src/serve/worker/client/ai.ts +124 -0
  445. package/src/serve/worker/client/auth.ts +489 -0
  446. package/src/serve/worker/client/connection.ts +202 -0
  447. package/src/serve/worker/client/core.ts +350 -0
  448. package/src/serve/worker/client/disconnect.ts +45 -0
  449. package/src/serve/worker/client/firestore-reads.ts +181 -0
  450. package/src/serve/worker/client/firestore-refs.ts +226 -0
  451. package/src/serve/worker/client/firestore-writes.ts +232 -0
  452. package/src/serve/worker/client/handles.ts +91 -0
  453. package/src/serve/worker/client/messaging.ts +119 -0
  454. package/src/serve/worker/client/presence.ts +174 -0
  455. package/src/serve/worker/client/rtdb.ts +311 -0
  456. package/src/serve/worker/client/rules.ts +63 -0
  457. package/src/serve/worker/client/service-worker-connection.ts +59 -0
  458. package/src/serve/worker/client/snapshots.ts +86 -0
  459. package/src/serve/worker/client/storage.ts +195 -0
  460. package/src/serve/worker/client/studio.ts +88 -0
  461. package/src/serve/worker/client.ts +57 -0
  462. package/src/serve/worker/durable-persistence.ts +137 -0
  463. package/src/serve/worker/entry.ts +179 -0
  464. package/src/serve/worker/host/admin-firestore.ts +88 -0
  465. package/src/serve/worker/host/connection.ts +179 -0
  466. package/src/serve/worker/host/core.ts +387 -0
  467. package/src/serve/worker/host/dispatch.ts +316 -0
  468. package/src/serve/worker/host/firestore-reads.ts +117 -0
  469. package/src/serve/worker/host/firestore-writes.ts +456 -0
  470. package/src/serve/worker/host/presence.ts +312 -0
  471. package/src/serve/worker/host/rtdb.ts +136 -0
  472. package/src/serve/worker/host/rules.ts +128 -0
  473. package/src/serve/worker/host/storage.ts +312 -0
  474. package/src/serve/worker/host/studio.ts +75 -0
  475. package/src/serve/worker/host/subscriptions.ts +238 -0
  476. package/src/serve/worker/host-ai.ts +165 -0
  477. package/src/serve/worker/host-auth.ts +469 -0
  478. package/src/serve/worker/host-context.ts +273 -0
  479. package/src/serve/worker/host-events.ts +94 -0
  480. package/src/serve/worker/host-messaging.ts +240 -0
  481. package/src/serve/worker/host.ts +47 -0
  482. package/src/serve/worker/index.ts +196 -0
  483. package/src/serve/worker/presence-timing.ts +15 -0
  484. package/src/serve/worker/protocol.ts +1112 -0
  485. package/src/serve/worker/serve-init.ts +606 -0
  486. package/src/serve/worker/service-worker-channel.ts +33 -0
  487. package/src/serve/worker/service-worker-relay.ts +86 -0
  488. package/src/serve/writer-lock.ts +53 -0
  489. package/src/verify/cases.ts +233 -0
  490. package/src/verify/fixture.ts +258 -0
  491. package/src/verify/index.ts +519 -0
  492. package/src/verify/tools.ts +108 -0
  493. package/src/version/compat-target.ts +17 -0
  494. package/src/vite.ts +17 -0
  495. package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api/index.html +0 -30
  496. package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api.md +0 -30
  497. package/dist/serve/studio-ui/assets/index-BvtQIpGn.js +0 -1211
  498. package/dist/serve/studio-ui/assets/seed-3DMedLL3.js +0 -2
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Worker-client handle types — the opaque, port-carrying references the client
3
+ * surface hands back to callers. Shared by every API family (firestore, auth,
4
+ * rtdb, storage), so they live in one leaf module with no runtime dependencies
5
+ * beyond the wire-protocol descriptor types.
6
+ */
7
+ import type {
8
+ DocRef,
9
+ CollRef,
10
+ QueryDescriptor,
11
+ InboundMessage,
12
+ OutboundMessage,
13
+ } from '../protocol.js';
14
+
15
+ /** The exact transport contract shared by native MessagePort and SW relay ports. */
16
+ export interface ClientPort {
17
+ onmessage: ((event: MessageEvent<OutboundMessage>) => void) | null;
18
+ postMessage(message: InboundMessage): void;
19
+ start(): void;
20
+ close(): void;
21
+ }
22
+
23
+ /** Opaque client-side Firestore handle. Holds the MessagePort to the worker. */
24
+ export interface ClientDb {
25
+ readonly __kind: 'client-db';
26
+ readonly port: ClientPort;
27
+ }
28
+
29
+ export interface ClientRtdb {
30
+ readonly __kind: 'client-rtdb';
31
+ readonly port: ClientPort;
32
+ }
33
+
34
+ export interface RtdbRefHandle {
35
+ readonly __kind: 'rtdb-ref';
36
+ readonly port: ClientPort;
37
+ readonly path: string;
38
+ readonly key: string | null;
39
+ readonly parent: RtdbRefHandle | null;
40
+ readonly root: RtdbRefHandle;
41
+ toString(): string;
42
+ }
43
+
44
+ export interface RtdbDataSnapshot {
45
+ readonly key: string | null;
46
+ readonly size: number;
47
+ exists(): boolean;
48
+ val(): unknown;
49
+ child(path: string): RtdbDataSnapshot;
50
+ hasChild(path: string): boolean;
51
+ hasChildren(): boolean;
52
+ exportVal(): unknown;
53
+ toJSON(): unknown;
54
+ forEach(cb: (child: RtdbDataSnapshot) => boolean | void): boolean;
55
+ readonly ref: RtdbRefHandle;
56
+ }
57
+
58
+ /** Client-side document reference — carries a DocRef descriptor + port. */
59
+ export interface DocRefHandle {
60
+ readonly __kind: 'doc-ref';
61
+ readonly descriptor: DocRef;
62
+ readonly port: ClientPort;
63
+ readonly id: string;
64
+ readonly path: string;
65
+ }
66
+
67
+ /** Client-side collection reference. */
68
+ export interface CollRefHandle {
69
+ readonly __kind: 'coll-ref';
70
+ readonly descriptor: CollRef;
71
+ readonly port: ClientPort;
72
+ readonly id: string;
73
+ readonly path: string;
74
+ }
75
+
76
+ /** Client-side query. */
77
+ export interface QueryHandle {
78
+ readonly __kind: 'query';
79
+ readonly descriptor: QueryDescriptor;
80
+ readonly port: ClientPort;
81
+ }
82
+
83
+ /** Union of all client handles. */
84
+ export type AnyHandle = ClientDb | DocRefHandle | CollRefHandle | QueryHandle;
85
+
86
+ /** Unsubscribe function returned by every streaming subscription. */
87
+ export type Unsubscribe = () => void;
88
+
89
+ export function lastSegment(path: string): string {
90
+ return path.split('/').at(-1) ?? path;
91
+ }
@@ -0,0 +1,119 @@
1
+ /** Worker-backed Firebase Messaging client/SW receive planes. */
2
+ import type {
3
+ DeliverSpec,
4
+ DeliveryResult,
5
+ GetTokenOptions,
6
+ MessagePayload,
7
+ NextFn,
8
+ Observer,
9
+ Unsubscribe,
10
+ } from 'pyric/messaging';
11
+ import { closeSubscription, nextId, nextSubId, openSnapshotSubscription, rpc } from './core.js';
12
+ import type { ClientDb, ClientPort } from './handles.js';
13
+
14
+ type ClientVisibilityState = 'visible' | 'hidden';
15
+
16
+ const DEFAULT_REGISTRATION_ID = 'swreg-port-default';
17
+ const registrationIds = new WeakMap<object, string>();
18
+ let registrationCounter = 0;
19
+
20
+ function registrationIdOf(registration: object | undefined): string {
21
+ if (registration === undefined) return DEFAULT_REGISTRATION_ID;
22
+ const existing = registrationIds.get(registration);
23
+ if (existing) return existing;
24
+ const id = `swreg-page-${++registrationCounter}`;
25
+ registrationIds.set(registration, id);
26
+ return id;
27
+ }
28
+
29
+ export interface ClientMessaging {
30
+ readonly __kind: 'client-messaging';
31
+ readonly port: ClientPort;
32
+ activeRegistrationId: string;
33
+ }
34
+
35
+ export function messagingGetMessaging(db: ClientDb): ClientMessaging {
36
+ return {
37
+ __kind: 'client-messaging',
38
+ port: db.port,
39
+ activeRegistrationId: DEFAULT_REGISTRATION_ID,
40
+ };
41
+ }
42
+
43
+ export async function messagingGetToken(
44
+ messaging: ClientMessaging,
45
+ options?: GetTokenOptions,
46
+ ): Promise<string> {
47
+ const registrationId = registrationIdOf(options?.serviceWorkerRegistration);
48
+ messaging.activeRegistrationId = registrationId;
49
+ const result = await rpc(messaging.port, {
50
+ t: 'op',
51
+ id: nextId(),
52
+ method: 'messaging.getToken',
53
+ registrationId,
54
+ }) as { token: string };
55
+ return result.token;
56
+ }
57
+
58
+ export async function messagingDeleteToken(messaging: ClientMessaging): Promise<boolean> {
59
+ return await rpc(messaging.port, {
60
+ t: 'op',
61
+ id: nextId(),
62
+ method: 'messaging.deleteToken',
63
+ registrationId: messaging.activeRegistrationId,
64
+ }) as boolean;
65
+ }
66
+
67
+ export async function messagingSetVisibility(
68
+ messaging: ClientMessaging,
69
+ state: ClientVisibilityState,
70
+ ): Promise<void> {
71
+ await rpc(messaging.port, {
72
+ t: 'op',
73
+ id: nextId(),
74
+ method: 'messaging.setVisibility',
75
+ state,
76
+ });
77
+ }
78
+
79
+ /**
80
+ * The worker transport for `pyric/messaging`'s `sandbox.deliver` — injects a
81
+ * simulated delivery into the app's real (worker-hosted) broker. The full
82
+ * {@link DeliverSpec} crosses the wire; the host sets this port's client
83
+ * visibility from `spec.visibilityState` before routing, so `visible` reaches
84
+ * `onMessage` and `hidden` reaches `onBackgroundMessage`.
85
+ */
86
+ export async function messagingDeliver(
87
+ messaging: ClientMessaging,
88
+ spec: DeliverSpec,
89
+ ): Promise<DeliveryResult> {
90
+ return await rpc(messaging.port, {
91
+ t: 'op',
92
+ id: nextId(),
93
+ method: 'messaging.deliver',
94
+ spec,
95
+ }) as DeliveryResult;
96
+ }
97
+
98
+ export function messagingSubscribe(
99
+ messaging: ClientMessaging,
100
+ target: 'messaging.foreground' | 'messaging.background',
101
+ nextOrObserver: NextFn<MessagePayload> | Observer<MessagePayload>,
102
+ ): Unsubscribe {
103
+ const next = typeof nextOrObserver === 'function'
104
+ ? nextOrObserver
105
+ : nextOrObserver.next.bind(nextOrObserver);
106
+ const error = typeof nextOrObserver === 'function'
107
+ ? undefined
108
+ : (value: unknown) => nextOrObserver.error(
109
+ value instanceof Error ? value : new Error(String(value)),
110
+ );
111
+ const subId = nextSubId();
112
+ openSnapshotSubscription(
113
+ messaging.port,
114
+ subId,
115
+ { port: messaging.port, next: (value) => next(value as MessagePayload), error },
116
+ { t: 'sub', subId, target },
117
+ );
118
+ return () => closeSubscription(messaging.port, subId);
119
+ }
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Worker-client connected-page presence (#227).
3
+ *
4
+ * Each served page (app or Studio) identifies itself with a stable-per-page
5
+ * `clientId`, registers with the SharedWorker, heartbeats on a bounded
6
+ * interval, updates route/visibility, and best-effort disconnects on
7
+ * `pagehide`. Studio also subscribes for live snapshots.
8
+ *
9
+ * Presence is independent of auth sessions and Firestore subscriptions.
10
+ */
11
+
12
+ import type {
13
+ InboundMessage,
14
+ PresenceClientKind,
15
+ PresenceSnapshot,
16
+ PresenceVisibility,
17
+ } from '../protocol.js';
18
+ import {
19
+ PRESENCE_HEARTBEAT_INTERVAL_MS,
20
+ PRESENCE_STALE_MS,
21
+ } from '../presence-timing.js';
22
+ import { closeSubscription, nextId, nextSubId, openSnapshotSubscription, rpc } from './core.js';
23
+ import type { ClientDb, Unsubscribe } from './handles.js';
24
+
25
+ export type { PresenceClientKind, PresenceSnapshot, PresenceVisibility };
26
+ export { PRESENCE_HEARTBEAT_INTERVAL_MS, PRESENCE_STALE_MS };
27
+
28
+ /** Mint a random client id (page-lifetime). */
29
+ export function mintPresenceClientId(): string {
30
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
31
+ return crypto.randomUUID();
32
+ }
33
+ return `page-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
34
+ }
35
+
36
+ function currentRoute(): string {
37
+ if (typeof location === 'undefined') return '/';
38
+ return `${location.pathname}${location.search}${location.hash}`;
39
+ }
40
+
41
+ function currentVisibility(): PresenceVisibility {
42
+ if (typeof document === 'undefined') return 'visible';
43
+ return document.visibilityState === 'hidden' ? 'hidden' : 'visible';
44
+ }
45
+
46
+ export interface PresenceSession {
47
+ /** Logical page id — Studio uses this to label "This page". */
48
+ readonly clientId: string;
49
+ readonly kind: PresenceClientKind;
50
+ /** Stop heartbeats, listeners, and send a best-effort disconnect. */
51
+ stop(): void;
52
+ }
53
+
54
+ export interface StartPresenceOptions {
55
+ db: ClientDb;
56
+ kind: PresenceClientKind;
57
+ /** Override client id (tests / reconnect). Default: mint a new one. */
58
+ clientId?: string;
59
+ /** Heartbeat interval. Default: {@link PRESENCE_HEARTBEAT_INTERVAL_MS}. */
60
+ heartbeatIntervalMs?: number;
61
+ }
62
+
63
+ /**
64
+ * Register this page with the worker and keep the lease alive until
65
+ * {@link PresenceSession.stop} or `pagehide`.
66
+ */
67
+ export function startPresence(opts: StartPresenceOptions): PresenceSession {
68
+ const { db, kind } = opts;
69
+ const clientId = opts.clientId ?? mintPresenceClientId();
70
+ const intervalMs = opts.heartbeatIntervalMs ?? PRESENCE_HEARTBEAT_INTERVAL_MS;
71
+ let stopped = false;
72
+ let timer: ReturnType<typeof setInterval> | null = null;
73
+
74
+ const register = (): void => {
75
+ void rpc(db.port, {
76
+ t: 'op',
77
+ id: nextId(),
78
+ method: 'presence.register',
79
+ clientId,
80
+ kind,
81
+ route: currentRoute(),
82
+ visibility: currentVisibility(),
83
+ }).catch(() => {});
84
+ };
85
+
86
+ const heartbeat = (): void => {
87
+ void rpc(db.port, {
88
+ t: 'op',
89
+ id: nextId(),
90
+ method: 'presence.heartbeat',
91
+ clientId,
92
+ }).catch(() => {});
93
+ };
94
+
95
+ const update = (): void => {
96
+ void rpc(db.port, {
97
+ t: 'op',
98
+ id: nextId(),
99
+ method: 'presence.update',
100
+ clientId,
101
+ route: currentRoute(),
102
+ visibility: currentVisibility(),
103
+ }).catch(() => {});
104
+ };
105
+
106
+ const disconnect = (): void => {
107
+ void rpc(db.port, {
108
+ t: 'op',
109
+ id: nextId(),
110
+ method: 'presence.disconnect',
111
+ clientId,
112
+ }).catch(() => {});
113
+ };
114
+
115
+ register();
116
+
117
+ if (typeof document !== 'undefined') {
118
+ document.addEventListener('visibilitychange', update);
119
+ }
120
+ if (typeof window !== 'undefined') {
121
+ window.addEventListener('popstate', update);
122
+ window.addEventListener('hashchange', update);
123
+ // Best-effort clean disconnect; lease expiry covers unclean shutdown.
124
+ window.addEventListener('pagehide', onPageHide);
125
+ // Heartbeats only in a real page — unit shims have no document lifecycle.
126
+ timer = setInterval(() => {
127
+ if (!stopped) heartbeat();
128
+ }, intervalMs);
129
+ }
130
+
131
+ function onPageHide(): void {
132
+ stop();
133
+ }
134
+
135
+ function stop(): void {
136
+ if (stopped) return;
137
+ stopped = true;
138
+ if (timer != null) {
139
+ clearInterval(timer);
140
+ timer = null;
141
+ }
142
+ if (typeof document !== 'undefined') {
143
+ document.removeEventListener('visibilitychange', update);
144
+ }
145
+ if (typeof window !== 'undefined') {
146
+ window.removeEventListener('popstate', update);
147
+ window.removeEventListener('hashchange', update);
148
+ window.removeEventListener('pagehide', onPageHide);
149
+ }
150
+ disconnect();
151
+ }
152
+
153
+ return { clientId, kind, stop };
154
+ }
155
+
156
+ /**
157
+ * Subscribe to the worker's authoritative presence snapshot. The callback
158
+ * fires immediately with the current snapshot, then on every change.
159
+ */
160
+ export function subscribePresence(
161
+ db: ClientDb,
162
+ callback: (snapshot: PresenceSnapshot) => void,
163
+ ): Unsubscribe {
164
+ const subId = nextSubId();
165
+ openSnapshotSubscription(db.port, subId, {
166
+ port: db.port,
167
+ next: (value) => {
168
+ callback(value as PresenceSnapshot);
169
+ },
170
+ }, { t: 'sub', subId, target: 'presence' } satisfies InboundMessage);
171
+ return () => {
172
+ closeSubscription(db.port, subId);
173
+ };
174
+ }
@@ -0,0 +1,311 @@
1
+ /**
2
+ * RTDB shared-worker modular subset — refs, push-id generation, value reads,
3
+ * writes, and `onValue` listeners over the worker port, plus the admin-lens data
4
+ * ops for the Pyric Studio RTDB viewer.
5
+ */
6
+
7
+ import type { InboundMessage } from '../protocol.js';
8
+ import {
9
+ isDisconnectedPort,
10
+ closeSubscription,
11
+ openSnapshotSubscription,
12
+ nextId,
13
+ nextSubId,
14
+ rpc,
15
+ dataRpc,
16
+ _snapSubs,
17
+ _defaultLens,
18
+ stampIssuer,
19
+ } from './core.js';
20
+ import type {
21
+ ClientDb,
22
+ ClientPort,
23
+ ClientRtdb,
24
+ RtdbRefHandle,
25
+ RtdbDataSnapshot,
26
+ Unsubscribe,
27
+ } from './handles.js';
28
+ import { getFirestore } from './connection.js';
29
+
30
+ // ─── RTDB shared-worker modular subset ────────────────────────────────────
31
+
32
+ export function rtdbGetDatabase(source?: ClientDb | string | URL, name?: string): ClientRtdb {
33
+ if (source && typeof source === 'object' && 'port' in source) {
34
+ return { __kind: 'client-rtdb', port: (source as ClientDb).port };
35
+ }
36
+ const firestore = getFirestore(source ?? '/__pyric/sdk/worker.js', name);
37
+ return { __kind: 'client-rtdb', port: firestore.port };
38
+ }
39
+
40
+ function normalizeRtdbPath(path?: string): string {
41
+ const joined = (path ?? '/').split('/').filter(Boolean).join('/');
42
+ return joined ? `/${joined}` : '/';
43
+ }
44
+
45
+ function rtdbKey(path: string): string | null {
46
+ const parts = path.split('/').filter(Boolean);
47
+ return parts.at(-1) ?? null;
48
+ }
49
+
50
+ const RTDB_PUSH_CHARS =
51
+ '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
52
+
53
+ let lastRtdbPushTime = 0;
54
+
55
+ const lastRtdbRandChars: number[] = new Array(12).fill(0);
56
+
57
+ function generateRtdbPushId(now: number = Date.now()): string {
58
+ const duplicateTime = now === lastRtdbPushTime;
59
+ lastRtdbPushTime = now;
60
+
61
+ const timeStampChars: string[] = new Array(8);
62
+ let ts = now;
63
+ for (let i = 7; i >= 0; i--) {
64
+ timeStampChars[i] = RTDB_PUSH_CHARS.charAt(ts % 64);
65
+ ts = Math.floor(ts / 64);
66
+ }
67
+ if (ts !== 0) throw new Error('RTDB push-id: timestamp overflow.');
68
+
69
+ if (!duplicateTime) {
70
+ for (let i = 0; i < 12; i++) lastRtdbRandChars[i] = Math.floor(Math.random() * 64);
71
+ } else {
72
+ let i: number;
73
+ for (i = 11; i >= 0 && lastRtdbRandChars[i] === 63; i--) lastRtdbRandChars[i] = 0;
74
+ if (i < 0) {
75
+ for (let j = 0; j < 12; j++) lastRtdbRandChars[j] = Math.floor(Math.random() * 64);
76
+ } else {
77
+ lastRtdbRandChars[i] = (lastRtdbRandChars[i] ?? 0) + 1;
78
+ }
79
+ }
80
+
81
+ let id = timeStampChars.join('');
82
+ for (let i = 0; i < 12; i++) id += RTDB_PUSH_CHARS.charAt(lastRtdbRandChars[i]!);
83
+ return id;
84
+ }
85
+
86
+ function makeRtdbRef(port: ClientPort, path: string): RtdbRefHandle {
87
+ const normalized = normalizeRtdbPath(path);
88
+ const parts = normalized.split('/').filter(Boolean);
89
+ const parentPath = parts.length > 0 ? `/${parts.slice(0, -1).join('/')}` : '/';
90
+ const self: RtdbRefHandle = {
91
+ __kind: 'rtdb-ref',
92
+ port,
93
+ path: normalized,
94
+ key: rtdbKey(normalized),
95
+ get parent() {
96
+ return normalized === '/' ? null : makeRtdbRef(port, parentPath);
97
+ },
98
+ get root() {
99
+ return makeRtdbRef(port, '/');
100
+ },
101
+ toString() {
102
+ return `worker://rtdb${normalized}`;
103
+ },
104
+ };
105
+ return self;
106
+ }
107
+
108
+ export function rtdbRef(db: ClientRtdb, path?: string): RtdbRefHandle {
109
+ if (isDisconnectedPort(db.port)) {
110
+ throw new Error('FIREBASE FATAL ERROR: Cannot call ref on a deleted database. ');
111
+ }
112
+ return makeRtdbRef(db.port, path ?? '/');
113
+ }
114
+
115
+ export function rtdbChild(parent: RtdbRefHandle, path: string): RtdbRefHandle {
116
+ return makeRtdbRef(parent.port, `${parent.path}/${path}`);
117
+ }
118
+
119
+ function valueAt(root: unknown, path: string): unknown {
120
+ let current = root;
121
+ for (const segment of path.split('/').filter(Boolean)) {
122
+ if (current === null || typeof current !== 'object') return null;
123
+ current = (current as Record<string, unknown>)[segment];
124
+ }
125
+ return current === undefined ? null : current;
126
+ }
127
+
128
+ function makeRtdbSnapshot(refHandle: RtdbRefHandle, value: unknown, exists?: boolean): RtdbDataSnapshot {
129
+ const childValue = (path: string) => valueAt(value, path);
130
+ const size =
131
+ value && typeof value === 'object' && !Array.isArray(value)
132
+ ? Object.keys(value as Record<string, unknown>).length
133
+ : 0;
134
+ const snapshot: RtdbDataSnapshot = {
135
+ key: refHandle.key,
136
+ size,
137
+ exists: () => exists ?? (value !== null && value !== undefined),
138
+ val: () => value ?? null,
139
+ child: (path) => makeRtdbSnapshot(rtdbChild(refHandle, path), childValue(path)),
140
+ hasChild: (path) => childValue(path) !== null && childValue(path) !== undefined,
141
+ hasChildren: () => size > 0,
142
+ exportVal: () => value ?? null,
143
+ toJSON: () => value ?? null,
144
+ forEach: (cb) => {
145
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
146
+ for (const [key, childVal] of Object.entries(value as Record<string, unknown>)) {
147
+ if (cb(makeRtdbSnapshot(rtdbChild(refHandle, key), childVal)) === true) return true;
148
+ }
149
+ return false;
150
+ },
151
+ ref: refHandle,
152
+ };
153
+ return snapshot;
154
+ }
155
+
156
+ function hydrateRtdbSnapshot(refHandle: RtdbRefHandle, wire: unknown): RtdbDataSnapshot {
157
+ const payload = wire as { value?: unknown; exists?: boolean; key?: string | null };
158
+ return makeRtdbSnapshot(refHandle, payload.value ?? null, payload.exists);
159
+ }
160
+
161
+ export async function rtdbGet(r: RtdbRefHandle): Promise<RtdbDataSnapshot> {
162
+ return hydrateRtdbSnapshot(
163
+ r,
164
+ await dataRpc(r.port, { t: 'op', id: nextId(), method: 'rtdb.get', path: r.path }),
165
+ );
166
+ }
167
+
168
+ export async function adminReadRtdbState(db: ClientDb | ClientRtdb): Promise<unknown> {
169
+ return rpc(db.port, { t: 'op', id: nextId(), method: 'rtdb.adminSnapshot' });
170
+ }
171
+
172
+ export async function adminSetRtdbValue(
173
+ db: ClientDb | ClientRtdb,
174
+ path: string,
175
+ value: unknown,
176
+ ): Promise<void> {
177
+ await rpc(db.port, {
178
+ t: 'op',
179
+ id: nextId(),
180
+ method: 'rtdb.set',
181
+ path,
182
+ value,
183
+ actAs: { mode: 'admin' },
184
+ });
185
+ }
186
+
187
+ export async function adminUpdateRtdbValue(
188
+ db: ClientDb | ClientRtdb,
189
+ path: string,
190
+ values: Record<string, unknown>,
191
+ ): Promise<void> {
192
+ await rpc(db.port, {
193
+ t: 'op',
194
+ id: nextId(),
195
+ method: 'rtdb.update',
196
+ path,
197
+ values,
198
+ actAs: { mode: 'admin' },
199
+ });
200
+ }
201
+
202
+ export async function adminDeleteRtdbValue(
203
+ db: ClientDb | ClientRtdb,
204
+ path: string,
205
+ ): Promise<void> {
206
+ await rpc(db.port, {
207
+ t: 'op',
208
+ id: nextId(),
209
+ method: 'rtdb.remove',
210
+ path,
211
+ actAs: { mode: 'admin' },
212
+ });
213
+ }
214
+
215
+ /**
216
+ * Subscribe to the raw value at an RTDB path with the ADMIN lens (Pyric Studio
217
+ * data viewer). Rides the same `{service:'rtdb'}` value-subscription channel as
218
+ * `rtdbOnValue`, but pins `actAs: {mode:'admin'}` per-sub instead of following
219
+ * the module default lens, so Studio's viewer stays admin (PRINCIPLES M3) while
220
+ * the page's own listeners keep their session semantics.
221
+ *
222
+ * `next` receives the plain JSON value at `path` (`null` when absent) on
223
+ * subscribe and again after every write that changes the subtree.
224
+ */
225
+ export function adminSubscribeRtdbValue(
226
+ db: ClientDb | ClientRtdb,
227
+ path: string,
228
+ next: (value: unknown) => void,
229
+ error?: (err: unknown) => void,
230
+ ): Unsubscribe {
231
+ const subId = nextSubId();
232
+ const opened = openSnapshotSubscription(
233
+ db.port,
234
+ subId,
235
+ {
236
+ port: db.port,
237
+ next: (wire) => next((wire as { value?: unknown } | null)?.value ?? null),
238
+ error,
239
+ },
240
+ stampIssuer({
241
+ t: 'sub',
242
+ subId,
243
+ target: { service: 'rtdb', path: normalizeRtdbPath(path) },
244
+ actAs: { mode: 'admin' },
245
+ } satisfies InboundMessage),
246
+ );
247
+ if (!opened && error) {
248
+ queueMicrotask(() => error(new Error('FIREBASE FATAL ERROR: Database has been deleted.')));
249
+ }
250
+ return () => {
251
+ closeSubscription(db.port, subId);
252
+ };
253
+ }
254
+
255
+ export async function rtdbSet(r: RtdbRefHandle, value: unknown): Promise<void> {
256
+ await dataRpc(r.port, { t: 'op', id: nextId(), method: 'rtdb.set', path: r.path, value });
257
+ }
258
+
259
+ export async function rtdbUpdate(r: RtdbRefHandle, values: Record<string, unknown>): Promise<void> {
260
+ await dataRpc(r.port, { t: 'op', id: nextId(), method: 'rtdb.update', path: r.path, values });
261
+ }
262
+
263
+ export async function rtdbRemove(r: RtdbRefHandle): Promise<void> {
264
+ await dataRpc(r.port, { t: 'op', id: nextId(), method: 'rtdb.remove', path: r.path });
265
+ }
266
+
267
+ export function rtdbPush(r: RtdbRefHandle, value?: unknown): RtdbRefHandle & PromiseLike<RtdbRefHandle> {
268
+ const key = generateRtdbPushId();
269
+ const pushed = makeRtdbRef(r.port, `${r.path}/${key}`);
270
+ const settledRef = makeRtdbRef(r.port, pushed.path);
271
+ const promise = dataRpc(r.port, { t: 'op', id: nextId(), method: 'rtdb.push', path: r.path, key, value })
272
+ .then(() => settledRef);
273
+ return Object.assign(pushed, {
274
+ then: promise.then.bind(promise),
275
+ catch: promise.catch.bind(promise),
276
+ });
277
+ }
278
+
279
+ export function rtdbOnValue(
280
+ r: RtdbRefHandle,
281
+ next: (snap: RtdbDataSnapshot) => void,
282
+ error?: (err: unknown) => void,
283
+ ): Unsubscribe {
284
+ const subId = nextSubId();
285
+ const msg: InboundMessage = _defaultLens
286
+ ? { t: 'sub', subId, target: { service: 'rtdb', path: r.path }, actAs: _defaultLens }
287
+ : { t: 'sub', subId, target: { service: 'rtdb', path: r.path } };
288
+ const opened = openSnapshotSubscription(r.port, subId, {
289
+ port: r.port,
290
+ next: (wire) => next(hydrateRtdbSnapshot(r, wire)),
291
+ error,
292
+ }, stampIssuer(msg));
293
+ if (!opened && error) queueMicrotask(() => error(new Error('FIREBASE FATAL ERROR: Database has been deleted.')));
294
+ return () => {
295
+ closeSubscription(r.port, subId);
296
+ };
297
+ }
298
+
299
+ export function rtdbOff(_r: RtdbRefHandle, _eventType?: unknown, _callback?: unknown): void {
300
+ // Firebase's `off` is callback-specific. The worker bridge exposes unsubscribe
301
+ // functions from `onValue`; this no-op preserves common app code that calls it
302
+ // defensively during cleanup.
303
+ }
304
+
305
+ export function rtdbServerTimestamp(): { readonly __rtdbSentinel: 'serverTimestamp' } {
306
+ return { __rtdbSentinel: 'serverTimestamp' };
307
+ }
308
+
309
+ export function rtdbConnectDatabaseEmulator(): void {
310
+ // Shared worker sandbox is already local.
311
+ }