@pyric/cli 0.1.0-alpha.18 → 0.1.0-alpha.20

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 (356) hide show
  1. package/README.md +14 -9
  2. package/dist/bridge/server/mcp-contract.d.ts +2 -2
  3. package/dist/bridge/server/mcp-contract.d.ts.map +1 -1
  4. package/dist/bridge/server/mcp-contract.js +3 -0
  5. package/dist/bridge/server/mcp-contract.js.map +1 -1
  6. package/dist/cli/index.d.ts +3 -2
  7. package/dist/cli/index.d.ts.map +1 -1
  8. package/dist/cli/index.js +51 -42
  9. package/dist/cli/index.js.map +1 -1
  10. package/dist/cli/mcp-proxy.d.ts.map +1 -1
  11. package/dist/cli/mcp-proxy.js +3 -3
  12. package/dist/cli/mcp-proxy.js.map +1 -1
  13. package/dist/cli/parse-args.d.ts +1 -1
  14. package/dist/cli/parse-args.d.ts.map +1 -1
  15. package/dist/cli/parse-args.js +51 -15
  16. package/dist/cli/parse-args.js.map +1 -1
  17. package/dist/cli/pyric-config.d.ts +24 -0
  18. package/dist/cli/pyric-config.d.ts.map +1 -0
  19. package/dist/cli/pyric-config.js +28 -0
  20. package/dist/cli/pyric-config.js.map +1 -0
  21. package/dist/cli/rules.d.ts +1 -0
  22. package/dist/cli/rules.d.ts.map +1 -1
  23. package/dist/cli/rules.js +18 -4
  24. package/dist/cli/rules.js.map +1 -1
  25. package/dist/cli/{dev-runner.d.ts → sandbox-runner.d.ts} +33 -36
  26. package/dist/cli/sandbox-runner.d.ts.map +1 -0
  27. package/dist/cli/{dev-runner.js → sandbox-runner.js} +90 -55
  28. package/dist/cli/sandbox-runner.js.map +1 -0
  29. package/dist/cli/serve.d.ts +6 -4
  30. package/dist/cli/serve.d.ts.map +1 -1
  31. package/dist/cli/serve.js +99 -40
  32. package/dist/cli/serve.js.map +1 -1
  33. package/dist/cli/service-command-records/storage-rules-resolve.d.ts +4 -0
  34. package/dist/cli/service-command-records/storage-rules-resolve.d.ts.map +1 -0
  35. package/dist/cli/service-command-records/storage-rules-resolve.js +3 -0
  36. package/dist/cli/service-command-records/storage-rules-resolve.js.map +1 -0
  37. package/dist/cli/service-commands.generated.d.ts +3 -0
  38. package/dist/cli/service-commands.generated.d.ts.map +1 -1
  39. package/dist/cli/service-commands.generated.js +2 -0
  40. package/dist/cli/service-commands.generated.js.map +1 -1
  41. package/dist/cli/snapshot.js +5 -5
  42. package/dist/cli/snapshot.js.map +1 -1
  43. package/dist/cli/verify.js +1 -1
  44. package/dist/cli/verify.js.map +1 -1
  45. package/dist/functions-rtdb/development-runtime.js +1 -1
  46. package/dist/functions-rtdb/development-runtime.js.map +1 -1
  47. package/dist/functions-rtdb/project.js +8 -8
  48. package/dist/functions-rtdb/project.js.map +1 -1
  49. package/dist/next/guard.js +1 -1
  50. package/dist/next/guard.js.map +1 -1
  51. package/dist/remote/index.d.ts +1 -1
  52. package/dist/remote/index.js +9 -9
  53. package/dist/remote/index.js.map +1 -1
  54. package/dist/serve/bundler.js +10 -10
  55. package/dist/serve/bundler.js.map +1 -1
  56. package/dist/serve/entries/ai.d.ts.map +1 -1
  57. package/dist/serve/entries/ai.js +27 -1
  58. package/dist/serve/entries/ai.js.map +1 -1
  59. package/dist/serve/entries/auth-helper-dom.js +1 -1
  60. package/dist/serve/entries/auth-helper-dom.js.map +1 -1
  61. package/dist/serve/entries/auth-helper-runtime.js +1 -1
  62. package/dist/serve/entries/auth-helper-runtime.js.map +1 -1
  63. package/dist/serve/entries/firestore.js +3 -3
  64. package/dist/serve/entries/firestore.js.map +1 -1
  65. package/dist/serve/entries/keepalive.js +1 -1
  66. package/dist/serve/entries/keepalive.js.map +1 -1
  67. package/dist/serve/entries/runtime.js +21 -14
  68. package/dist/serve/entries/runtime.js.map +1 -1
  69. package/dist/serve/entries/storage.js +1 -1
  70. package/dist/serve/entries/storage.js.map +1 -1
  71. package/dist/serve/entries/worker-runtime.js +1 -1
  72. package/dist/serve/entries/worker-runtime.js.map +1 -1
  73. package/dist/serve/init-payload.d.ts +4 -0
  74. package/dist/serve/init-payload.d.ts.map +1 -1
  75. package/dist/serve/namespace.d.ts +6 -0
  76. package/dist/serve/namespace.d.ts.map +1 -1
  77. package/dist/serve/namespace.js +36 -5
  78. package/dist/serve/namespace.js.map +1 -1
  79. package/dist/serve/rules.d.ts +3 -3
  80. package/dist/serve/rules.d.ts.map +1 -1
  81. package/dist/serve/rules.js +56 -25
  82. package/dist/serve/rules.js.map +1 -1
  83. package/dist/serve/runtime/chip.d.ts.map +1 -1
  84. package/dist/serve/runtime/chip.js +32 -1
  85. package/dist/serve/runtime/chip.js.map +1 -1
  86. package/dist/serve/runtime/manifest.d.ts +1 -1
  87. package/dist/serve/runtime/manifest.d.ts.map +1 -1
  88. package/dist/serve/runtime/manifest.js +1 -1
  89. package/dist/serve/runtime/manifest.js.map +1 -1
  90. package/dist/serve/runtime/status.d.ts.map +1 -1
  91. package/dist/serve/runtime/status.js +23 -0
  92. package/dist/serve/runtime/status.js.map +1 -1
  93. package/dist/serve/sandbox-session.d.ts +1 -0
  94. package/dist/serve/sandbox-session.d.ts.map +1 -1
  95. package/dist/serve/sandbox-session.js +10 -4
  96. package/dist/serve/sandbox-session.js.map +1 -1
  97. package/dist/serve/server.d.ts +7 -0
  98. package/dist/serve/server.d.ts.map +1 -1
  99. package/dist/serve/server.js +15 -1
  100. package/dist/serve/server.js.map +1 -1
  101. package/dist/serve/site-ui/404.html +1 -1
  102. package/dist/serve/site-ui/_astro/{RulesCodeEditor.CzwHdCi9.js → RulesCodeEditor.XtDmHOlN.js} +1 -1
  103. package/dist/serve/site-ui/_astro/_example_.B9DG9HLJ.css +1 -0
  104. package/dist/serve/site-ui/_astro/_slug_.Da5VLhW1.css +1 -0
  105. package/dist/serve/site-ui/_astro/_studio_.BnfYCKoI.css +1 -0
  106. package/dist/serve/site-ui/_astro/app.B52xr-DK.js +1 -0
  107. package/dist/serve/site-ui/_astro/app.DWBraPUw.js +12 -0
  108. package/dist/serve/site-ui/_astro/app.pMSnN6Qw.css +1 -0
  109. package/dist/serve/site-ui/_astro/chess-showcase.B72XYeoh.js +354 -0
  110. package/dist/serve/site-ui/_astro/{example-runtime.B0byNQOl.js → example-runtime.C25_lx6Z.js} +2 -26
  111. package/dist/serve/site-ui/_astro/index.Tb-31efc.css +1 -0
  112. package/dist/serve/site-ui/_astro/index.UkCBr-_0.css +1 -0
  113. package/dist/serve/site-ui/_astro/sandbox-controls.DEpnKg-O.js +1169 -0
  114. package/dist/serve/site-ui/_astro/seed.Co0yUJY5.js +20 -0
  115. package/dist/serve/site-ui/_astro/writes.rpjrFzmu.js +102 -0
  116. package/dist/serve/site-ui/auth/index.html +5 -3
  117. package/dist/serve/site-ui/david-east.jpg +0 -0
  118. package/dist/serve/site-ui/docs/_rhythm/index.html +6 -3
  119. package/dist/serve/site-ui/docs/_rhythm.md +1 -1
  120. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +45 -17
  121. package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +20 -17
  122. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +6 -5
  123. package/dist/serve/site-ui/docs/agent/watch-and-review.md +1 -5
  124. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +8 -5
  125. package/dist/serve/site-ui/docs/agent/work-with-an-agent.md +4 -4
  126. package/dist/serve/site-ui/docs/ai-compat/index.html +5 -2
  127. package/dist/serve/site-ui/docs/api-reference/index.html +6 -2
  128. package/dist/serve/site-ui/docs/api-reference.md +1 -0
  129. package/dist/serve/site-ui/docs/app-compat/index.html +5 -2
  130. package/dist/serve/site-ui/docs/auth-compat/index.html +5 -2
  131. package/dist/serve/site-ui/docs/build/ai-logic/index.html +5 -2
  132. package/dist/serve/site-ui/docs/build/authentication/index.html +7 -4
  133. package/dist/serve/site-ui/docs/build/authentication.md +2 -2
  134. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +34 -53
  135. package/dist/serve/site-ui/docs/build/cloud-firestore.md +40 -36
  136. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +5 -2
  137. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +6 -3
  138. package/dist/serve/site-ui/docs/build/cloud-storage.md +1 -1
  139. package/dist/serve/site-ui/docs/build/realtime-database/index.html +9 -6
  140. package/dist/serve/site-ui/docs/build/realtime-database.md +4 -4
  141. package/dist/serve/site-ui/docs/conformance-scores/index.html +5 -2
  142. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -3
  143. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +1 -1
  144. package/dist/serve/site-ui/docs/database-compat/index.html +5 -2
  145. package/dist/serve/site-ui/docs/examples/chess/index.html +649 -250
  146. package/dist/serve/site-ui/docs/examples/chess.md +45 -16
  147. package/dist/serve/site-ui/docs/examples/index.html +6 -3
  148. package/dist/serve/site-ui/docs/firestore-compat/index.html +5 -2
  149. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +5 -2
  150. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +9 -6
  151. package/dist/serve/site-ui/docs/get-started/how-the-swap-works.md +5 -5
  152. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +9 -6
  153. package/dist/serve/site-ui/docs/get-started/nextjs.md +4 -4
  154. package/dist/serve/site-ui/docs/get-started/start-building/index.html +41 -10
  155. package/dist/serve/site-ui/docs/get-started/start-building.md +21 -10
  156. package/dist/serve/site-ui/docs/get-started/vite/index.html +6 -3
  157. package/dist/serve/site-ui/docs/get-started/vite.md +1 -1
  158. package/dist/serve/site-ui/docs/index.json +203 -168
  159. package/dist/serve/site-ui/docs/messaging-compat/index.html +5 -2
  160. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +5 -2
  161. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +6 -4
  162. package/dist/serve/site-ui/docs/observe/see-whats-happening.md +2 -4
  163. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +9 -6
  164. package/dist/serve/site-ui/docs/observe/shape-your-data.md +4 -4
  165. package/dist/serve/site-ui/docs/overview/index.html +16 -10
  166. package/dist/serve/site-ui/docs/overview.md +19 -11
  167. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +5 -2
  168. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +5 -2
  169. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +5 -2
  170. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +8 -5
  171. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +3 -3
  172. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +5 -2
  173. package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +501 -0
  174. package/dist/serve/site-ui/docs/pyric-admin-reference-api.md +587 -0
  175. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +5 -2
  176. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +5 -2
  177. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +5 -2
  178. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +5 -2
  179. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +5 -2
  180. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +5 -2
  181. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +5 -2
  182. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +5 -2
  183. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +5 -2
  184. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +5 -2
  185. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +5 -2
  186. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +5 -2
  187. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +5 -2
  188. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +5 -2
  189. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +5 -2
  190. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +5 -2
  191. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +5 -2
  192. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +6 -3
  193. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +1 -1
  194. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +5 -2
  195. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +5 -2
  196. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +5 -2
  197. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +166 -95
  198. package/dist/serve/site-ui/docs/pyric-database-reference-api.md +107 -1
  199. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +5 -2
  200. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +10 -4
  201. package/dist/serve/site-ui/docs/pyric-messaging-reference-api.md +5 -2
  202. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +10 -4
  203. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api.md +5 -2
  204. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +5 -2
  205. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +5 -2
  206. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +6 -3
  207. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api.md +2 -2
  208. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +5 -2
  209. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +5 -2
  210. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +5 -2
  211. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +5 -2
  212. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +5 -2
  213. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +5 -2
  214. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +5 -2
  215. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +5 -2
  216. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +5 -2
  217. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +5 -2
  218. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -2
  219. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +5 -2
  220. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +5 -2
  221. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +5 -2
  222. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +5 -2
  223. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +5 -2
  224. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +5 -2
  225. package/dist/serve/site-ui/docs/reference/cli/index.html +153 -0
  226. package/dist/serve/site-ui/docs/reference/cli.md +114 -0
  227. package/dist/serve/site-ui/docs/rules-compat/index.html +5 -2
  228. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +5 -2
  229. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +5 -2
  230. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +6 -3
  231. package/dist/serve/site-ui/docs/secure/read-a-denial.md +1 -1
  232. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +5 -2
  233. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +5 -2
  234. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +5 -2
  235. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +5 -2
  236. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +5 -2
  237. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +7 -4
  238. package/dist/serve/site-ui/docs/ship/ship-to-production.md +2 -2
  239. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +9 -6
  240. package/dist/serve/site-ui/docs/ship/test-in-node.md +4 -4
  241. package/dist/serve/site-ui/docs/storage-compat/index.html +5 -2
  242. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +5 -2
  243. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +5 -2
  244. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +5 -2
  245. package/dist/serve/site-ui/docs/tutorial/index.html +10 -7
  246. package/dist/serve/site-ui/docs/tutorial.md +4 -4
  247. package/dist/serve/site-ui/examples/chess/index.html +4 -2
  248. package/dist/serve/site-ui/firestore/index.html +5 -3
  249. package/dist/serve/site-ui/hero-charcoal.jpg +0 -0
  250. package/dist/serve/site-ui/index.html +9 -7
  251. package/dist/serve/site-ui/llms.txt +4 -3
  252. package/dist/serve/site-ui/pyric-campfire-full.png +0 -0
  253. package/dist/serve/site-ui/pyric-campfire.png +0 -0
  254. package/dist/serve/site-ui/rtdb/index.html +5 -3
  255. package/dist/serve/site-ui/settings/index.html +5 -3
  256. package/dist/serve/site-ui/storage/index.html +5 -3
  257. package/dist/serve/site-ui/studio/index.html +13 -0
  258. package/dist/serve/site-ui/studio-routes.json +1 -1
  259. package/dist/serve/site-ui/traffic/index.html +5 -3
  260. package/dist/serve/studio/routes.d.ts +9 -0
  261. package/dist/serve/studio/routes.d.ts.map +1 -1
  262. package/dist/serve/studio/routes.js +47 -7
  263. package/dist/serve/studio/routes.js.map +1 -1
  264. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  265. package/dist/serve/vite-ai-config.js +38 -8
  266. package/dist/serve/vite-ai-config.js.map +1 -1
  267. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  268. package/dist/serve/vite-module-swap.js +0 -28
  269. package/dist/serve/vite-module-swap.js.map +1 -1
  270. package/dist/serve/vite-rules-source.d.ts.map +1 -1
  271. package/dist/serve/vite-rules-source.js +28 -7
  272. package/dist/serve/vite-rules-source.js.map +1 -1
  273. package/dist/serve/vite-sandbox-generation.d.ts +1 -1
  274. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
  275. package/dist/serve/vite-sandbox-generation.js +1 -1
  276. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  277. package/dist/serve/worker/client/disconnect.js +1 -1
  278. package/dist/serve/worker/client/disconnect.js.map +1 -1
  279. package/dist/serve/worker/client/presence.d.ts.map +1 -1
  280. package/dist/serve/worker/client/presence.js +18 -5
  281. package/dist/serve/worker/client/presence.js.map +1 -1
  282. package/dist/serve/worker/host-ai.d.ts.map +1 -1
  283. package/dist/serve/worker/host-ai.js +15 -0
  284. package/dist/serve/worker/host-ai.js.map +1 -1
  285. package/dist/serve/worker/protocol.d.ts +4 -0
  286. package/dist/serve/worker/protocol.d.ts.map +1 -1
  287. package/dist/serve/worker/protocol.js.map +1 -1
  288. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  289. package/dist/serve/worker/serve-init.js +7 -1
  290. package/dist/serve/worker/serve-init.js.map +1 -1
  291. package/package.json +5 -5
  292. package/src/bridge/server/mcp-contract.ts +3 -0
  293. package/src/cli/cli.test.ts +2 -2
  294. package/src/cli/index.ts +51 -42
  295. package/src/cli/mcp-proxy.ts +10 -11
  296. package/src/cli/parse-args.ts +61 -15
  297. package/src/cli/pyric-config.ts +45 -0
  298. package/src/cli/rules.ts +31 -4
  299. package/src/cli/{dev-runner.ts → sandbox-runner.ts} +117 -72
  300. package/src/cli/serve.ts +115 -47
  301. package/src/cli/service-command-records/storage-rules-resolve.ts +4 -0
  302. package/src/cli/service-commands.generated.ts +2 -0
  303. package/src/cli/snapshot.ts +5 -5
  304. package/src/cli/verify.ts +1 -1
  305. package/src/functions-rtdb/development-runtime.ts +1 -1
  306. package/src/functions-rtdb/project.ts +8 -8
  307. package/src/next/guard.ts +1 -1
  308. package/src/remote/index.ts +9 -9
  309. package/src/serve/bundler.ts +10 -10
  310. package/src/serve/entries/ai.ts +27 -1
  311. package/src/serve/entries/auth-helper-dom.ts +1 -1
  312. package/src/serve/entries/auth-helper-runtime.ts +1 -1
  313. package/src/serve/entries/firestore.ts +3 -3
  314. package/src/serve/entries/keepalive.ts +1 -1
  315. package/src/serve/entries/runtime.ts +19 -14
  316. package/src/serve/entries/storage.ts +1 -1
  317. package/src/serve/entries/worker-runtime.ts +1 -1
  318. package/src/serve/init-payload.ts +4 -0
  319. package/src/serve/namespace.ts +44 -5
  320. package/src/serve/rules.ts +61 -26
  321. package/src/serve/runtime/chip.ts +38 -1
  322. package/src/serve/runtime/manifest.ts +1 -1
  323. package/src/serve/runtime/status.ts +24 -0
  324. package/src/serve/sandbox-session.ts +10 -4
  325. package/src/serve/server.ts +18 -1
  326. package/src/serve/studio/routes.ts +63 -7
  327. package/src/serve/vite-ai-config.ts +37 -7
  328. package/src/serve/vite-module-swap.ts +0 -28
  329. package/src/serve/vite-rules-source.ts +29 -7
  330. package/src/serve/vite-sandbox-generation.ts +1 -1
  331. package/src/serve/worker/client/disconnect.ts +1 -1
  332. package/src/serve/worker/client/presence.ts +25 -5
  333. package/src/serve/worker/host-ai.ts +15 -0
  334. package/src/serve/worker/protocol.ts +2 -1
  335. package/src/serve/worker/serve-init.ts +5 -1
  336. package/README.md.orig +0 -141
  337. package/dist/cli/dev-runner.d.ts.map +0 -1
  338. package/dist/cli/dev-runner.js.map +0 -1
  339. package/dist/serve/site-ui/_astro/_example_.jevZ7OdV.css +0 -1
  340. package/dist/serve/site-ui/_astro/_slug_.C6QfVOxJ.css +0 -1
  341. package/dist/serve/site-ui/_astro/_slug_.CXh9yTP1.css +0 -1
  342. package/dist/serve/site-ui/_astro/_studio_.B6b_G1ev.css +0 -1
  343. package/dist/serve/site-ui/_astro/app.B7pBzz5N.js +0 -11
  344. package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +0 -1
  345. package/dist/serve/site-ui/_astro/app.boex5SnQ.js +0 -1
  346. package/dist/serve/site-ui/_astro/chess-showcase.DDqE-QGe.js +0 -1
  347. package/dist/serve/site-ui/_astro/chess-source-explorer.C5k9c5yK.js +0 -1
  348. package/dist/serve/site-ui/_astro/chess-v2.CFHmd3UL.js +0 -354
  349. package/dist/serve/site-ui/_astro/index.uwPvjH_1.js +0 -1
  350. package/dist/serve/site-ui/_astro/jsx-runtime.D_zvdyIk.js +0 -9
  351. package/dist/serve/site-ui/_astro/reads.Dh3z0fJy.js +0 -1
  352. package/dist/serve/site-ui/_astro/sandbox-controls.C2IqtoSw.js +0 -1252
  353. package/dist/serve/site-ui/_astro/seed.CCmj00su.js +0 -20
  354. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +0 -582
  355. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +0 -448
  356. package/dist/serve/site-ui/examples/firestore-first-write/index.html +0 -2
package/src/cli/index.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * `pyric` CLI front door to the bridge + project tooling.
3
+ * `pyric` CLI front door to the bridge and project tooling.
4
4
  *
5
5
  * Subcommands:
6
6
  * pyric bridge [--port N] [--project ID]
7
- * pyric dev [--port N] [--host H] [--no-cache] [--bridge] [--ui] [--seed FILE] [--no-watch] [--no-open] [--no-capture] [--no-run] [--json] [--persist] [--fresh] [-- <cmd>]
7
+ * pyric sandbox [flags] [--] [command...]
8
8
  * pyric init [dir] [--template web|node] [--name N] [--force] [--json]
9
9
  * pyric vendor [dir] [--json]
10
10
  * pyric snapshot [--out FILE] [--port N] [--force] [--json] [--include-passwords]
@@ -15,6 +15,7 @@
15
15
  * pyric firestore rules resolve <path> [--out <path>]
16
16
  * pyric firestore indexes generate <path...> [--out <path>]
17
17
  * pyric storage rules lint <path>
18
+ * pyric storage rules resolve <path> [--out <path>]
18
19
  * pyric storage rules simulate [--stdin]
19
20
  * pyric database rules lint <path>
20
21
  * pyric database rules validate <path>
@@ -54,12 +55,12 @@ const VERSION = pyricVersion();
54
55
 
55
56
  function printUsage(): void {
56
57
  process.stdout.write(`pyric ${VERSION}
57
- Firebase for agents bridge an in-browser pyric sandbox to external MCP
58
+ Firebase for agents. Bridge an in-browser Pyric sandbox to external MCP
58
59
  clients (Claude Code, Cursor, ...).
59
60
 
60
61
  USAGE
61
62
  pyric bridge [flags]
62
- pyric dev [flags] [-- <cmd>]
63
+ pyric sandbox [flags] [--] [command...]
63
64
  pyric init [dir] [--template=web|node]
64
65
  pyric snapshot [--out=FILE]
65
66
  pyric verify [fixture|dir] [--engine sandbox|rules-test-api|both]
@@ -71,6 +72,7 @@ USAGE
71
72
  pyric firestore rules resolve <path> [--out <path>]
72
73
  pyric firestore indexes generate <path...> [--out <path>]
73
74
  pyric storage rules lint <path>
75
+ pyric storage rules resolve <path> [--out <path>]
74
76
  pyric storage rules simulate [--stdin]
75
77
  pyric database rules lint <path>
76
78
  pyric database rules validate <path>
@@ -81,16 +83,14 @@ USAGE
81
83
 
82
84
  COMMANDS
83
85
  bridge Start the HTTP+WebSocket bridge external MCP clients point at.
84
- dev Serve the app locally with the pyric sandbox standing in for
85
- Firebase unmodified firebase/* imports hit an in-page sandbox
86
- with your firestore.rules deployed. Also runs your own dev
87
- command (\`-- <cmd>\`, else the package.json \`dev\` script) with
88
- unchanged firebase-admin/firebase imports routed to the
89
- sandbox (PYRIC_SANDBOX + \`--import @pyric/cli/register\`). A
90
- firebase.json Functions source is discovered automatically;
86
+ sandbox [command...] Run an application command or script inside the local Firebase sandbox
87
+ with unmodified firebase/* and firebase-admin/* imports routed to the
88
+ in-memory mirror. When [command...] is omitted, runs the command
89
+ configured in pyric.json; if none is configured, runs the sandbox host only.
90
+ A firebase.json Functions source is discovered automatically;
91
91
  supported RTDB onValueCreated exports run in isolated Node.
92
92
  init [dir] Scaffold a pyric project. --template=web (default; Vite app
93
- on \`@pyric/cli/vite\`), static (\`pyric dev\`), or node.
93
+ on \`@pyric/cli/vite\`), static (\`pyric sandbox\`), or node.
94
94
  --name=NAME --force (overwrite scaffold files) --json (machine
95
95
  output on stdout). Never prompts; rerunning is safe.
96
96
  Greenfield shortcut: \`npm create pyric [dir]\`.
@@ -100,15 +100,15 @@ COMMANDS
100
100
  bun install. Standalone binary only.
101
101
  mcp Stdio MCP server for editors (Cursor / Claude /
102
102
  Antigravity). Hosts a headless in-process sandbox,
103
- or attaches to a running \`pyric dev --bridge\`
103
+ or attaches to a running \`pyric sandbox --bridge\`
104
104
  (found via .pyric/serve.json) for shared-live Studio.
105
- snapshot [--out=FILE] Promote lived sandbox state (live dev --persist, else
105
+ snapshot [--out=FILE] Promote lived sandbox state (live sandbox --persist, else
106
106
  .pyric/state/state.json) to a committable fixture that
107
- \`pyric dev --seed FILE\` re-serves. Passwords are redacted
107
+ \`pyric sandbox --seed FILE\` re-serves. Passwords are redacted
108
108
  by default (--include-passwords keeps them). --port, --force, --json.
109
109
  verify [fixture|dir] Replay a captured sandbox session against candidate rules
110
110
  for the Firestore/RTDB services present in the fixture.
111
- No arg replays the latest \`pyric dev\` capture
111
+ No arg replays the latest \`pyric sandbox\` capture
112
112
  (.pyric/last-session.json). --service filters services.
113
113
  --engine sandbox (default), rules-test-api, or both.
114
114
  Hosted Rules Test API verification is Firestore-only
@@ -127,64 +127,73 @@ COMMANDS
127
127
  firestore rules resolve Resolve Firestore 2+modules imports to one ruleset.
128
128
  firestore indexes generate Generate firestore.indexes.json from application source.
129
129
  storage rules lint Check Storage rules syntax locally.
130
+ storage rules resolve Resolve Storage 2+modules imports to one ruleset.
130
131
  storage rules simulate Run the local Storage rules evaluator.
131
132
  database rules lint Run the Realtime Database rules expression linter.
132
133
  database rules validate Validate Realtime Database rules expressions.
133
134
  database rules simulate Run the local Realtime Database rules simulator.
134
135
  database rules generate Compile a constraints module to database.rules.json.
135
- CORE FLAGS (dev)
136
- --port Port to serve on. Default 3473 "FIRE" on a phone keypad (scans forward when taken;
137
- macOS AirPlay squats 5000).
136
+ CORE FLAGS (sandbox)
137
+ --port Port to serve on. Default 3473. Pyric scans forward when
138
+ the selected port is taken.
138
139
  --host Host to bind. Default localhost.
139
140
  --no-cache Rebuild the served pyric SDK bundles (skip ~/.pyric/serve-cache).
140
141
  --only hosting Accepted for firebase-serve parity (hosting is all v1 serves).
141
- --bridge Also mount the MCP bridge on the serve origin agents point
142
+ --bridge Also mount the MCP bridge on the serve origin. Agents point
142
143
  at http://<host>:<port>/__pyric/mcp and drive the sandbox
143
144
  living in the served page. --project labels health/audit.
144
- --ui Also serve the Pyric Studio app at <url>/__pyric/ui/ (and
145
- mount its disk-backed workspace + project data routes).
146
- Auto-opens Studio instead of the served page. Needs a full
147
- build so the app assets are present.
148
- --seed FILE JSON map of "collection/doc" → fields, loaded admin-style.
145
+ --ui Open Studio instead of the served page. Studio and docs
146
+ are served by default at <url>/__pyric/ui/.
147
+ --no-ui Do not serve Studio, docs, workspace, or project routes.
148
+ --seed FILE JSON map of "collection/doc" to fields, loaded with admin access.
149
149
  Also accepts a pyric state file (from \`pyric snapshot\`,
150
- detected by its version key) seeds docs + auth users.
151
- into the page sandbox before app code runs.
150
+ detected by its version key). Seeds documents and auth users
151
+ before application code runs.
152
152
  --no-watch Disable firestore.rules hot-reload (on by default).
153
- --no-open Don't auto-open the browser. dev opens the served page
153
+ --no-open Don't auto-open the browser. sandbox opens the served page
154
154
  by default (the sandbox is browser-resident); auto-open
155
155
  is already suppressed under --json, no TTY, and CI.
156
- --no-capture Don't write the session capture. dev writes
156
+ --no-capture Don't write the session capture. sandbox writes
157
157
  .pyric/last-session.json by default so \`pyric verify\`
158
158
  can replay your session; --no-capture disables it.
159
+ --permissive Allow unauthenticated Realtime Database reads and writes when no
160
+ rules file is present. For local prototyping only.
159
161
  --allowed-host H Allow an extra Host header past the DNS-rebinding guard
160
162
  (comma-separated; localhost/127.0.0.1 always allowed).
161
163
  --persist Persist sandbox state (docs + auth users) to
162
- .pyric/state/state.json survives reloads and dev
164
+ .pyric/state/state.json. It survives reloads and sandbox
163
165
  restarts. Once a state file exists it wins; --seed
164
166
  applies only on the first (state-less) run. Ephemeral
165
167
  is the default.
166
168
  --fresh Requires --persist: discard the existing state file and
167
169
  re-seed from scratch (escape hatch when you've edited
168
- seed.json). Without --persist, --fresh errors there is
170
+ seed.json). Without --persist, --fresh errors because there is
169
171
  no state file to discard. Half-reset warning: a browser
170
172
  tab that already has sandbox data in IndexedDB keeps it
171
173
  and writes it back to the new file; also clear the
172
- browser store (Studio Settings Reset, or an
174
+ browser store in Studio under Settings, Reset, or use an
173
175
  incognito window) for a full reset.
174
- -- <cmd> Run <cmd> once the host is up, with PYRIC_SANDBOX set and
176
+ [command...] Run a command once the host is up, with PYRIC_SANDBOX set and
175
177
  NODE_OPTIONS extended with --import @pyric/cli/register
176
- so firebase-admin/firebase resolve to the sandbox. When
177
- omitted, the package.json \`dev\` script runs (via the
178
- detected package manager); no script host-only.
179
- --no-run Don't run the project's dev command (for users with their
180
- own process manager). A declared Functions source still
181
- runs. --json skips the dev command unless a \`-- <cmd>\`
182
- is given explicitly.
178
+ so firebase-admin/firebase resolve to the sandbox. Put
179
+ Pyric flags before the command. A bare -- separates the
180
+ command and its flags. When omitted, pyric.json#command
181
+ runs. With no configured command, the host runs alone.
182
+ --no-run Don't run an explicit or configured command. A declared
183
+ Functions source still runs.
183
184
  --json One machine-readable line on stdout ({url, port, mcpUrl,
184
185
  rulesHash, persist, restoredDocs, restoredUsers}); the
185
- banner moves to stderr. Readiness probe:
186
+ banner moves to stderr. A pyric.json command is skipped
187
+ unless a command is supplied explicitly. Readiness probe:
186
188
  GET <url>/__pyric/init.json → 200 (live rules hash).
187
189
 
190
+ PROJECT CONFIG (pyric.json)
191
+ command Default child command. An explicit CLI command overrides it.
192
+ port Default sandbox port. --port overrides it.
193
+ project Project label. --project, then PYRIC_PROJECT, override it.
194
+ rules Firestore rules path, or an object with firestore,
195
+ database, and storage paths.
196
+
188
197
  CORE FLAGS (bridge)
189
198
  --port Port to bind on 127.0.0.1. Default 5174. Env: PYRIC_PORT.
190
199
  --project Project label surfaced in /health + audit output.
@@ -333,7 +342,7 @@ export async function dispatch(parsed: ParsedArgs): Promise<number> {
333
342
  return parsed.subcommand === null ? 0 : 1;
334
343
  case 'bridge':
335
344
  return await runBridge(parsed);
336
- case 'dev':
345
+ case 'sandbox':
337
346
  const { runServe } = await import('./serve.js');
338
347
  return runServe(parsed);
339
348
  case 'snapshot':
@@ -1,17 +1,16 @@
1
1
  /**
2
2
  * `pyric mcp-proxy` — a stdio MCP server that relays to a RUNNING
3
- * `pyric dev --bridge`'s HTTP MCP endpoint.
3
+ * the HTTP MCP endpoint from `pyric sandbox --bridge`.
4
4
  *
5
- * Why this exists: a Claude Code plugin can only declare a STATIC MCP URL in
6
- * `.mcp.json`, but serve's endpoint is `http://localhost:<PORT>/__pyric/mcp`
7
- * with a runtime port (scan-forward / AirPlay). So the plugin declares a
8
- * STDIO server that runs this proxy; the proxy discovers the live serve and
9
- * forwards the protocol. No manual `claude mcp add`, no fixed port.
5
+ * Why this exists: the agent plugin declares one static stdio command, while
6
+ * serve's endpoint is `http://localhost:<PORT>/__pyric/mcp` with a runtime
7
+ * port (scan-forward / AirPlay). The proxy discovers the live serve and
8
+ * forwards the protocol. No per-client MCP setup, no fixed port.
10
9
  * (design rationale)
11
10
  *
12
11
  * Relay is at the TRANSPORT level via the MCP SDK's own transports — we do
13
12
  * NOT re-implement JSON-RPC/SSE/session framing. `StdioServerTransport`
14
- * talks to Claude Code; `StreamableHTTPClientTransport` talks to serve; each
13
+ * talks to the MCP client; `StreamableHTTPClientTransport` talks to serve; each
15
14
  * transport's `onmessage` is piped to the other's `send`.
16
15
  *
17
16
  * Two hardening layers sit on top of that pipe:
@@ -22,7 +21,7 @@
22
21
  * + IPv6 `[::1]:P`); without this, the proxy locks onto whichever family
23
22
  * answers first while the browser is on the other — split-brain.
24
23
  * TIMEOUT — every relayed request is failed with a JSON-RPC error after
25
- * REQUEST_TIMEOUT_MS instead of hanging Claude Code forever (a killed
24
+ * REQUEST_TIMEOUT_MS instead of hanging the agent forever (a killed
26
25
  * server can leave a half-open keep-alive socket that never FINs). A
27
26
  * `settled` set swallows a late real response so the client never sees a
28
27
  * duplicate after the timeout already failed the call.
@@ -85,12 +84,12 @@ export async function runMcpProxy(
85
84
  if (!found) {
86
85
  // Hybrid mode (design rationale): no dev server to attach to, so host the
87
86
  // sandbox IN this process. Zero setup, no browser tab required. A running
88
- // `pyric dev --bridge` upgrades to the shared-live experience on reconnect.
87
+ // `pyric sandbox --bridge` upgrades to the shared session on reconnect.
89
88
  log(
90
- 'no running `pyric dev --bridge` found (looked for .pyric/serve.json and ports ' +
89
+ 'no running `pyric sandbox --bridge` found (looked for .pyric/serve.json and ports ' +
91
90
  `${SCAN_PORTS.join(', ')}); starting a headless in-process sandbox (zero-setup).\n` +
92
91
  ' Data persists to .pyric/state/headless.json. For a shared-live Studio\n' +
93
- ' session, start `pyric dev --bridge` BEFORE connecting the agent (a dev server\n' +
92
+ ' session, start `pyric sandbox --bridge` before connecting the agent (a sandbox host\n' +
94
93
  ' started mid-session does not yet adopt this headless data).',
95
94
  );
96
95
  const headless =
@@ -12,17 +12,54 @@ export interface ParsedArgs {
12
12
  subcommand: string | null;
13
13
  flags: Map<string, FlagValue>;
14
14
  positional: string[];
15
- /** Everything after a bare `--`, verbatim (e.g. `pyric dev -- npm start`).
15
+ /** Everything after a bare `--`, verbatim (e.g. `pyric sandbox -- npm start`).
16
16
  * Optional so hand-built ParsedArgs literals stay valid. */
17
17
  passthrough?: string[];
18
18
  }
19
19
 
20
20
  export type FlagValue = string | boolean | Array<string | boolean>;
21
21
 
22
- // Flags whose command contract is boolean must not consume a following
23
- // positional. Value-bearing flags retain the Firebase-style `--flag value`
24
- // form, while explicit boolean values remain available as `--json=true`.
25
- const BOOLEAN_FLAGS = new Set(['json']);
22
+ const BOOLEAN_FLAGS = new Set([
23
+ 'json',
24
+ 'bridge',
25
+ 'ui',
26
+ 'no-ui',
27
+ 'no-open',
28
+ 'no-run',
29
+ 'no-cache',
30
+ 'no-watch',
31
+ 'no-capture',
32
+ 'persist',
33
+ 'fresh',
34
+ 'force',
35
+ 'permissive',
36
+ 'help',
37
+ 'version',
38
+ ]);
39
+
40
+ function isBooleanFlag(key: string): boolean {
41
+ return BOOLEAN_FLAGS.has(key) || key.startsWith('no-');
42
+ }
43
+
44
+ const SHORT_VALUE_ALIASES: ReadonlyMap<string, string> = new Map([
45
+ ['p', 'port'],
46
+ ]);
47
+
48
+ function consumeFlag(
49
+ flags: Map<string, FlagValue>,
50
+ key: string,
51
+ argv: string[],
52
+ currentIndex: number,
53
+ canTakeValue: boolean,
54
+ ): number {
55
+ const next = argv[currentIndex + 1];
56
+ if (canTakeValue && next !== undefined && !next.startsWith('-')) {
57
+ setFlag(flags, key, next);
58
+ return currentIndex + 1;
59
+ }
60
+ setFlag(flags, key, true);
61
+ return currentIndex;
62
+ }
26
63
 
27
64
  export function parseArgs(argv: string[]): ParsedArgs {
28
65
  const flags = new Map<string, FlagValue>();
@@ -38,26 +75,31 @@ export function parseArgs(argv: string[]): ParsedArgs {
38
75
  }
39
76
  if (arg === '--') {
40
77
  // Everything after a bare `--` belongs to the child command, verbatim
41
- // — never parsed as flags (`pyric dev -- npm start --port 3000`).
78
+ // — never parsed as flags (`pyric sandbox -- npm start --port 3000`).
42
79
  passthrough.push(...argv.slice(i + 1).filter((a): a is string => a !== undefined));
43
80
  break;
44
81
  }
82
+ if (isExecutionSubcommand(subcommand) && positional.length > 0) {
83
+ positional.push(arg);
84
+ i += 1;
85
+ continue;
86
+ }
45
87
  if (arg.startsWith('--')) {
46
88
  const eq = arg.indexOf('=');
47
89
  if (eq !== -1) {
48
90
  setFlag(flags, arg.slice(2, eq), arg.slice(eq + 1));
49
91
  } else {
50
92
  const key = arg.slice(2);
51
- const next = argv[i + 1];
52
- if (!BOOLEAN_FLAGS.has(key) && next && !next.startsWith('-')) {
53
- setFlag(flags, key, next);
54
- i += 1;
55
- } else {
56
- setFlag(flags, key, true);
57
- }
93
+ i = consumeFlag(flags, key, argv, i, !isBooleanFlag(key));
94
+ }
95
+ } else if (arg.startsWith('-') && arg !== '-') {
96
+ const raw = arg.slice(1);
97
+ const longKey = SHORT_VALUE_ALIASES.get(raw);
98
+ if (longKey !== undefined) {
99
+ i = consumeFlag(flags, longKey, argv, i, true);
100
+ } else {
101
+ setFlag(flags, raw, true);
58
102
  }
59
- } else if (arg.startsWith('-')) {
60
- setFlag(flags, arg.slice(1), true);
61
103
  } else if (subcommand === null) {
62
104
  subcommand = arg;
63
105
  } else {
@@ -68,6 +110,10 @@ export function parseArgs(argv: string[]): ParsedArgs {
68
110
  return { subcommand, flags, positional, passthrough };
69
111
  }
70
112
 
113
+ function isExecutionSubcommand(subcommand: string | null): boolean {
114
+ return subcommand === 'sandbox';
115
+ }
116
+
71
117
  function setFlag(flags: Map<string, FlagValue>, key: string, value: string | boolean): void {
72
118
  const current = flags.get(key);
73
119
  if (current === undefined) {
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Reader for the optional project-level `pyric.json` configuration file.
3
+ *
4
+ * Configures defaults for `pyric sandbox` (such as a default `command`,
5
+ * custom `port`, or explicit `rules` paths) without requiring CLI flags
6
+ * or magic process sniffing.
7
+ */
8
+
9
+ import { readFile } from 'node:fs/promises';
10
+ import { join } from 'node:path';
11
+
12
+ export interface PyricRulesConfig {
13
+ firestore?: string;
14
+ database?: string;
15
+ storage?: string;
16
+ }
17
+
18
+ export interface PyricConfig {
19
+ /** Default command to execute under the sandbox if none is passed on CLI. */
20
+ command?: string;
21
+ /** Local port to bind the Pyric sandbox host. */
22
+ port?: number;
23
+ /** Path to Firestore, RTDB, or Storage rules files. */
24
+ rules?: string | PyricRulesConfig;
25
+ /** Project ID label for emulation. */
26
+ project?: string;
27
+ }
28
+
29
+ export async function readPyricConfig(cwd: string = process.cwd()): Promise<PyricConfig> {
30
+ const path = join(cwd, 'pyric.json');
31
+ let raw: string;
32
+ try {
33
+ raw = await readFile(path, 'utf-8');
34
+ } catch (e) {
35
+ if ((e as NodeJS.ErrnoException).code === 'ENOENT') return {};
36
+ throw e;
37
+ }
38
+ try {
39
+ return JSON.parse(raw) as PyricConfig;
40
+ } catch (e) {
41
+ throw new Error(
42
+ `pyric: failed to parse pyric.json: ${e instanceof Error ? e.message : String(e)}`,
43
+ );
44
+ }
45
+ }
package/src/cli/rules.ts CHANGED
@@ -125,14 +125,30 @@ export async function runRulesValidate(parsed: ParsedArgs, deps: RulesDeps = {})
125
125
  export async function runRulesResolve(
126
126
  parsed: ParsedArgs,
127
127
  deps: ResolveRulesDeps = {},
128
+ ): Promise<number> {
129
+ return runServiceRulesResolve('firestore', parsed, deps);
130
+ }
131
+
132
+ export async function runStorageRulesResolve(
133
+ parsed: ParsedArgs,
134
+ deps: ResolveRulesDeps = {},
135
+ ): Promise<number> {
136
+ return runServiceRulesResolve('storage', parsed, deps);
137
+ }
138
+
139
+ async function runServiceRulesResolve(
140
+ service: 'firestore' | 'storage',
141
+ parsed: ParsedArgs,
142
+ deps: ResolveRulesDeps,
128
143
  ): Promise<number> {
129
144
  const out = deps.stdout ?? process.stdout;
130
145
  const err = deps.stderr ?? process.stderr;
131
146
  const cwd = deps.cwd ?? process.cwd();
147
+ const command = `pyric ${service} rules resolve`;
132
148
  const sourcePath = parsed.positional[0];
133
149
  if (!sourcePath) {
134
150
  err.write(
135
- 'pyric firestore rules resolve: missing rules-file path. Usage: pyric firestore rules resolve <path> [--out <path>]\n',
151
+ `${command}: missing rules-file path. Usage: ${command} <path> [--out <path>]\n`,
136
152
  );
137
153
  return 1;
138
154
  }
@@ -143,16 +159,27 @@ export async function runRulesResolve(
143
159
  source = await (deps.readFile ?? readFile)(absoluteSourcePath, 'utf-8');
144
160
  } catch (error) {
145
161
  err.write(
146
- `pyric firestore rules resolve: ${error instanceof Error ? error.message : String(error)}\n`,
162
+ `${command}: ${error instanceof Error ? error.message : String(error)}\n`,
147
163
  );
148
164
  return 1;
149
165
  }
150
166
 
167
+ const expectedService =
168
+ service === 'storage' ? 'firebase.storage' : 'cloud.firestore';
169
+ const parsedSource = parseToAST(source);
170
+ if (parsedSource && parsedSource.service.name !== expectedService) {
171
+ err.write(
172
+ `${command}: source declares service ${parsedSource.service.name}; expected ${expectedService}\n`,
173
+ );
174
+ return 2;
175
+ }
176
+
151
177
  const result = (deps.resolveModules ?? resolveModules)(source, {
152
178
  basePath: dirname(absoluteSourcePath),
179
+ sourceFile: sourcePath,
153
180
  });
154
181
  if (!result.success) {
155
- err.write(`pyric firestore rules resolve: ${result.error.message}\n`);
182
+ err.write(`${command}: ${result.error.message}\n`);
156
183
  return 2;
157
184
  }
158
185
 
@@ -169,7 +196,7 @@ export async function runRulesResolve(
169
196
  result.data.resolved.endsWith('\n') ? result.data.resolved : `${result.data.resolved}\n`,
170
197
  'utf-8',
171
198
  );
172
- out.write(`pyric firestore rules resolve: wrote ${outputPath}\n`);
199
+ out.write(`${command}: wrote ${outputPath}\n`);
173
200
  return 0;
174
201
  }
175
202