@pyric/cli 0.1.0-alpha.16 → 0.1.0-alpha.17

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 (378) hide show
  1. package/README.md +13 -9
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +80 -72
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +80 -72
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/cli/database-rules.d.ts.map +1 -1
  7. package/dist/cli/database-rules.js +6 -4
  8. package/dist/cli/database-rules.js.map +1 -1
  9. package/dist/cli/dev-runner.d.ts +9 -0
  10. package/dist/cli/dev-runner.d.ts.map +1 -1
  11. package/dist/cli/dev-runner.js +18 -0
  12. package/dist/cli/dev-runner.js.map +1 -1
  13. package/dist/cli/serve.d.ts.map +1 -1
  14. package/dist/cli/serve.js +61 -6
  15. package/dist/cli/serve.js.map +1 -1
  16. package/dist/cli/verify.js +2 -2
  17. package/dist/cli/verify.js.map +1 -1
  18. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  19. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  20. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  21. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  22. package/dist/conformance/.generated/can-i-use.js +1 -1
  23. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  24. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  25. package/dist/conformance/.generated/conformance-docs.js +1 -1
  26. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  27. package/dist/next/client-aliases.d.ts +11 -0
  28. package/dist/next/client-aliases.d.ts.map +1 -0
  29. package/dist/next/client-aliases.js +38 -0
  30. package/dist/next/client-aliases.js.map +1 -0
  31. package/dist/next/dev-rewrites.d.ts +9 -0
  32. package/dist/next/dev-rewrites.d.ts.map +1 -0
  33. package/dist/next/dev-rewrites.js +53 -0
  34. package/dist/next/dev-rewrites.js.map +1 -0
  35. package/dist/next/guard.d.ts +15 -0
  36. package/dist/next/guard.d.ts.map +1 -0
  37. package/dist/next/guard.js +52 -0
  38. package/dist/next/guard.js.map +1 -0
  39. package/dist/next/index.d.ts +12 -0
  40. package/dist/next/index.d.ts.map +1 -0
  41. package/dist/next/index.js +11 -0
  42. package/dist/next/index.js.map +1 -0
  43. package/dist/next/runtime-env.d.ts +7 -0
  44. package/dist/next/runtime-env.d.ts.map +1 -0
  45. package/dist/next/runtime-env.js +13 -0
  46. package/dist/next/runtime-env.js.map +1 -0
  47. package/dist/next/server-external-packages.d.ts +10 -0
  48. package/dist/next/server-external-packages.d.ts.map +1 -0
  49. package/dist/next/server-external-packages.js +34 -0
  50. package/dist/next/server-external-packages.js.map +1 -0
  51. package/dist/next/target-url.d.ts +11 -0
  52. package/dist/next/target-url.d.ts.map +1 -0
  53. package/dist/next/target-url.js +36 -0
  54. package/dist/next/target-url.js.map +1 -0
  55. package/dist/next/turbopack-config.d.ts +9 -0
  56. package/dist/next/turbopack-config.d.ts.map +1 -0
  57. package/dist/next/turbopack-config.js +39 -0
  58. package/dist/next/turbopack-config.js.map +1 -0
  59. package/dist/next/types.d.ts +40 -0
  60. package/dist/next/types.d.ts.map +1 -0
  61. package/dist/next/types.js +5 -0
  62. package/dist/next/types.js.map +1 -0
  63. package/dist/next/webpack-config.d.ts +11 -0
  64. package/dist/next/webpack-config.d.ts.map +1 -0
  65. package/dist/next/webpack-config.js +51 -0
  66. package/dist/next/webpack-config.js.map +1 -0
  67. package/dist/next/with-pyric.d.ts +22 -0
  68. package/dist/next/with-pyric.d.ts.map +1 -0
  69. package/dist/next/with-pyric.js +49 -0
  70. package/dist/next/with-pyric.js.map +1 -0
  71. package/dist/register/app-bridge.d.ts +9 -0
  72. package/dist/register/app-bridge.d.ts.map +1 -0
  73. package/dist/register/app-bridge.js +56 -0
  74. package/dist/register/app-bridge.js.map +1 -0
  75. package/dist/register/hooks.d.ts.map +1 -1
  76. package/dist/register/hooks.js +6 -1
  77. package/dist/register/hooks.js.map +1 -1
  78. package/dist/register/index.js +1 -1
  79. package/dist/register/index.js.map +1 -1
  80. package/dist/register/mapping.d.ts +3 -1
  81. package/dist/register/mapping.d.ts.map +1 -1
  82. package/dist/register/mapping.js +41 -5
  83. package/dist/register/mapping.js.map +1 -1
  84. package/dist/rtdb/rules-json.d.ts +12 -0
  85. package/dist/rtdb/rules-json.d.ts.map +1 -1
  86. package/dist/rtdb/rules-json.js +98 -0
  87. package/dist/rtdb/rules-json.js.map +1 -1
  88. package/dist/serve/bundler.d.ts.map +1 -1
  89. package/dist/serve/bundler.js +2 -0
  90. package/dist/serve/bundler.js.map +1 -1
  91. package/dist/serve/discovery.d.ts +4 -4
  92. package/dist/serve/discovery.d.ts.map +1 -1
  93. package/dist/serve/discovery.js +59 -38
  94. package/dist/serve/discovery.js.map +1 -1
  95. package/dist/serve/entries/app-ai-passthrough.d.ts +8 -0
  96. package/dist/serve/entries/app-ai-passthrough.d.ts.map +1 -0
  97. package/dist/serve/entries/app-ai-passthrough.js +59 -0
  98. package/dist/serve/entries/app-ai-passthrough.js.map +1 -0
  99. package/dist/serve/entries/auth-helper-core.js +9 -7
  100. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  101. package/dist/serve/entries/auth.d.ts +1 -0
  102. package/dist/serve/entries/auth.d.ts.map +1 -1
  103. package/dist/serve/entries/auth.js +1 -0
  104. package/dist/serve/entries/auth.js.map +1 -1
  105. package/dist/serve/entries/bridge-url.d.ts.map +1 -1
  106. package/dist/serve/entries/bridge-url.js +7 -2
  107. package/dist/serve/entries/bridge-url.js.map +1 -1
  108. package/dist/serve/entries/database.d.ts +1 -0
  109. package/dist/serve/entries/database.d.ts.map +1 -1
  110. package/dist/serve/entries/database.js +1 -0
  111. package/dist/serve/entries/database.js.map +1 -1
  112. package/dist/serve/entries/firestore.d.ts +1 -0
  113. package/dist/serve/entries/firestore.d.ts.map +1 -1
  114. package/dist/serve/entries/firestore.js +1 -0
  115. package/dist/serve/entries/firestore.js.map +1 -1
  116. package/dist/serve/entries/init.d.ts.map +1 -1
  117. package/dist/serve/entries/init.js +4 -2
  118. package/dist/serve/entries/init.js.map +1 -1
  119. package/dist/serve/entries/runtime.js +23 -0
  120. package/dist/serve/entries/runtime.js.map +1 -1
  121. package/dist/serve/entries/storage.d.ts +2 -0
  122. package/dist/serve/entries/storage.d.ts.map +1 -1
  123. package/dist/serve/entries/storage.js +9 -2
  124. package/dist/serve/entries/storage.js.map +1 -1
  125. package/dist/serve/html-injection.d.ts +3 -1
  126. package/dist/serve/html-injection.d.ts.map +1 -1
  127. package/dist/serve/html-injection.js +27 -1
  128. package/dist/serve/html-injection.js.map +1 -1
  129. package/dist/serve/rules.js +2 -2
  130. package/dist/serve/rules.js.map +1 -1
  131. package/dist/serve/runtime/chip-config.d.ts +1 -1
  132. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  133. package/dist/serve/runtime/chip-config.js +16 -8
  134. package/dist/serve/runtime/chip-config.js.map +1 -1
  135. package/dist/serve/sandbox-session.d.ts +1 -0
  136. package/dist/serve/sandbox-session.d.ts.map +1 -1
  137. package/dist/serve/sandbox-session.js +30 -2
  138. package/dist/serve/sandbox-session.js.map +1 -1
  139. package/dist/serve/site-ui/_astro/_studio_.B6b_G1ev.css +1 -0
  140. package/dist/serve/site-ui/_astro/app.bnmVTkIY.js +11 -0
  141. package/dist/serve/site-ui/_astro/app.t6u-adB_.js +1 -0
  142. package/dist/serve/site-ui/_astro/{chess-showcase.CnoxIle5.js → chess-showcase.kC8dXLKY.js} +1 -1
  143. package/dist/serve/site-ui/_astro/{example-runtime.R1d96L6-.js → example-runtime.D79PnoSk.js} +1 -1
  144. package/dist/serve/site-ui/_astro/index.DzVde04M.js +1 -0
  145. package/dist/serve/site-ui/_astro/reads.BYBRLbsE.js +1 -0
  146. package/dist/serve/site-ui/_astro/sandbox-controls.C9Aaazt8.js +1252 -0
  147. package/dist/serve/site-ui/_astro/{seed.EyI3VYEu.js → seed.DANAIyRw.js} +1 -1
  148. package/dist/serve/site-ui/auth/index.html +2 -2
  149. package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
  150. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +1 -1
  151. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
  152. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
  153. package/dist/serve/site-ui/docs/ai-compat/index.html +85 -85
  154. package/dist/serve/site-ui/docs/ai-compat.md +84 -84
  155. package/dist/serve/site-ui/docs/api-reference/index.html +3 -1
  156. package/dist/serve/site-ui/docs/api-reference.md +2 -0
  157. package/dist/serve/site-ui/docs/app-compat/index.html +28 -28
  158. package/dist/serve/site-ui/docs/app-compat.md +27 -27
  159. package/dist/serve/site-ui/docs/auth-compat/index.html +122 -122
  160. package/dist/serve/site-ui/docs/auth-compat.md +121 -121
  161. package/dist/serve/site-ui/docs/build/ai-logic/index.html +1 -1
  162. package/dist/serve/site-ui/docs/build/authentication/index.html +1 -1
  163. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +1 -1
  164. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
  165. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +1 -1
  166. package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
  167. package/dist/serve/site-ui/docs/conformance-scores/index.html +4 -4
  168. package/dist/serve/site-ui/docs/conformance-scores.md +3 -3
  169. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -6
  170. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +5 -5
  171. package/dist/serve/site-ui/docs/database-compat/index.html +200 -448
  172. package/dist/serve/site-ui/docs/database-compat.md +198 -461
  173. package/dist/serve/site-ui/docs/examples/chess/index.html +2 -2
  174. package/dist/serve/site-ui/docs/examples/index.html +1 -1
  175. package/dist/serve/site-ui/docs/firestore-compat/index.html +186 -195
  176. package/dist/serve/site-ui/docs/firestore-compat.md +184 -195
  177. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +15 -15
  178. package/dist/serve/site-ui/docs/functions-rtdb-compat.md +14 -14
  179. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
  180. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +57 -0
  181. package/dist/serve/site-ui/docs/get-started/nextjs.md +86 -0
  182. package/dist/serve/site-ui/docs/get-started/start-building/index.html +25 -8
  183. package/dist/serve/site-ui/docs/get-started/start-building.md +34 -5
  184. package/dist/serve/site-ui/docs/get-started/vite/index.html +26 -0
  185. package/dist/serve/site-ui/docs/get-started/vite.md +45 -0
  186. package/dist/serve/site-ui/docs/index.json +668 -103
  187. package/dist/serve/site-ui/docs/messaging-compat/index.html +56 -56
  188. package/dist/serve/site-ui/docs/messaging-compat.md +55 -55
  189. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +1 -1
  190. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
  191. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
  192. package/dist/serve/site-ui/docs/overview/index.html +1 -1
  193. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +39 -13
  194. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api.md +28 -2
  195. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
  196. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +38 -6
  197. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api.md +43 -0
  198. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +9 -1
  199. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +8 -0
  200. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
  201. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +27 -4
  202. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api.md +23 -0
  203. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
  204. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
  205. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
  206. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +1 -1
  207. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
  208. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
  209. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
  210. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
  211. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
  212. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
  213. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
  214. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
  215. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
  216. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +123 -0
  217. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +99 -0
  218. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +127 -0
  219. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api.md +174 -0
  220. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
  221. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
  222. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +570 -326
  223. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +198 -6
  224. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +1 -1
  225. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +1 -1
  226. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +1 -1
  227. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +2971 -627
  228. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +2873 -517
  229. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
  230. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
  231. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +43 -3
  232. package/dist/serve/site-ui/docs/pyric-rules-reference-api.md +8 -0
  233. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +26 -2
  234. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +24 -0
  235. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
  236. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +77 -9
  237. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +28 -13
  238. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +240 -63
  239. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +164 -5
  240. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
  241. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
  242. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
  243. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
  244. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
  245. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
  246. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
  247. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
  248. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
  249. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
  250. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
  251. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
  252. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +2 -1
  253. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +1 -0
  254. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
  255. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
  256. package/dist/serve/site-ui/docs/rules-compat/index.html +87 -79
  257. package/dist/serve/site-ui/docs/rules-compat.md +86 -78
  258. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
  259. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
  260. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
  261. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
  262. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
  263. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
  264. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
  265. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
  266. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +1 -1
  267. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
  268. package/dist/serve/site-ui/docs/storage-compat/index.html +119 -125
  269. package/dist/serve/site-ui/docs/storage-compat.md +118 -124
  270. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
  271. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
  272. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +1 -1
  273. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
  274. package/dist/serve/site-ui/docs/tutorial/index.html +1 -1
  275. package/dist/serve/site-ui/examples/chess/index.html +1 -1
  276. package/dist/serve/site-ui/examples/firestore-first-write/index.html +1 -1
  277. package/dist/serve/site-ui/firestore/index.html +2 -2
  278. package/dist/serve/site-ui/index.html +2 -2
  279. package/dist/serve/site-ui/llms.txt +6 -2
  280. package/dist/serve/site-ui/rtdb/index.html +2 -2
  281. package/dist/serve/site-ui/settings/index.html +2 -2
  282. package/dist/serve/site-ui/storage/index.html +2 -2
  283. package/dist/serve/site-ui/traffic/index.html +2 -2
  284. package/dist/serve/vite-ai-config.d.ts +4 -1
  285. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  286. package/dist/serve/vite-ai-config.js +83 -19
  287. package/dist/serve/vite-ai-config.js.map +1 -1
  288. package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -1
  289. package/dist/serve/vite-generation-rules-watch.js +61 -14
  290. package/dist/serve/vite-generation-rules-watch.js.map +1 -1
  291. package/dist/serve/vite-module-swap.d.ts +4 -1
  292. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  293. package/dist/serve/vite-module-swap.js +106 -21
  294. package/dist/serve/vite-module-swap.js.map +1 -1
  295. package/dist/serve/vite-plugin.d.ts.map +1 -1
  296. package/dist/serve/vite-plugin.js +45 -5
  297. package/dist/serve/vite-plugin.js.map +1 -1
  298. package/dist/serve/vite-sandbox-generation.js +1 -1
  299. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  300. package/dist/serve/worker/client/resumable.d.ts +30 -0
  301. package/dist/serve/worker/client/resumable.d.ts.map +1 -0
  302. package/dist/serve/worker/client/resumable.js +416 -0
  303. package/dist/serve/worker/client/resumable.js.map +1 -0
  304. package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -1
  305. package/dist/serve/worker/client/rtdb-references.js +4 -1
  306. package/dist/serve/worker/client/rtdb-references.js.map +1 -1
  307. package/dist/serve/worker/client/storage.d.ts +16 -2
  308. package/dist/serve/worker/client/storage.d.ts.map +1 -1
  309. package/dist/serve/worker/client/storage.js +57 -6
  310. package/dist/serve/worker/client/storage.js.map +1 -1
  311. package/dist/serve/worker/host/rules.d.ts.map +1 -1
  312. package/dist/serve/worker/host/rules.js +2 -1
  313. package/dist/serve/worker/host/rules.js.map +1 -1
  314. package/dist/serve/worker/index.d.ts +1 -1
  315. package/dist/serve/worker/index.d.ts.map +1 -1
  316. package/dist/serve/worker/index.js +1 -1
  317. package/dist/serve/worker/index.js.map +1 -1
  318. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  319. package/dist/serve/worker/serve-init.js +31 -0
  320. package/dist/serve/worker/serve-init.js.map +1 -1
  321. package/package.json +15 -4
  322. package/src/assurance/.generated/conformance-verdicts.ts +80 -72
  323. package/src/cli/cli.test.ts +14 -0
  324. package/src/cli/database-rules.ts +6 -4
  325. package/src/cli/dev-runner.ts +21 -0
  326. package/src/cli/serve.ts +62 -5
  327. package/src/cli/verify.ts +2 -2
  328. package/src/conformance/.generated/can-i-use-browser.ts +1 -1
  329. package/src/conformance/.generated/can-i-use.ts +1 -1
  330. package/src/conformance/.generated/conformance-docs.ts +1 -1
  331. package/src/next/client-aliases.ts +39 -0
  332. package/src/next/dev-rewrites.ts +77 -0
  333. package/src/next/guard.ts +61 -0
  334. package/src/next/index.ts +16 -0
  335. package/src/next/runtime-env.ts +18 -0
  336. package/src/next/server-external-packages.ts +43 -0
  337. package/src/next/target-url.ts +46 -0
  338. package/src/next/turbopack-config.ts +54 -0
  339. package/src/next/types.ts +47 -0
  340. package/src/next/webpack-config.ts +71 -0
  341. package/src/next/with-pyric.ts +58 -0
  342. package/src/register/app-bridge.ts +79 -0
  343. package/src/register/hooks.ts +6 -1
  344. package/src/register/index.ts +1 -1
  345. package/src/register/mapping.ts +50 -4
  346. package/src/rtdb/rules-json.ts +110 -0
  347. package/src/serve/bundler.ts +2 -0
  348. package/src/serve/discovery.ts +65 -44
  349. package/src/serve/entries/app-ai-passthrough.ts +83 -0
  350. package/src/serve/entries/auth-helper-core.ts +9 -7
  351. package/src/serve/entries/auth.ts +1 -0
  352. package/src/serve/entries/bridge-url.ts +9 -2
  353. package/src/serve/entries/database.ts +1 -0
  354. package/src/serve/entries/firestore.ts +1 -0
  355. package/src/serve/entries/init.ts +5 -2
  356. package/src/serve/entries/runtime.ts +25 -0
  357. package/src/serve/entries/storage.ts +12 -1
  358. package/src/serve/html-injection.ts +26 -1
  359. package/src/serve/rules.ts +2 -2
  360. package/src/serve/runtime/chip-config.ts +19 -6
  361. package/src/serve/sandbox-session.ts +31 -2
  362. package/src/serve/vite-ai-config.ts +86 -19
  363. package/src/serve/vite-generation-rules-watch.ts +67 -15
  364. package/src/serve/vite-module-swap.ts +121 -21
  365. package/src/serve/vite-plugin.ts +44 -6
  366. package/src/serve/vite-sandbox-generation.ts +1 -1
  367. package/src/serve/worker/client/resumable.ts +506 -0
  368. package/src/serve/worker/client/rtdb-references.ts +4 -1
  369. package/src/serve/worker/client/storage.ts +77 -7
  370. package/src/serve/worker/host/rules.ts +2 -1
  371. package/src/serve/worker/index.ts +4 -0
  372. package/src/serve/worker/serve-init.ts +30 -0
  373. package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +0 -1
  374. package/dist/serve/site-ui/_astro/app.4HeLP_FA.js +0 -109
  375. package/dist/serve/site-ui/_astro/app.BgSnCR5G.js +0 -1
  376. package/dist/serve/site-ui/_astro/index.BJiOemMX.js +0 -1
  377. package/dist/serve/site-ui/_astro/reads.BrKNdKAa.js +0 -1
  378. package/dist/serve/site-ui/_astro/sandbox-controls.BTb3EbQp.js +0 -1153
@@ -23,11 +23,57 @@ const MAPPINGS: ReadonlyArray<readonly [from: string, to: string]> = [
23
23
  * Map a Firebase specifier to its pyric mirror, or return `null` when the
24
24
  * specifier is not a Firebase package (leave it for the default resolver).
25
25
  */
26
- export function mapFirebaseSpecifier(specifier: string): string | null {
27
- if (specifier === 'firebase/app') return 'pyric/app/register';
26
+ export function mapFirebaseSpecifier(
27
+ specifier: string,
28
+ importer?: string,
29
+ options?: { aiMode?: 'sandbox' | 'production' },
30
+ ): string | null {
31
+ const isShadowBridgeImporter = importer !== undefined &&
32
+ (importer.includes('app-bridge') || importer.includes('app-ai-passthrough'));
33
+ const isFirebaseAppSpecifier = specifier === 'firebase/app';
34
+ const isBypassedBridgeImport = isShadowBridgeImporter && isFirebaseAppSpecifier;
35
+ if (isBypassedBridgeImport) {
36
+ return null;
37
+ }
38
+
39
+ let mode: 'sandbox' | 'production' = 'sandbox';
40
+ const explicitMode = options?.aiMode;
41
+ const hasExplicitMode = explicitMode !== undefined;
42
+ if (hasExplicitMode) {
43
+ mode = explicitMode;
44
+ } else {
45
+ const isEnvProductionMode = process.env.PYRIC_AI_MODE === 'production';
46
+ const isEnvPassthroughFlag = process.env.PYRIC_AI_PASSTHROUGH === '1';
47
+ const isProductionEnv = isEnvProductionMode || isEnvPassthroughFlag;
48
+ if (isProductionEnv) {
49
+ mode = 'production';
50
+ }
51
+ }
52
+
53
+ const isProductionMode = mode === 'production';
54
+ const isFirebaseAiSpecifier = specifier === 'firebase/ai';
55
+ const isProductionAiPassthrough = isProductionMode && isFirebaseAiSpecifier;
56
+ if (isProductionAiPassthrough) {
57
+ return null;
58
+ }
59
+
60
+ if (isFirebaseAppSpecifier) {
61
+ if (isProductionMode) {
62
+ return '@pyric/cli/register/app-bridge';
63
+ }
64
+ return 'pyric/app/register';
65
+ }
66
+
28
67
  for (const [from, to] of MAPPINGS) {
29
- if (specifier === from) return to;
30
- if (specifier.startsWith(`${from}/`)) return to + specifier.slice(from.length);
68
+ const isExactMatch = specifier === from;
69
+ if (isExactMatch) {
70
+ return to;
71
+ }
72
+ const isSubpathMatch = specifier.startsWith(`${from}/`);
73
+ if (isSubpathMatch) {
74
+ const subpath = specifier.slice(from.length);
75
+ return to + subpath;
76
+ }
31
77
  }
32
78
  return null;
33
79
  }
@@ -27,3 +27,113 @@ export function isRtdbRulesDocument(value: unknown): value is RtdbRulesDocument
27
27
  function isRtdbRulesObject(value: unknown): value is Record<string, unknown> {
28
28
  return typeof value === 'object' && value !== null && !Array.isArray(value);
29
29
  }
30
+
31
+ /**
32
+ * Strip JavaScript-style line comments (`//...`) and block comments (`/*...*\/`)
33
+ * from JSON source text without altering string literals. Firebase Realtime
34
+ * Database security rules files (`database.rules.json`) permit comment blocks,
35
+ * requiring pre-processing before evaluation with standard JSON parsers.
36
+ */
37
+ export function stripJsonComments(text: string): string {
38
+ let result = '';
39
+ let inString = false;
40
+ let inSingleLineComment = false;
41
+ let inMultiLineComment = false;
42
+ let i = 0;
43
+
44
+ while (i < text.length) {
45
+ const char = text[i];
46
+ const nextChar = i + 1 < text.length ? text[i + 1] : '';
47
+
48
+ if (inSingleLineComment) {
49
+ const isNewline = char === '\n' || char === '\r';
50
+ if (isNewline) {
51
+ inSingleLineComment = false;
52
+ result += char;
53
+ }
54
+ i++;
55
+ continue;
56
+ }
57
+
58
+ if (inMultiLineComment) {
59
+ const isEndOfBlock = char === '*' && nextChar === '/';
60
+ if (isEndOfBlock) {
61
+ inMultiLineComment = false;
62
+ i += 2;
63
+ } else {
64
+ const isNewline = char === '\n' || char === '\r';
65
+ if (isNewline) {
66
+ result += char; // Preserve line numbering for accurate diagnostics
67
+ }
68
+ i++;
69
+ }
70
+ continue;
71
+ }
72
+
73
+ if (inString) {
74
+ const isEscape = char === '\\';
75
+ if (isEscape) {
76
+ result += char;
77
+ if (nextChar !== '') {
78
+ result += nextChar;
79
+ i++;
80
+ }
81
+ i++;
82
+ continue;
83
+ }
84
+ const isQuote = char === '"';
85
+ if (isQuote) {
86
+ inString = false;
87
+ }
88
+ result += char;
89
+ i++;
90
+ continue;
91
+ }
92
+
93
+ const isQuote = char === '"';
94
+ if (isQuote) {
95
+ inString = true;
96
+ result += char;
97
+ i++;
98
+ continue;
99
+ }
100
+
101
+ const isLineCommentStart = char === '/' && nextChar === '/';
102
+ if (isLineCommentStart) {
103
+ inSingleLineComment = true;
104
+ i += 2;
105
+ continue;
106
+ }
107
+
108
+ const isBlockCommentStart = char === '/' && nextChar === '*';
109
+ if (isBlockCommentStart) {
110
+ inMultiLineComment = true;
111
+ i += 2;
112
+ continue;
113
+ }
114
+
115
+ result += char;
116
+ i++;
117
+ }
118
+
119
+ return result;
120
+ }
121
+
122
+ /**
123
+ * Parse a JSON string that may contain line or block comments into a validated
124
+ * Realtime Database rules document structure.
125
+ */
126
+ export function parseRtdbRulesText(
127
+ text: string,
128
+ onInvalid: (error: Error) => Error,
129
+ ): RtdbRulesJson {
130
+ const clean = stripJsonComments(text);
131
+ let parsed: unknown;
132
+ try {
133
+ parsed = JSON.parse(clean);
134
+ } catch (e) {
135
+ const detail = e instanceof Error ? e.message : String(e);
136
+ throw onInvalid(new Error(`Failed to parse rules JSON: ${detail}`));
137
+ }
138
+ return parseRtdbRulesJson(parsed, () => onInvalid(new Error('Document must contain a top-level "rules" object.')));
139
+ }
@@ -57,6 +57,7 @@ export function defaultSdkEntries(): Record<string, string> {
57
57
  return {
58
58
  ai: pick('ai'),
59
59
  app: pick('app'),
60
+ 'app-ai-passthrough': pick('app-ai-passthrough'),
60
61
  auth: pick('auth'),
61
62
  firestore: pick('firestore'),
62
63
  database: pick('database'),
@@ -309,6 +310,7 @@ export async function bundleSdk(opts: BundleOptions): Promise<BundleResult> {
309
310
  sourcemap: 'linked',
310
311
  minify: opts.minify ?? true,
311
312
  logLevel: 'silent',
313
+ external: ['firebase/*'],
312
314
  // Provenance: any stack frame or "view source" into these bundles must
313
315
  // self-identify as the sandbox shim, not the real Firebase SDK.
314
316
  chunkNames: 'pyric-sandbox-[hash]',
@@ -17,16 +17,36 @@
17
17
  * first while the browser is on the other — split-brain.
18
18
  */
19
19
  import { existsSync, readFileSync } from 'node:fs';
20
- import { join } from 'node:path';
20
+ import { dirname, join, resolve } from 'node:path';
21
21
 
22
22
  /** Ports probed when the pointer is absent — serve's default scan window PLUS
23
- * the vite-plugin default (5174), which the plain 3473+ window would miss (so a
24
- * vite-only project was never found by scan). The standalone `pyric bridge`
25
- * serves `/health` (not `/__pyric/health`) and writes no pointer, so it is
26
- * registered directly via `claude mcp add`, not discovered here. */
27
- export const SCAN_PORTS = [3473, 3474, 3475, 3476, 3477, 5174];
23
+ * the standard Vite dev ports (5173-5177), which the plain 3473+ window would miss
24
+ * (so a vite-only or monorepo split-directory project is reliably found by scan).
25
+ * The standalone `pyric bridge` serves `/health` (not `/__pyric/health`) and
26
+ * writes no pointer, so it is registered directly via `claude mcp add`, not discovered here. */
27
+ export const SCAN_PORTS = [3473, 3474, 3475, 3476, 3477, 5173, 5174, 5175, 5176, 5177];
28
28
  export const POINTER = join('.pyric', 'serve.json');
29
29
 
30
+ function candidatePointerPaths(startDir: string): string[] {
31
+ const paths: string[] = [];
32
+ const seen = new Set<string>();
33
+ const subdirs = ['', 'web', 'frontend', 'client', 'app', 'ui', 'www'];
34
+ let current = resolve(startDir);
35
+ while (true) {
36
+ for (const sub of subdirs) {
37
+ const p = sub ? join(current, sub, POINTER) : join(current, POINTER);
38
+ if (!seen.has(p)) {
39
+ seen.add(p);
40
+ paths.push(p);
41
+ }
42
+ }
43
+ const parent = dirname(current);
44
+ if (parent === current) break;
45
+ current = parent;
46
+ }
47
+ return paths;
48
+ }
49
+
30
50
  export interface HealthLite {
31
51
  mode?: string;
32
52
  instanceId?: string;
@@ -141,46 +161,47 @@ export async function discoverServe(
141
161
  // real localhost ports, which a test environment can't guarantee are free.
142
162
  scanPorts: number[] = SCAN_PORTS,
143
163
  ): Promise<Discovered | null> {
144
- const pointerPath = join(cwd, POINTER);
145
- if (existsSync(pointerPath)) {
146
- try {
147
- const p = JSON.parse(readFileSync(pointerPath, 'utf8')) as {
148
- url?: string;
149
- mcpUrl?: string;
150
- port?: number;
151
- instanceId?: string;
152
- };
153
- const port = p.port ?? portOf(p.mcpUrl) ?? portOf(p.url);
154
- if (port) {
155
- const expectedId = typeof p.instanceId === 'string' && p.instanceId ? p.instanceId : null;
156
- const hit = await healthyBase(port, expectedId);
157
- if (hit) {
158
- return {
159
- mcpUrl: `${hit.base}/__pyric/mcp`,
160
- url: canonicalServeUrl(port, p.url),
161
- base: hit.base,
162
- instanceId: hit.instanceId,
163
- source: `pointer ${POINTER}`,
164
- };
165
- }
166
- // The pointer named a specific identity we could NOT find on its port:
167
- // a different sandbox may be squatting it (cross-family collision) or
168
- // the server stopped. Do NOT scan into a possibly-wrong server — that
169
- // split-brain is exactly what this identity check prevents. Fail legibly.
170
- if (expectedId) {
171
- log(
172
- `pointer ${POINTER} names a server (instanceId ${expectedId.slice(0, 8)}…) ` +
173
- `that isn't answering on port ${port} — another sandbox may be squatting the ` +
174
- `port on the other loopback family, or the server stopped. Not falling back to ` +
175
- `a blind port scan (it could hit the wrong sandbox). Restart your dev server, ` +
176
- `and open the exact URL it prints (http://localhost:<port> by default) — every ` +
177
- `page must share that ONE origin, or the browser splits into separate sandboxes.`,
178
- );
179
- return null;
164
+ for (const pointerPath of candidatePointerPaths(cwd)) {
165
+ if (existsSync(pointerPath)) {
166
+ try {
167
+ const p = JSON.parse(readFileSync(pointerPath, 'utf8')) as {
168
+ url?: string;
169
+ mcpUrl?: string;
170
+ port?: number;
171
+ instanceId?: string;
172
+ };
173
+ const port = p.port ?? portOf(p.mcpUrl) ?? portOf(p.url);
174
+ if (port) {
175
+ const expectedId = typeof p.instanceId === 'string' && p.instanceId ? p.instanceId : null;
176
+ const hit = await healthyBase(port, expectedId);
177
+ if (hit) {
178
+ return {
179
+ mcpUrl: `${hit.base}/__pyric/mcp`,
180
+ url: canonicalServeUrl(port, p.url),
181
+ base: hit.base,
182
+ instanceId: hit.instanceId,
183
+ source: `pointer ${pointerPath}`,
184
+ };
185
+ }
186
+ // The pointer named a specific identity we could NOT find on its port:
187
+ // a different sandbox may be squatting it (cross-family collision) or
188
+ // the server stopped. Do NOT scan into a possibly-wrong server — that
189
+ // split-brain is exactly what this identity check prevents. Fail legibly.
190
+ if (expectedId) {
191
+ log(
192
+ `pointer ${pointerPath} names a server (instanceId ${expectedId.slice(0, 8)}…) ` +
193
+ `that isn't answering on port ${port} — another sandbox may be squatting the ` +
194
+ `port on the other loopback family, or the server stopped. Not falling back to ` +
195
+ `a blind port scan (it could hit the wrong sandbox). Restart your dev server, ` +
196
+ `and open the exact URL it prints (http://localhost:<port> by default) — every ` +
197
+ `page must share that ONE origin, or the browser splits into separate sandboxes.`,
198
+ );
199
+ return null;
200
+ }
180
201
  }
202
+ } catch {
203
+ /* stale/corrupt pointer — fall through to next candidate */
181
204
  }
182
- } catch {
183
- /* stale/corrupt pointer — fall through to scan */
184
205
  }
185
206
  }
186
207
  for (const port of scanPorts) {
@@ -0,0 +1,83 @@
1
+ /** Served `firebase/app`: Pyric client registry with shadow container bridge for production AI pass-through. */
2
+ import { bindAppRegistrySandbox } from 'pyric/app/internal';
3
+ import { sandbox } from './app-backend.js';
4
+ import * as pyricApp from 'pyric/app';
5
+ import * as realApp from 'firebase/app';
6
+
7
+ bindAppRegistrySandbox(sandbox);
8
+
9
+ function decorateApp(
10
+ app: pyricApp.FirebaseApp,
11
+ options?: pyricApp.FirebaseOptions,
12
+ rawSettings?: string | pyricApp.FirebaseAppSettings,
13
+ ): pyricApp.FirebaseApp {
14
+ try {
15
+ let shadow: { container?: unknown };
16
+ try {
17
+ shadow = realApp.getApp(app.name) as { container?: unknown };
18
+ } catch {
19
+ const initOptions = (options ?? app.options) as realApp.FirebaseOptions;
20
+ const initSettings = rawSettings ?? app.name;
21
+ const isStringSettings = typeof initSettings === 'string';
22
+ if (isStringSettings) {
23
+ shadow = realApp.initializeApp(initOptions, initSettings) as { container?: unknown };
24
+ } else {
25
+ const objectSettings = initSettings as realApp.FirebaseAppSettings;
26
+ shadow = realApp.initializeApp(initOptions, objectSettings) as { container?: unknown };
27
+ }
28
+ }
29
+ const hasShadowContainer = shadow.container !== undefined && shadow.container !== null;
30
+ if (hasShadowContainer) {
31
+ Object.defineProperty(app, 'container', { value: shadow.container, configurable: true });
32
+ }
33
+ } catch {
34
+ // Observational/best-effort: do not break Pyric initialization if shadow initialization fails.
35
+ }
36
+ return app;
37
+ }
38
+
39
+ export function initializeApp(
40
+ options?: pyricApp.FirebaseOptions,
41
+ rawSettings?: string | pyricApp.FirebaseAppSettings,
42
+ ): pyricApp.FirebaseApp {
43
+ const app = pyricApp.initializeApp(options, rawSettings);
44
+ return decorateApp(app, options, rawSettings);
45
+ }
46
+
47
+ export function getApp(name?: string): pyricApp.FirebaseApp {
48
+ return decorateApp(pyricApp.getApp(name));
49
+ }
50
+
51
+ export function getApps(): pyricApp.FirebaseApp[] {
52
+ return pyricApp.getApps().map((app) => decorateApp(app));
53
+ }
54
+
55
+ export async function deleteApp(app: pyricApp.FirebaseApp): Promise<void> {
56
+ try {
57
+ const shadow = realApp.getApp(app.name);
58
+ const hasShadow = shadow !== undefined && shadow !== null;
59
+ if (hasShadow) {
60
+ await realApp.deleteApp(shadow);
61
+ }
62
+ } catch {
63
+ // Ignore if shadow app was not initialized or already deleted.
64
+ }
65
+ return pyricApp.deleteApp(app);
66
+ }
67
+
68
+ export {
69
+ FirebaseError,
70
+ SDK_VERSION,
71
+ onLog,
72
+ registerVersion,
73
+ setLogLevel,
74
+ } from 'pyric/app';
75
+ export type {
76
+ FirebaseApp,
77
+ FirebaseAppSettings,
78
+ FirebaseOptions,
79
+ LogCallback,
80
+ LogEntry,
81
+ LogLevel,
82
+ LogOptions,
83
+ } from 'pyric/app';
@@ -224,6 +224,12 @@ function mintProviderUid(): string {
224
224
  function bareCredential(identity: HelperIdentity, providerId: string): UserCredential {
225
225
  const issuedAtTime = new Date().toISOString();
226
226
  const expirationTime = new Date(Date.now() + 3600_000).toISOString();
227
+ const claims: Record<string, unknown> = {
228
+ sub: identity.uid,
229
+ ...identity.customClaims,
230
+ firebase: { sign_in_provider: providerId },
231
+ };
232
+ const token = `sandbox-id-token-${identity.uid}-0:${JSON.stringify(claims)}`;
227
233
  const user: User = {
228
234
  uid: identity.uid,
229
235
  email: identity.email,
@@ -243,14 +249,10 @@ function bareCredential(identity: HelperIdentity, providerId: string): UserCrede
243
249
  providerId,
244
250
  },
245
251
  ],
246
- getIdToken: async () => `pyric-serve-${identity.uid}`,
252
+ getIdToken: async () => token,
247
253
  getIdTokenResult: async () => ({
248
- token: `pyric-serve-${identity.uid}`,
249
- claims: {
250
- sub: identity.uid,
251
- ...identity.customClaims,
252
- firebase: { sign_in_provider: providerId },
253
- },
254
+ token,
255
+ claims,
254
256
  signInProvider: providerId,
255
257
  expirationTime,
256
258
  issuedAtTime,
@@ -13,6 +13,7 @@
13
13
  * in or seeds a user. Email/password + anonymous also go straight to the
14
14
  * worker. The COMPLETE surface is exported on both paths (import-time parity).
15
15
  */
16
+ import './init.js';
16
17
  import * as ipAuth from 'pyric/auth';
17
18
  import { getAuth as pyricGetAuth, setPersistence as pyricSetPersistence } from 'pyric/auth';
18
19
  import * as wcRaw from '../worker/client.js';
@@ -22,9 +22,16 @@ export function toPageOriginWsUrl(
22
22
  loc: { href: string; protocol: string; host: string },
23
23
  ): string {
24
24
  try {
25
- const path = new URL(raw, loc.href).pathname;
25
+ const rawUrl = new URL(raw, loc.href);
26
+ const locUrl = new URL(loc.href);
26
27
  const scheme = loc.protocol === 'https:' ? 'wss:' : 'ws:';
27
- return `${scheme}//${loc.host}${path}`;
28
+
29
+ const hasExplicitLocPort = locUrl.port.length > 0;
30
+ const hasExplicitRawPort = rawUrl.port.length > 0;
31
+ const shouldPreserveRawPort = hasExplicitLocPort && hasExplicitRawPort;
32
+ const hostTarget = shouldPreserveRawPort ? `${locUrl.hostname}:${rawUrl.port}` : locUrl.host;
33
+
34
+ return `${scheme}//${hostTarget}${rawUrl.pathname}`;
28
35
  } catch {
29
36
  return raw;
30
37
  }
@@ -5,6 +5,7 @@
5
5
  * and the Playground. This entry gives served apps the same common modular SDK
6
6
  * surface while the in-page fallback delegates to `pyric/database`.
7
7
  */
8
+ import './init.js';
8
9
  import * as ip from 'pyric/database';
9
10
  import { getDatabase as pyricGetDatabase } from 'pyric/database';
10
11
  import { queryIdentifier } from 'pyric/database/internal';
@@ -13,6 +13,7 @@
13
13
  *
14
14
  * Browser-bundled by `../bundler.ts`; never imported by node-side code.
15
15
  */
16
+ import './init.js';
16
17
  import * as ip from 'pyric/firestore';
17
18
  import { getFirestore as pyricGetFirestore } from 'pyric/firestore';
18
19
  import * as wcRaw from '../worker/client.js';
@@ -53,7 +53,10 @@ const helper = workerAuth
53
53
  const resolver = helper.resolver();
54
54
  installServeAuthResolver(resolver);
55
55
  if (localAuth) authSandbox.setAuthFlowResolver(localAuth, resolver);
56
- mountAuthHelperDialog(helper);
57
- installPyricRuntimeChip({ runtime: getPyricRuntimeStatus(), document });
56
+
57
+ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
58
+ mountAuthHelperDialog(helper);
59
+ installPyricRuntimeChip({ runtime: getPyricRuntimeStatus(), document });
60
+ }
58
61
 
59
62
  export {};
@@ -553,4 +553,29 @@ if (!useWorker && typeof EventSource !== 'undefined') {
553
553
  console.error('[pyric dev] rules hot-reload failed:', err instanceof Error ? err.message : String(err));
554
554
  }
555
555
  });
556
+ events.addEventListener('rtdb-rules-update', (e) => {
557
+ try {
558
+ const { rules, rulesHash } = JSON.parse((e as MessageEvent).data as string) as {
559
+ rules: { rules: Record<string, unknown> };
560
+ rulesHash: string;
561
+ };
562
+ rtdbSandbox.setRules(getDatabase(sandbox), rules);
563
+ diagnostics.databaseRulesDeployed = true;
564
+ let newHash: string | null = null;
565
+ const isHashDefined = rulesHash !== undefined;
566
+ if (isHashDefined) {
567
+ newHash = rulesHash;
568
+ }
569
+ diagnostics.databaseRulesHash = newHash;
570
+ console.info(`[pyric dev] database.rules.json hot-reloaded (hash ${rulesHash})`);
571
+ } catch (err) {
572
+ runtimeStatus.reportError(err, 'runtime');
573
+ const isErrorInstance = err instanceof Error;
574
+ let errorMessage = String(err);
575
+ if (isErrorInstance) {
576
+ errorMessage = (err as Error).message;
577
+ }
578
+ console.error('[pyric dev] database rules hot-reload failed:', errorMessage);
579
+ }
580
+ });
556
581
  }
@@ -6,6 +6,7 @@
6
6
  * still lack a worker protocol fail loudly. In in-page fallback mode, the entry
7
7
  * delegates to `pyric/storage` against the page sandbox.
8
8
  */
9
+ import './init.js';
9
10
  import * as ip from 'pyric/storage';
10
11
  import {
11
12
  getStorage as pyricGetStorage,
@@ -20,6 +21,8 @@ import {
20
21
  listAll as workerListAll,
21
22
  ref as workerRef,
22
23
  uploadBytes as workerUploadBytes,
24
+ uploadString as workerUploadString,
25
+ uploadBytesResumable as workerUploadBytesResumable,
23
26
  deleteObject as workerDeleteObject,
24
27
  } from '../worker/client.js';
25
28
  import { useWorker } from './worker-runtime.js';
@@ -85,8 +88,16 @@ function workerOrInPage<T extends (...args: any[]) => unknown>(name: string, fn:
85
88
  // ruleset; only their active Auth sessions differ. Payloads are capped at
86
89
  // 8 MiB per op.
87
90
  export const uploadBytes = (useWorker ? workerUploadBytes : ip.uploadBytes) as typeof ip.uploadBytes;
91
+
92
+ let selectedUploadBytesResumable = ip.uploadBytesResumable;
93
+ const isWorkerMode = useWorker === true;
94
+ if (isWorkerMode) {
95
+ selectedUploadBytesResumable = workerUploadBytesResumable as unknown as typeof ip.uploadBytesResumable;
96
+ }
97
+ export const uploadBytesResumable = selectedUploadBytesResumable;
98
+
88
99
  export const getBytes = (useWorker ? workerGetBytes : ip.getBytes) as typeof ip.getBytes;
89
100
  export const deleteObject = (useWorker ? workerDeleteObject : ip.deleteObject) as typeof ip.deleteObject;
90
101
 
91
- export const uploadString = workerOrInPage('uploadString', ip.uploadString);
102
+ export const uploadString = (useWorker ? workerUploadString : ip.uploadString) as typeof ip.uploadString;
92
103
  export const updateMetadata = workerOrInPage('updateMetadata', ip.updateMetadata);
@@ -1,7 +1,32 @@
1
1
  import { SANDBOX_BUILD_MARKER } from './sandbox-marker.js';
2
2
 
3
3
  /** The import-map targets. Spec → served URL. */
4
- export function sdkImportMap(): Record<string, string> {
4
+ export function sdkImportMap(options?: { aiMode?: 'sandbox' | 'production' }): Record<string, string> {
5
+ const explicitMode = options?.aiMode;
6
+ let mode: 'sandbox' | 'production' = 'sandbox';
7
+ const hasExplicitMode = explicitMode !== undefined;
8
+ if (hasExplicitMode) {
9
+ mode = explicitMode;
10
+ } else {
11
+ const isEnvProductionMode = process.env.PYRIC_AI_MODE === 'production';
12
+ const isEnvPassthroughFlag = process.env.PYRIC_AI_PASSTHROUGH === '1';
13
+ const isProductionEnv = isEnvProductionMode || isEnvPassthroughFlag;
14
+ if (isProductionEnv) {
15
+ mode = 'production';
16
+ }
17
+ }
18
+ const isProductionMode = mode === 'production';
19
+ if (isProductionMode) {
20
+ return {
21
+ 'firebase/app': '/__pyric/sdk/app-ai-passthrough.js',
22
+ 'firebase/auth': '/__pyric/sdk/auth.js',
23
+ 'firebase/database': '/__pyric/sdk/database.js',
24
+ 'firebase/firestore': '/__pyric/sdk/firestore.js',
25
+ 'firebase/messaging': '/__pyric/sdk/messaging.js',
26
+ 'firebase/messaging/sw': '/__pyric/sdk/messaging-sw.js',
27
+ 'firebase/storage': '/__pyric/sdk/storage.js',
28
+ };
29
+ }
5
30
  return {
6
31
  'firebase/ai': '/__pyric/sdk/ai.js',
7
32
  'firebase/app': '/__pyric/sdk/app.js',
@@ -16,7 +16,7 @@ import { isAbsolute, join } from 'node:path';
16
16
  import { lintFirestoreRules, resolveModulesBrowser } from 'pyric/rules/internal';
17
17
  import { parseStorageRules } from 'pyric/storage';
18
18
  import type { FirebaseJson } from '../cli/firebase-json.js';
19
- import { parseRtdbRulesJson } from '../rtdb/rules-json.js';
19
+ import { parseRtdbRulesJson, stripJsonComments } from '../rtdb/rules-json.js';
20
20
 
21
21
  export interface LoadedRules {
22
22
  /** Plain-v2 source ready for the sandbox, or null when the project has no
@@ -186,7 +186,7 @@ export async function loadProjectDatabaseRules(
186
186
 
187
187
  let parsed: unknown;
188
188
  try {
189
- parsed = JSON.parse(raw);
189
+ parsed = JSON.parse(stripJsonComments(raw));
190
190
  } catch (e) {
191
191
  throw new Error(`pyric dev: ${path} failed to parse as RTDB rules JSON: ${e instanceof Error ? e.message : String(e)}`);
192
192
  }
@@ -17,14 +17,27 @@ interface RuntimeChipDocument {
17
17
  querySelector(selector: string): { getAttribute(name: string): string | null } | null;
18
18
  }
19
19
 
20
- /** Read only plugin-authored values; absent/unknown metadata keeps the UI off. */
20
+ function hasBundlerRuntimeChipConfig(): boolean {
21
+ return typeof process !== 'undefined' && typeof process.env !== 'undefined' && typeof process.env.PYRIC_RUNTIME_CHIP === 'string';
22
+ }
23
+
24
+ /** Read plugin-authored values from DOM metadata or bundler environment variables, defaulting to collapsed UI when omitted. */
21
25
  export function readPyricRuntimeChipConfig(
22
26
  documentLike: RuntimeChipDocument,
23
27
  ): PyricRuntimeChipConfig | null {
24
28
  const meta = documentLike.querySelector(`meta[name="${PYRIC_RUNTIME_CHIP_META}"]`);
25
- const value = meta?.getAttribute('content');
26
- const studioEnabled = meta?.getAttribute('data-studio') !== 'off';
27
- if (value === 'collapsed') return { initiallyOpen: false, studioEnabled };
28
- if (value === 'expanded') return { initiallyOpen: true, studioEnabled };
29
- return null;
29
+ const hasMetaTag = meta !== null;
30
+ let value = hasMetaTag ? meta.getAttribute('content') : null;
31
+
32
+ const shouldFallbackToEnv = !hasMetaTag && hasBundlerRuntimeChipConfig();
33
+ if (shouldFallbackToEnv) {
34
+ value = process.env.PYRIC_RUNTIME_CHIP as string;
35
+ }
36
+ if (value === 'off') {
37
+ return null;
38
+ }
39
+
40
+ const studioEnabled = !hasMetaTag || meta.getAttribute('data-studio') !== 'off';
41
+ const initiallyOpen = value === 'expanded';
42
+ return { initiallyOpen, studioEnabled };
30
43
  }