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

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 (419) hide show
  1. package/README.md +42 -12
  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/bridge/server/bridge.d.ts.map +1 -1
  7. package/dist/bridge/server/bridge.js +4 -2
  8. package/dist/bridge/server/bridge.js.map +1 -1
  9. package/dist/bridge/server/peer.d.ts.map +1 -1
  10. package/dist/bridge/server/peer.js +1 -0
  11. package/dist/bridge/server/peer.js.map +1 -1
  12. package/dist/cli/database-rules.d.ts.map +1 -1
  13. package/dist/cli/database-rules.js +6 -4
  14. package/dist/cli/database-rules.js.map +1 -1
  15. package/dist/cli/dev-runner.d.ts +9 -0
  16. package/dist/cli/dev-runner.d.ts.map +1 -1
  17. package/dist/cli/dev-runner.js +18 -0
  18. package/dist/cli/dev-runner.js.map +1 -1
  19. package/dist/cli/serve.d.ts.map +1 -1
  20. package/dist/cli/serve.js +62 -6
  21. package/dist/cli/serve.js.map +1 -1
  22. package/dist/cli/verify.js +2 -2
  23. package/dist/cli/verify.js.map +1 -1
  24. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  25. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  26. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  27. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  28. package/dist/conformance/.generated/can-i-use.js +1 -1
  29. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  30. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  31. package/dist/conformance/.generated/conformance-docs.js +1 -1
  32. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  33. package/dist/functions-rtdb/child.d.ts +1 -0
  34. package/dist/functions-rtdb/child.d.ts.map +1 -1
  35. package/dist/functions-rtdb/child.js +11 -1
  36. package/dist/functions-rtdb/child.js.map +1 -1
  37. package/dist/functions-rtdb/development-runtime.d.ts +1 -0
  38. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
  39. package/dist/functions-rtdb/development-runtime.js +1 -0
  40. package/dist/functions-rtdb/development-runtime.js.map +1 -1
  41. package/dist/next/client-aliases.d.ts +11 -0
  42. package/dist/next/client-aliases.d.ts.map +1 -0
  43. package/dist/next/client-aliases.js +38 -0
  44. package/dist/next/client-aliases.js.map +1 -0
  45. package/dist/next/dev-rewrites.d.ts +9 -0
  46. package/dist/next/dev-rewrites.d.ts.map +1 -0
  47. package/dist/next/dev-rewrites.js +53 -0
  48. package/dist/next/dev-rewrites.js.map +1 -0
  49. package/dist/next/guard.d.ts +15 -0
  50. package/dist/next/guard.d.ts.map +1 -0
  51. package/dist/next/guard.js +52 -0
  52. package/dist/next/guard.js.map +1 -0
  53. package/dist/next/index.d.ts +12 -0
  54. package/dist/next/index.d.ts.map +1 -0
  55. package/dist/next/index.js +11 -0
  56. package/dist/next/index.js.map +1 -0
  57. package/dist/next/runtime-env.d.ts +7 -0
  58. package/dist/next/runtime-env.d.ts.map +1 -0
  59. package/dist/next/runtime-env.js +13 -0
  60. package/dist/next/runtime-env.js.map +1 -0
  61. package/dist/next/server-external-packages.d.ts +10 -0
  62. package/dist/next/server-external-packages.d.ts.map +1 -0
  63. package/dist/next/server-external-packages.js +34 -0
  64. package/dist/next/server-external-packages.js.map +1 -0
  65. package/dist/next/target-url.d.ts +11 -0
  66. package/dist/next/target-url.d.ts.map +1 -0
  67. package/dist/next/target-url.js +36 -0
  68. package/dist/next/target-url.js.map +1 -0
  69. package/dist/next/turbopack-config.d.ts +9 -0
  70. package/dist/next/turbopack-config.d.ts.map +1 -0
  71. package/dist/next/turbopack-config.js +39 -0
  72. package/dist/next/turbopack-config.js.map +1 -0
  73. package/dist/next/types.d.ts +40 -0
  74. package/dist/next/types.d.ts.map +1 -0
  75. package/dist/next/types.js +5 -0
  76. package/dist/next/types.js.map +1 -0
  77. package/dist/next/webpack-config.d.ts +11 -0
  78. package/dist/next/webpack-config.d.ts.map +1 -0
  79. package/dist/next/webpack-config.js +51 -0
  80. package/dist/next/webpack-config.js.map +1 -0
  81. package/dist/next/with-pyric.d.ts +22 -0
  82. package/dist/next/with-pyric.d.ts.map +1 -0
  83. package/dist/next/with-pyric.js +49 -0
  84. package/dist/next/with-pyric.js.map +1 -0
  85. package/dist/register/app-bridge.d.ts +9 -0
  86. package/dist/register/app-bridge.d.ts.map +1 -0
  87. package/dist/register/app-bridge.js +56 -0
  88. package/dist/register/app-bridge.js.map +1 -0
  89. package/dist/register/hooks.d.ts.map +1 -1
  90. package/dist/register/hooks.js +6 -1
  91. package/dist/register/hooks.js.map +1 -1
  92. package/dist/register/index.js +1 -1
  93. package/dist/register/index.js.map +1 -1
  94. package/dist/register/mapping.d.ts +3 -1
  95. package/dist/register/mapping.d.ts.map +1 -1
  96. package/dist/register/mapping.js +41 -5
  97. package/dist/register/mapping.js.map +1 -1
  98. package/dist/remote/index.d.ts.map +1 -1
  99. package/dist/remote/index.js +5 -3
  100. package/dist/remote/index.js.map +1 -1
  101. package/dist/rtdb/rules-json.d.ts +12 -0
  102. package/dist/rtdb/rules-json.d.ts.map +1 -1
  103. package/dist/rtdb/rules-json.js +98 -0
  104. package/dist/rtdb/rules-json.js.map +1 -1
  105. package/dist/serve/bundler.d.ts.map +1 -1
  106. package/dist/serve/bundler.js +2 -0
  107. package/dist/serve/bundler.js.map +1 -1
  108. package/dist/serve/discovery.d.ts +4 -4
  109. package/dist/serve/discovery.d.ts.map +1 -1
  110. package/dist/serve/discovery.js +59 -38
  111. package/dist/serve/discovery.js.map +1 -1
  112. package/dist/serve/entries/app-ai-passthrough.d.ts +8 -0
  113. package/dist/serve/entries/app-ai-passthrough.d.ts.map +1 -0
  114. package/dist/serve/entries/app-ai-passthrough.js +59 -0
  115. package/dist/serve/entries/app-ai-passthrough.js.map +1 -0
  116. package/dist/serve/entries/auth-helper-core.js +9 -7
  117. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  118. package/dist/serve/entries/auth.d.ts +1 -0
  119. package/dist/serve/entries/auth.d.ts.map +1 -1
  120. package/dist/serve/entries/auth.js +1 -0
  121. package/dist/serve/entries/auth.js.map +1 -1
  122. package/dist/serve/entries/bridge-url.d.ts.map +1 -1
  123. package/dist/serve/entries/bridge-url.js +7 -2
  124. package/dist/serve/entries/bridge-url.js.map +1 -1
  125. package/dist/serve/entries/database.d.ts +1 -0
  126. package/dist/serve/entries/database.d.ts.map +1 -1
  127. package/dist/serve/entries/database.js +1 -0
  128. package/dist/serve/entries/database.js.map +1 -1
  129. package/dist/serve/entries/firestore.d.ts +1 -0
  130. package/dist/serve/entries/firestore.d.ts.map +1 -1
  131. package/dist/serve/entries/firestore.js +1 -0
  132. package/dist/serve/entries/firestore.js.map +1 -1
  133. package/dist/serve/entries/init.d.ts.map +1 -1
  134. package/dist/serve/entries/init.js +4 -2
  135. package/dist/serve/entries/init.js.map +1 -1
  136. package/dist/serve/entries/runtime.js +23 -0
  137. package/dist/serve/entries/runtime.js.map +1 -1
  138. package/dist/serve/entries/storage.d.ts +2 -0
  139. package/dist/serve/entries/storage.d.ts.map +1 -1
  140. package/dist/serve/entries/storage.js +9 -2
  141. package/dist/serve/entries/storage.js.map +1 -1
  142. package/dist/serve/html-injection.d.ts +3 -1
  143. package/dist/serve/html-injection.d.ts.map +1 -1
  144. package/dist/serve/html-injection.js +27 -1
  145. package/dist/serve/html-injection.js.map +1 -1
  146. package/dist/serve/rules.js +2 -2
  147. package/dist/serve/rules.js.map +1 -1
  148. package/dist/serve/runtime/chip-config.d.ts +1 -1
  149. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  150. package/dist/serve/runtime/chip-config.js +16 -8
  151. package/dist/serve/runtime/chip-config.js.map +1 -1
  152. package/dist/serve/runtime/chip.d.ts.map +1 -1
  153. package/dist/serve/runtime/chip.js +24 -3
  154. package/dist/serve/runtime/chip.js.map +1 -1
  155. package/dist/serve/runtime/status.d.ts +1 -0
  156. package/dist/serve/runtime/status.d.ts.map +1 -1
  157. package/dist/serve/runtime/status.js +71 -13
  158. package/dist/serve/runtime/status.js.map +1 -1
  159. package/dist/serve/sandbox-session.d.ts +1 -0
  160. package/dist/serve/sandbox-session.d.ts.map +1 -1
  161. package/dist/serve/sandbox-session.js +30 -2
  162. package/dist/serve/sandbox-session.js.map +1 -1
  163. package/dist/serve/site-ui/_astro/_slug_.C6QfVOxJ.css +1 -0
  164. package/dist/serve/site-ui/_astro/_studio_.B6b_G1ev.css +1 -0
  165. package/dist/serve/site-ui/_astro/app.B7pBzz5N.js +11 -0
  166. package/dist/serve/site-ui/_astro/app.boex5SnQ.js +1 -0
  167. package/dist/serve/site-ui/_astro/{chess-showcase.CnoxIle5.js → chess-showcase.DDqE-QGe.js} +1 -1
  168. package/dist/serve/site-ui/_astro/{example-runtime.R1d96L6-.js → example-runtime.B0byNQOl.js} +1 -1
  169. package/dist/serve/site-ui/_astro/index.uwPvjH_1.js +1 -0
  170. package/dist/serve/site-ui/_astro/reads.Dh3z0fJy.js +1 -0
  171. package/dist/serve/site-ui/_astro/sandbox-controls.C2IqtoSw.js +1252 -0
  172. package/dist/serve/site-ui/_astro/{seed.EyI3VYEu.js → seed.CCmj00su.js} +1 -1
  173. package/dist/serve/site-ui/auth/index.html +2 -2
  174. package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
  175. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +48 -13
  176. package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +74 -11
  177. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
  178. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
  179. package/dist/serve/site-ui/docs/ai-compat/index.html +85 -85
  180. package/dist/serve/site-ui/docs/ai-compat.md +84 -84
  181. package/dist/serve/site-ui/docs/api-reference/index.html +3 -1
  182. package/dist/serve/site-ui/docs/api-reference.md +2 -0
  183. package/dist/serve/site-ui/docs/app-compat/index.html +28 -28
  184. package/dist/serve/site-ui/docs/app-compat.md +27 -27
  185. package/dist/serve/site-ui/docs/auth-compat/index.html +122 -122
  186. package/dist/serve/site-ui/docs/auth-compat.md +121 -121
  187. package/dist/serve/site-ui/docs/build/ai-logic/index.html +19 -2
  188. package/dist/serve/site-ui/docs/build/ai-logic.md +28 -0
  189. package/dist/serve/site-ui/docs/build/authentication/index.html +1 -1
  190. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +1 -1
  191. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
  192. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +1 -1
  193. package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
  194. package/dist/serve/site-ui/docs/conformance-scores/index.html +25 -10
  195. package/dist/serve/site-ui/docs/conformance-scores.md +23 -8
  196. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -6
  197. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +5 -5
  198. package/dist/serve/site-ui/docs/database-compat/index.html +200 -448
  199. package/dist/serve/site-ui/docs/database-compat.md +198 -461
  200. package/dist/serve/site-ui/docs/examples/chess/index.html +2 -2
  201. package/dist/serve/site-ui/docs/examples/index.html +1 -1
  202. package/dist/serve/site-ui/docs/firestore-compat/index.html +186 -195
  203. package/dist/serve/site-ui/docs/firestore-compat.md +184 -195
  204. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +15 -15
  205. package/dist/serve/site-ui/docs/functions-rtdb-compat.md +14 -14
  206. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
  207. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +57 -0
  208. package/dist/serve/site-ui/docs/get-started/nextjs.md +86 -0
  209. package/dist/serve/site-ui/docs/get-started/start-building/index.html +38 -9
  210. package/dist/serve/site-ui/docs/get-started/start-building.md +62 -7
  211. package/dist/serve/site-ui/docs/get-started/vite/index.html +26 -0
  212. package/dist/serve/site-ui/docs/get-started/vite.md +45 -0
  213. package/dist/serve/site-ui/docs/index.json +711 -111
  214. package/dist/serve/site-ui/docs/messaging-compat/index.html +56 -56
  215. package/dist/serve/site-ui/docs/messaging-compat.md +55 -55
  216. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +1 -1
  217. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
  218. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
  219. package/dist/serve/site-ui/docs/overview/index.html +1 -1
  220. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +39 -13
  221. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api.md +28 -2
  222. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
  223. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +38 -6
  224. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api.md +43 -0
  225. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +9 -1
  226. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +8 -0
  227. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
  228. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +27 -4
  229. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api.md +23 -0
  230. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
  231. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
  232. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
  233. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +1 -1
  234. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
  235. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
  236. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
  237. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
  238. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
  239. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
  240. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
  241. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
  242. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
  243. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +123 -0
  244. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +99 -0
  245. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +127 -0
  246. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api.md +174 -0
  247. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
  248. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
  249. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +570 -326
  250. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +198 -6
  251. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +1 -1
  252. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +1 -1
  253. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +1 -1
  254. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +2971 -627
  255. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +2873 -517
  256. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
  257. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
  258. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +43 -3
  259. package/dist/serve/site-ui/docs/pyric-rules-reference-api.md +8 -0
  260. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +26 -2
  261. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +24 -0
  262. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
  263. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +77 -9
  264. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +28 -13
  265. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +240 -63
  266. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +164 -5
  267. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
  268. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
  269. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
  270. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
  271. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
  272. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
  273. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
  274. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
  275. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
  276. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
  277. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -10
  278. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api.md +0 -9
  279. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
  280. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +2 -1
  281. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +1 -0
  282. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
  283. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
  284. package/dist/serve/site-ui/docs/rules-compat/index.html +87 -79
  285. package/dist/serve/site-ui/docs/rules-compat.md +86 -78
  286. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
  287. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
  288. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
  289. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
  290. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
  291. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
  292. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
  293. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
  294. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +1 -1
  295. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
  296. package/dist/serve/site-ui/docs/storage-compat/index.html +119 -125
  297. package/dist/serve/site-ui/docs/storage-compat.md +118 -124
  298. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
  299. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
  300. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +1 -1
  301. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
  302. package/dist/serve/site-ui/docs/tutorial/index.html +2 -1
  303. package/dist/serve/site-ui/docs/tutorial.md +2 -0
  304. package/dist/serve/site-ui/examples/chess/index.html +1 -1
  305. package/dist/serve/site-ui/examples/firestore-first-write/index.html +1 -1
  306. package/dist/serve/site-ui/firestore/index.html +2 -2
  307. package/dist/serve/site-ui/index.html +2 -2
  308. package/dist/serve/site-ui/llms.txt +8 -4
  309. package/dist/serve/site-ui/rtdb/index.html +2 -2
  310. package/dist/serve/site-ui/settings/index.html +2 -2
  311. package/dist/serve/site-ui/storage/index.html +2 -2
  312. package/dist/serve/site-ui/traffic/index.html +2 -2
  313. package/dist/serve/vite-ai-config.d.ts +4 -1
  314. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  315. package/dist/serve/vite-ai-config.js +83 -19
  316. package/dist/serve/vite-ai-config.js.map +1 -1
  317. package/dist/serve/vite-functions-development.d.ts.map +1 -1
  318. package/dist/serve/vite-functions-development.js +1 -0
  319. package/dist/serve/vite-functions-development.js.map +1 -1
  320. package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -1
  321. package/dist/serve/vite-generation-rules-watch.js +61 -14
  322. package/dist/serve/vite-generation-rules-watch.js.map +1 -1
  323. package/dist/serve/vite-module-swap.d.ts +4 -1
  324. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  325. package/dist/serve/vite-module-swap.js +106 -21
  326. package/dist/serve/vite-module-swap.js.map +1 -1
  327. package/dist/serve/vite-plugin.d.ts.map +1 -1
  328. package/dist/serve/vite-plugin.js +45 -5
  329. package/dist/serve/vite-plugin.js.map +1 -1
  330. package/dist/serve/vite-sandbox-generation.js +1 -1
  331. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  332. package/dist/serve/worker/client/resumable.d.ts +30 -0
  333. package/dist/serve/worker/client/resumable.d.ts.map +1 -0
  334. package/dist/serve/worker/client/resumable.js +416 -0
  335. package/dist/serve/worker/client/resumable.js.map +1 -0
  336. package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -1
  337. package/dist/serve/worker/client/rtdb-references.js +4 -1
  338. package/dist/serve/worker/client/rtdb-references.js.map +1 -1
  339. package/dist/serve/worker/client/storage.d.ts +16 -2
  340. package/dist/serve/worker/client/storage.d.ts.map +1 -1
  341. package/dist/serve/worker/client/storage.js +57 -6
  342. package/dist/serve/worker/client/storage.js.map +1 -1
  343. package/dist/serve/worker/host/rules.d.ts.map +1 -1
  344. package/dist/serve/worker/host/rules.js +2 -1
  345. package/dist/serve/worker/host/rules.js.map +1 -1
  346. package/dist/serve/worker/index.d.ts +1 -1
  347. package/dist/serve/worker/index.d.ts.map +1 -1
  348. package/dist/serve/worker/index.js +1 -1
  349. package/dist/serve/worker/index.js.map +1 -1
  350. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  351. package/dist/serve/worker/serve-init.js +31 -0
  352. package/dist/serve/worker/serve-init.js.map +1 -1
  353. package/package.json +15 -4
  354. package/src/assurance/.generated/conformance-verdicts.ts +80 -72
  355. package/src/bridge/server/bridge.ts +5 -2
  356. package/src/bridge/server/peer.ts +2 -1
  357. package/src/cli/cli.test.ts +14 -0
  358. package/src/cli/database-rules.ts +6 -4
  359. package/src/cli/dev-runner.ts +21 -0
  360. package/src/cli/serve.ts +63 -5
  361. package/src/cli/verify.ts +2 -2
  362. package/src/conformance/.generated/can-i-use-browser.ts +1 -1
  363. package/src/conformance/.generated/can-i-use.ts +1 -1
  364. package/src/conformance/.generated/conformance-docs.ts +1 -1
  365. package/src/functions-rtdb/child.ts +12 -1
  366. package/src/functions-rtdb/development-runtime.ts +2 -0
  367. package/src/next/client-aliases.ts +39 -0
  368. package/src/next/dev-rewrites.ts +77 -0
  369. package/src/next/guard.ts +61 -0
  370. package/src/next/index.ts +16 -0
  371. package/src/next/runtime-env.ts +18 -0
  372. package/src/next/server-external-packages.ts +43 -0
  373. package/src/next/target-url.ts +46 -0
  374. package/src/next/turbopack-config.ts +54 -0
  375. package/src/next/types.ts +47 -0
  376. package/src/next/webpack-config.ts +71 -0
  377. package/src/next/with-pyric.ts +58 -0
  378. package/src/register/app-bridge.ts +79 -0
  379. package/src/register/hooks.ts +6 -1
  380. package/src/register/index.ts +1 -1
  381. package/src/register/mapping.ts +50 -4
  382. package/src/remote/index.ts +7 -5
  383. package/src/rtdb/rules-json.ts +110 -0
  384. package/src/serve/bundler.ts +2 -0
  385. package/src/serve/discovery.ts +65 -44
  386. package/src/serve/entries/app-ai-passthrough.ts +83 -0
  387. package/src/serve/entries/auth-helper-core.ts +9 -7
  388. package/src/serve/entries/auth.ts +1 -0
  389. package/src/serve/entries/bridge-url.ts +9 -2
  390. package/src/serve/entries/database.ts +1 -0
  391. package/src/serve/entries/firestore.ts +1 -0
  392. package/src/serve/entries/init.ts +5 -2
  393. package/src/serve/entries/runtime.ts +25 -0
  394. package/src/serve/entries/storage.ts +12 -1
  395. package/src/serve/html-injection.ts +26 -1
  396. package/src/serve/rules.ts +2 -2
  397. package/src/serve/runtime/chip-config.ts +19 -6
  398. package/src/serve/runtime/chip.ts +24 -3
  399. package/src/serve/runtime/status.ts +76 -13
  400. package/src/serve/sandbox-session.ts +31 -2
  401. package/src/serve/vite-ai-config.ts +86 -19
  402. package/src/serve/vite-functions-development.ts +1 -0
  403. package/src/serve/vite-generation-rules-watch.ts +67 -15
  404. package/src/serve/vite-module-swap.ts +121 -21
  405. package/src/serve/vite-plugin.ts +44 -6
  406. package/src/serve/vite-sandbox-generation.ts +1 -1
  407. package/src/serve/worker/client/resumable.ts +506 -0
  408. package/src/serve/worker/client/rtdb-references.ts +4 -1
  409. package/src/serve/worker/client/storage.ts +77 -7
  410. package/src/serve/worker/host/rules.ts +2 -1
  411. package/src/serve/worker/index.ts +4 -0
  412. package/src/serve/worker/serve-init.ts +30 -0
  413. package/dist/serve/site-ui/_astro/_slug_.BoKXYrnu.css +0 -1
  414. package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +0 -1
  415. package/dist/serve/site-ui/_astro/app.4HeLP_FA.js +0 -109
  416. package/dist/serve/site-ui/_astro/app.BgSnCR5G.js +0 -1
  417. package/dist/serve/site-ui/_astro/index.BJiOemMX.js +0 -1
  418. package/dist/serve/site-ui/_astro/reads.BrKNdKAa.js +0 -1
  419. package/dist/serve/site-ui/_astro/sandbox-controls.BTb3EbQp.js +0 -1153
@@ -92,7 +92,7 @@ function activate(): void {
92
92
  if (typeof moduleApi.registerHooks === 'function') {
93
93
  moduleApi.registerHooks({
94
94
  resolve(specifier, context, nextResolve) {
95
- const mapped = mapFirebaseSpecifier(specifier);
95
+ const mapped = mapFirebaseSpecifier(specifier, context.parentURL);
96
96
  if (mapped === null) return nextResolve(specifier, context);
97
97
  try {
98
98
  return nextResolve(mapped, { ...context, parentURL: import.meta.url });
@@ -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
  }
@@ -60,13 +60,15 @@ function remoteError(
60
60
  code: string,
61
61
  message: string,
62
62
  denialContext?: unknown,
63
- ): Error & { code: string; denialContext?: unknown } {
64
- const err = new Error(message) as Error & { code: string; denialContext?: unknown };
63
+ envelope?: unknown,
64
+ ): Error & { code: string; denialContext?: unknown; envelope?: unknown } {
65
+ const err = new Error(message) as Error & { code: string; denialContext?: unknown; envelope?: unknown };
65
66
  err.code = code;
66
67
  // Structured denial context (spike gap 6): a relayed permission-denied
67
68
  // carries the same "why did this deny" frame a local SandboxError has —
68
69
  // plain JSON off the wire, re-attached here.
69
70
  if (denialContext !== undefined) err.denialContext = denialContext;
71
+ if (envelope !== undefined) err.envelope = envelope;
70
72
  return err;
71
73
  }
72
74
 
@@ -406,7 +408,7 @@ export function createRemoteSandboxCore(
406
408
  ' — the running sandbox may predate this feature; restart pyric dev ' +
407
409
  'and close other open pages of this origin, then reload.';
408
410
  }
409
- call.reject(remoteError(code, message, msg.error?.denialContext));
411
+ call.reject(remoteError(code, message, msg.error?.denialContext, (msg.error as any)?.envelope));
410
412
  }
411
413
  return;
412
414
  }
@@ -430,8 +432,8 @@ export function createRemoteSandboxCore(
430
432
  send({ type: 'worker-unsub', subId: msg.subId });
431
433
  } catch {}
432
434
  }
433
- const payload = value.__error as { code: string; message: string; denialContext?: unknown };
434
- const err = remoteError(payload.code, payload.message, payload.denialContext);
435
+ const payload = value.__error as { code: string; message: string; denialContext?: unknown; envelope?: unknown };
436
+ const err = remoteError(payload.code, payload.message, payload.denialContext, payload.envelope);
435
437
  if (sub.onError) sub.onError(err);
436
438
  else console.error('pyric remote sandbox: uncaught error in subscription:', err);
437
439
  return;
@@ -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
  }