@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,312 @@
1
+ /**
2
+ * SharedWorker host — connected-page presence (#227).
3
+ *
4
+ * Ephemeral, worker-lifetime registry of logical pages attached to this
5
+ * sandbox worker. Distinct from per-port subscription / auth-session /
6
+ * messaging maps: the user-facing count is keyed by `clientId`, so one page
7
+ * with multiple MessagePorts still counts as one client.
8
+ *
9
+ * Correctness rests on heartbeats + lease expiry (MessagePort `close` is
10
+ * best-effort and unreliable in Chrome). `cleanupPort` is an optimization
11
+ * that removes a client when its last associated port disappears.
12
+ */
13
+
14
+ import type { OpMessage, PresenceClientRecord, PresenceSnapshot, PresenceSubMessage } from '../protocol.js';
15
+ import { type HostCtx, type PortLike, ok, fail, post } from '../host-context.js';
16
+ import { PRESENCE_HEARTBEAT_INTERVAL_MS, PRESENCE_STALE_MS } from '../presence-timing.js';
17
+
18
+ export { PRESENCE_HEARTBEAT_INTERVAL_MS, PRESENCE_STALE_MS };
19
+
20
+ /** Controllable clock for deterministic lease tests. */
21
+ let _now: () => number = () => Date.now();
22
+
23
+ export function setPresenceNow(fn: () => number): void {
24
+ _now = fn;
25
+ }
26
+
27
+ export function resetPresenceNow(): void {
28
+ _now = () => Date.now();
29
+ }
30
+
31
+ export function presenceNow(): number {
32
+ return _now();
33
+ }
34
+
35
+ interface PresenceEntry extends PresenceClientRecord {
36
+ /** Ports currently associated with this logical client. */
37
+ ports: Set<PortLike>;
38
+ }
39
+
40
+ interface PresenceState {
41
+ clients: Map<string, PresenceEntry>;
42
+ /** Reverse index: port → clientId (for cleanupPort optimization). */
43
+ portToClient: Map<PortLike, string>;
44
+ /** Presence subscribers: Map<port, Set<subId>>. */
45
+ subs: Map<PortLike, Set<string>>;
46
+ /** Periodic expiry timer (worker-global; tests drive expiry via {@link expireStalePresence}). */
47
+ timer: ReturnType<typeof setInterval> | null;
48
+ }
49
+
50
+ const _state = new WeakMap<HostCtx, PresenceState>();
51
+
52
+ function stateFor(ctx: HostCtx): PresenceState {
53
+ let s = _state.get(ctx);
54
+ if (!s) {
55
+ s = {
56
+ clients: new Map(),
57
+ portToClient: new Map(),
58
+ subs: new Map(),
59
+ timer: null,
60
+ };
61
+ _state.set(ctx, s);
62
+ }
63
+ return s;
64
+ }
65
+
66
+ function ensureExpiryTimer(ctx: HostCtx): void {
67
+ const s = stateFor(ctx);
68
+ if (s.timer != null) return;
69
+ // Sweep at half the stale window so expiry is prompt without busy-polling.
70
+ s.timer = setInterval(() => {
71
+ expireStalePresence(ctx);
72
+ }, Math.max(5_000, Math.floor(PRESENCE_STALE_MS / 2)));
73
+ // Workers may not have unref; guard for Node/test hosts that do.
74
+ const t = s.timer as { unref?: () => void };
75
+ if (typeof t.unref === 'function') t.unref();
76
+ }
77
+
78
+ function stopExpiryTimerIfIdle(ctx: HostCtx): void {
79
+ const s = stateFor(ctx);
80
+ if (s.clients.size > 0 || s.subs.size > 0) return;
81
+ if (s.timer != null) {
82
+ clearInterval(s.timer);
83
+ s.timer = null;
84
+ }
85
+ }
86
+
87
+ function toSnapshot(s: PresenceState): PresenceSnapshot {
88
+ const clients: PresenceClientRecord[] = [];
89
+ for (const e of s.clients.values()) {
90
+ clients.push({
91
+ clientId: e.clientId,
92
+ kind: e.kind,
93
+ route: e.route,
94
+ visibility: e.visibility,
95
+ connectedAt: e.connectedAt,
96
+ lastSeen: e.lastSeen,
97
+ });
98
+ }
99
+ clients.sort((a, b) => a.connectedAt - b.connectedAt || a.clientId.localeCompare(b.clientId));
100
+ return { clients };
101
+ }
102
+
103
+ function broadcast(ctx: HostCtx): void {
104
+ const s = stateFor(ctx);
105
+ const snap = toSnapshot(s);
106
+ for (const [port, subIds] of s.subs) {
107
+ for (const subId of subIds) {
108
+ post(port, { t: 'snap', subId, value: snap });
109
+ }
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Drop clients whose lease is older than {@link PRESENCE_STALE_MS}.
115
+ * Returns true when any client was removed (and subscribers were notified).
116
+ * Tests call this with a controllable {@link setPresenceNow}.
117
+ */
118
+ export function expireStalePresence(ctx: HostCtx, now: number = presenceNow()): boolean {
119
+ const s = stateFor(ctx);
120
+ let removed = false;
121
+ for (const [id, entry] of s.clients) {
122
+ if (now - entry.lastSeen > PRESENCE_STALE_MS) {
123
+ for (const port of entry.ports) {
124
+ if (s.portToClient.get(port) === id) s.portToClient.delete(port);
125
+ }
126
+ s.clients.delete(id);
127
+ removed = true;
128
+ }
129
+ }
130
+ if (removed) {
131
+ broadcast(ctx);
132
+ stopExpiryTimerIfIdle(ctx);
133
+ }
134
+ return removed;
135
+ }
136
+
137
+ /** Authoritative presence snapshot for diagnostics / tests. */
138
+ export function getPresenceSnapshot(ctx: HostCtx): PresenceSnapshot {
139
+ expireStalePresence(ctx);
140
+ return toSnapshot(stateFor(ctx));
141
+ }
142
+
143
+ const PRESENCE_METHODS = new Set<string>([
144
+ 'presence.register',
145
+ 'presence.heartbeat',
146
+ 'presence.update',
147
+ 'presence.disconnect',
148
+ ]);
149
+
150
+ export function isPresenceOp(method: OpMessage['method']): boolean {
151
+ return PRESENCE_METHODS.has(method);
152
+ }
153
+
154
+ export async function handlePresenceOp(
155
+ ctx: HostCtx,
156
+ port: PortLike,
157
+ msg: OpMessage,
158
+ ): Promise<void> {
159
+ const s = stateFor(ctx);
160
+ expireStalePresence(ctx);
161
+
162
+ switch (msg.method) {
163
+ case 'presence.register': {
164
+ const { clientId, kind, route, visibility } = msg;
165
+ if (!clientId || (kind !== 'app' && kind !== 'studio')) {
166
+ fail(port, msg.id, new Error('presence.register: invalid clientId/kind'));
167
+ return;
168
+ }
169
+ const now = presenceNow();
170
+ const existing = s.clients.get(clientId);
171
+ if (existing) {
172
+ // Re-register (reload / reconnect): one logical entry, refresh metadata,
173
+ // associate this port, drop stale port associations for this clientId.
174
+ for (const p of existing.ports) {
175
+ if (s.portToClient.get(p) === clientId) s.portToClient.delete(p);
176
+ }
177
+ existing.ports.clear();
178
+ existing.ports.add(port);
179
+ existing.kind = kind;
180
+ existing.route = route;
181
+ existing.visibility = visibility;
182
+ existing.lastSeen = now;
183
+ // Keep original connectedAt across reconnects within the worker lifetime
184
+ // so the UI does not flicker "just connected" on a soft reload — but a
185
+ // full reconnect after disconnect/expiry starts fresh (new entry below).
186
+ } else {
187
+ s.clients.set(clientId, {
188
+ clientId,
189
+ kind,
190
+ route,
191
+ visibility,
192
+ connectedAt: now,
193
+ lastSeen: now,
194
+ ports: new Set([port]),
195
+ });
196
+ }
197
+ s.portToClient.set(port, clientId);
198
+ ensureExpiryTimer(ctx);
199
+ ok(port, msg.id, { ok: true });
200
+ broadcast(ctx);
201
+ break;
202
+ }
203
+
204
+ case 'presence.heartbeat': {
205
+ const entry = s.clients.get(msg.clientId);
206
+ if (!entry) {
207
+ // Unknown / already expired — client should re-register.
208
+ ok(port, msg.id, { ok: false, reason: 'unknown' });
209
+ return;
210
+ }
211
+ entry.lastSeen = presenceNow();
212
+ entry.ports.add(port);
213
+ s.portToClient.set(port, msg.clientId);
214
+ ok(port, msg.id, { ok: true });
215
+ // Heartbeats renew the lease without broadcasting — lastSeen freshness
216
+ // is only needed for expiry; subscribers care about connect/disconnect/
217
+ // route/visibility. Still broadcast so Studio can show freshness if it
218
+ // wants; cheap for small N.
219
+ broadcast(ctx);
220
+ break;
221
+ }
222
+
223
+ case 'presence.update': {
224
+ const entry = s.clients.get(msg.clientId);
225
+ if (!entry) {
226
+ ok(port, msg.id, { ok: false, reason: 'unknown' });
227
+ return;
228
+ }
229
+ if (msg.route !== undefined) entry.route = msg.route;
230
+ if (msg.visibility !== undefined) entry.visibility = msg.visibility;
231
+ entry.lastSeen = presenceNow();
232
+ entry.ports.add(port);
233
+ s.portToClient.set(port, msg.clientId);
234
+ ok(port, msg.id, { ok: true });
235
+ broadcast(ctx);
236
+ break;
237
+ }
238
+
239
+ case 'presence.disconnect': {
240
+ const entry = s.clients.get(msg.clientId);
241
+ if (entry) {
242
+ for (const p of entry.ports) {
243
+ if (s.portToClient.get(p) === msg.clientId) s.portToClient.delete(p);
244
+ }
245
+ s.clients.delete(msg.clientId);
246
+ ok(port, msg.id, { ok: true });
247
+ broadcast(ctx);
248
+ stopExpiryTimerIfIdle(ctx);
249
+ } else {
250
+ ok(port, msg.id, { ok: true });
251
+ }
252
+ break;
253
+ }
254
+
255
+ default: {
256
+ fail(port, msg.id, new Error(`Unknown method: ${String((msg as { method: unknown }).method)}`));
257
+ }
258
+ }
259
+ }
260
+
261
+ export function handlePresenceSub(ctx: HostCtx, port: PortLike, msg: PresenceSubMessage): void {
262
+ expireStalePresence(ctx);
263
+ const s = stateFor(ctx);
264
+ let subIds = s.subs.get(port);
265
+ if (!subIds) {
266
+ subIds = new Set();
267
+ s.subs.set(port, subIds);
268
+ }
269
+ if (subIds.has(msg.subId)) return;
270
+ subIds.add(msg.subId);
271
+ ensureExpiryTimer(ctx);
272
+ post(port, { t: 'snap', subId: msg.subId, value: toSnapshot(s) });
273
+ }
274
+
275
+ export function handlePresenceUnsub(ctx: HostCtx, port: PortLike, subId: string): boolean {
276
+ const s = stateFor(ctx);
277
+ const subIds = s.subs.get(port);
278
+ if (!subIds || !subIds.has(subId)) return false;
279
+ subIds.delete(subId);
280
+ if (subIds.size === 0) s.subs.delete(port);
281
+ stopExpiryTimerIfIdle(ctx);
282
+ return true;
283
+ }
284
+
285
+ /**
286
+ * Port-close optimization: if this port was the last association for a
287
+ * logical client, remove that client. Lease expiry remains the correctness
288
+ * path when close events are missing.
289
+ */
290
+ export function cleanupPortPresence(ctx: HostCtx, port: PortLike): void {
291
+ const s = stateFor(ctx);
292
+ // Drop presence subscriptions on this port.
293
+ s.subs.delete(port);
294
+
295
+ const clientId = s.portToClient.get(port);
296
+ s.portToClient.delete(port);
297
+ if (!clientId) {
298
+ stopExpiryTimerIfIdle(ctx);
299
+ return;
300
+ }
301
+ const entry = s.clients.get(clientId);
302
+ if (!entry) {
303
+ stopExpiryTimerIfIdle(ctx);
304
+ return;
305
+ }
306
+ entry.ports.delete(port);
307
+ if (entry.ports.size === 0) {
308
+ s.clients.delete(clientId);
309
+ broadcast(ctx);
310
+ }
311
+ stopExpiryTimerIfIdle(ctx);
312
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * SharedWorker host — RTDB modular ops (playground shared-runtime bridge).
3
+ *
4
+ * `rtdb.get/set/update/remove/push` run against the op's lens-resolved Database
5
+ * handle (impersonation / admin / anon / port-session, via `lensRtdb`);
6
+ * `rtdb.adminSnapshot` reads the whole tree through the rules-bypass admin
7
+ * handle. Owns the RTDB server-sentinel reconstruction and the snapshot→wire
8
+ * shaping (`rtdbSnapToWire`, also used by the value-subscription handler).
9
+ *
10
+ * Routed here by the host dispatcher. Never imports the dispatcher.
11
+ */
12
+
13
+ import {
14
+ ref as rtdbRef,
15
+ get as rtdbGet,
16
+ set as rtdbSet,
17
+ update as rtdbUpdate,
18
+ remove as rtdbRemove,
19
+ serverTimestamp as rtdbServerTimestamp,
20
+ sandbox as rtdbSandbox,
21
+ type DataSnapshot,
22
+ } from 'pyric/database';
23
+
24
+ import type { OpMessage } from '../protocol.js';
25
+ import { type HostCtx, type PortLike, ok, fail, bestEffortFlush } from '../host-context.js';
26
+ import { lensRtdb } from './core.js';
27
+
28
+ export function rtdbSnapToWire(snap: DataSnapshot): unknown {
29
+ return {
30
+ key: snap.key,
31
+ exists: snap.exists(),
32
+ value: snap.val(),
33
+ size: snap.size,
34
+ };
35
+ }
36
+
37
+ function resolveRtdbSentinels(value: unknown): unknown {
38
+ if (value && typeof value === 'object') {
39
+ const marker = value as { __rtdbSentinel?: unknown };
40
+ if (marker.__rtdbSentinel === 'serverTimestamp') return rtdbServerTimestamp();
41
+ if (Array.isArray(value)) return value.map(resolveRtdbSentinels);
42
+ const out: Record<string, unknown> = {};
43
+ for (const [k, v] of Object.entries(value)) out[k] = resolveRtdbSentinels(v);
44
+ return out;
45
+ }
46
+ return value;
47
+ }
48
+
49
+ /** The RTDB op methods routed to {@link handleRtdbOp}. */
50
+ const RTDB_METHODS = new Set<string>([
51
+ 'rtdb.get',
52
+ 'rtdb.set',
53
+ 'rtdb.update',
54
+ 'rtdb.remove',
55
+ 'rtdb.push',
56
+ 'rtdb.adminSnapshot',
57
+ ]);
58
+
59
+ export function isRtdbOp(method: OpMessage['method']): boolean {
60
+ return RTDB_METHODS.has(method);
61
+ }
62
+
63
+ export async function handleRtdbOp(
64
+ ctx: HostCtx,
65
+ port: PortLike,
66
+ msg: OpMessage,
67
+ ): Promise<void> {
68
+ switch (msg.method) {
69
+ case 'rtdb.get': {
70
+ try {
71
+ const db = lensRtdb(ctx, msg.actAs, port);
72
+ ok(port, msg.id, rtdbSnapToWire(await rtdbGet(rtdbRef(db, msg.path))));
73
+ } catch (e) { fail(port, msg.id, e); }
74
+ break;
75
+ }
76
+
77
+ case 'rtdb.set': {
78
+ try {
79
+ const db = lensRtdb(ctx, msg.actAs, port);
80
+ const value = resolveRtdbSentinels(msg.value);
81
+ await rtdbSet(rtdbRef(db, msg.path), value as never);
82
+ await bestEffortFlush(ctx);
83
+ ok(port, msg.id, null);
84
+ } catch (e) { fail(port, msg.id, e); }
85
+ break;
86
+ }
87
+
88
+ case 'rtdb.update': {
89
+ try {
90
+ const db = lensRtdb(ctx, msg.actAs, port);
91
+ await rtdbUpdate(rtdbRef(db, msg.path), resolveRtdbSentinels(msg.values) as Record<string, unknown>);
92
+ await bestEffortFlush(ctx);
93
+ ok(port, msg.id, null);
94
+ } catch (e) { fail(port, msg.id, e); }
95
+ break;
96
+ }
97
+
98
+ case 'rtdb.remove': {
99
+ try {
100
+ const db = lensRtdb(ctx, msg.actAs, port);
101
+ await rtdbRemove(rtdbRef(db, msg.path));
102
+ await bestEffortFlush(ctx);
103
+ ok(port, msg.id, null);
104
+ } catch (e) { fail(port, msg.id, e); }
105
+ break;
106
+ }
107
+
108
+ case 'rtdb.push': {
109
+ try {
110
+ const db = lensRtdb(ctx, msg.actAs, port);
111
+ const childPath = `${msg.path}/${msg.key}`;
112
+ if (msg.value !== undefined) {
113
+ await rtdbSet(
114
+ rtdbRef(db, childPath),
115
+ resolveRtdbSentinels(msg.value) as never,
116
+ );
117
+ await bestEffortFlush(ctx);
118
+ }
119
+ const normalizedPath = `/${childPath.split('/').filter(Boolean).join('/')}`;
120
+ ok(port, msg.id, { key: msg.key, path: normalizedPath });
121
+ } catch (e) { fail(port, msg.id, e); }
122
+ break;
123
+ }
124
+
125
+ case 'rtdb.adminSnapshot': {
126
+ try {
127
+ ok(port, msg.id, rtdbSandbox.snapshotState(lensRtdb(ctx, { mode: 'admin' }, port)));
128
+ } catch (e) { fail(port, msg.id, e); }
129
+ break;
130
+ }
131
+
132
+ default: {
133
+ fail(port, msg.id, new Error(`Unknown method: ${String((msg as { method: unknown }).method)}`));
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * SharedWorker host — rules deploy + status ops.
3
+ *
4
+ * Firestore rules hot-reload (`setRules`/`setFirestoreRules`), RTDB rules
5
+ * deploy (`setDatabaseRules`), and the active-rules / status reflection
6
+ * (`getActiveRules`/`getRulesStatus`) that shared-runtime diagnostics + revert
7
+ * read. Tracks the deployed source + last-known-good on `ctx.activeRules`.
8
+ *
9
+ * Routed here by the host dispatcher with the op's resolved Firestore handle
10
+ * (`db`, used by the firestore-rules deploy). Never imports the dispatcher.
11
+ */
12
+
13
+ import type { Firestore } from 'pyric/firestore';
14
+ import { setRules } from 'pyric/sandbox/firestore';
15
+ import { sandbox as rtdbSandbox } from 'pyric/database';
16
+
17
+ import type { OpMessage } from '../protocol.js';
18
+ import { type HostCtx, type PortLike, ok, fail } from '../host-context.js';
19
+ import { ensureRtdb } from './core.js';
20
+
21
+ function normalizeDatabaseRules(source: unknown): { rules: Record<string, unknown> } | null {
22
+ if (source === null) return null;
23
+ if (typeof source === 'string') {
24
+ return JSON.parse(source) as { rules: Record<string, unknown> };
25
+ }
26
+ if (typeof source === 'object' && source !== null) {
27
+ return source as { rules: Record<string, unknown> };
28
+ }
29
+ throw new Error('RTDB rules must be a rules JSON object or JSON string.');
30
+ }
31
+
32
+ function firestoreRuleMessages(result: { warnings?: Array<{ severity?: string; message?: string }>; parseError?: { line?: number; column?: number; expected?: unknown; actual?: string } | null }) {
33
+ const messages: Array<{ severity: 'info' | 'warn' | 'error'; text: string; line?: number; column?: number }> = [];
34
+ if (result.parseError) {
35
+ messages.push({
36
+ severity: 'error',
37
+ text: `PARSE ERROR: expected ${String(result.parseError.expected ?? 'valid rules')}`,
38
+ line: result.parseError.line,
39
+ column: result.parseError.column,
40
+ });
41
+ }
42
+ for (const warning of result.warnings ?? []) {
43
+ messages.push({
44
+ severity: warning.severity === 'error' ? 'error' : warning.severity === 'warning' ? 'warn' : 'info',
45
+ text: String(warning.message ?? warning),
46
+ });
47
+ }
48
+ return messages;
49
+ }
50
+
51
+ /** The rules deploy/status op methods routed to {@link handleRulesOp}. */
52
+ const RULES_METHODS = new Set<string>([
53
+ 'setRules',
54
+ 'setFirestoreRules',
55
+ 'setDatabaseRules',
56
+ 'getActiveRules',
57
+ 'getRulesStatus',
58
+ ]);
59
+
60
+ export function isRulesOp(method: OpMessage['method']): boolean {
61
+ return RULES_METHODS.has(method);
62
+ }
63
+
64
+ export function handleRulesOp(
65
+ ctx: HostCtx,
66
+ port: PortLike,
67
+ msg: OpMessage,
68
+ db: Firestore,
69
+ ): void {
70
+ switch (msg.method) {
71
+ case 'setRules':
72
+ case 'setFirestoreRules': {
73
+ try {
74
+ const result = setRules(ctx.sandbox, msg.source);
75
+ const messages = firestoreRuleMessages(result);
76
+ const okDeploy = !messages.some((m) => m.severity === 'error');
77
+ ctx.activeRules ??= {};
78
+ const previous = ctx.activeRules.firestore?.status === 'active'
79
+ ? ctx.activeRules.firestore.source
80
+ : ctx.activeRules.firestore?.lastKnownGood;
81
+ ctx.activeRules.firestore = {
82
+ source: okDeploy ? msg.source : ctx.activeRules.firestore?.source ?? msg.source,
83
+ updatedAt: Date.now(),
84
+ status: okDeploy ? 'active' : 'error',
85
+ messages,
86
+ ...(previous ? { lastKnownGood: previous } : {}),
87
+ };
88
+ ok(port, msg.id, { warnings: result.warnings, messages, ok: okDeploy });
89
+ } catch (e) { fail(port, msg.id, e); }
90
+ break;
91
+ }
92
+
93
+ case 'setDatabaseRules': {
94
+ try {
95
+ const db = ensureRtdb(ctx);
96
+ const rules = normalizeDatabaseRules(msg.source);
97
+ const previous = ctx.activeRules?.database?.status === 'active'
98
+ ? ctx.activeRules.database.source
99
+ : ctx.activeRules?.database?.lastKnownGood;
100
+ rtdbSandbox.setRules(db, rules);
101
+ ctx.activeRules ??= {};
102
+ ctx.activeRules.database = {
103
+ source: rules,
104
+ updatedAt: Date.now(),
105
+ status: 'active',
106
+ messages: [],
107
+ ...(previous ? { lastKnownGood: previous } : {}),
108
+ };
109
+ ok(port, msg.id, { ok: true, messages: [] });
110
+ } catch (e) { fail(port, msg.id, e); }
111
+ break;
112
+ }
113
+
114
+ case 'getActiveRules': {
115
+ ok(port, msg.id, msg.service ? ctx.activeRules?.[msg.service] ?? null : ctx.activeRules ?? {});
116
+ break;
117
+ }
118
+
119
+ case 'getRulesStatus': {
120
+ ok(port, msg.id, msg.service ? ctx.activeRules?.[msg.service] ?? null : ctx.activeRules ?? {});
121
+ break;
122
+ }
123
+
124
+ default: {
125
+ fail(port, msg.id, new Error(`Unknown method: ${String((msg as { method: unknown }).method)}`));
126
+ }
127
+ }
128
+ }