@pyric/cli 0.1.0-alpha.15 → 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 (384) 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/bridge/client/dispatch.js +1 -1
  7. package/dist/bridge/client/dispatch.js.map +1 -1
  8. package/dist/cli/database-rules.d.ts.map +1 -1
  9. package/dist/cli/database-rules.js +6 -4
  10. package/dist/cli/database-rules.js.map +1 -1
  11. package/dist/cli/dev-runner.d.ts +9 -0
  12. package/dist/cli/dev-runner.d.ts.map +1 -1
  13. package/dist/cli/dev-runner.js +18 -0
  14. package/dist/cli/dev-runner.js.map +1 -1
  15. package/dist/cli/serve.d.ts.map +1 -1
  16. package/dist/cli/serve.js +61 -6
  17. package/dist/cli/serve.js.map +1 -1
  18. package/dist/cli/verify.js +2 -2
  19. package/dist/cli/verify.js.map +1 -1
  20. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  21. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  22. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  23. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  24. package/dist/conformance/.generated/can-i-use.js +1 -1
  25. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  26. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  27. package/dist/conformance/.generated/conformance-docs.js +1 -1
  28. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  29. package/dist/next/client-aliases.d.ts +11 -0
  30. package/dist/next/client-aliases.d.ts.map +1 -0
  31. package/dist/next/client-aliases.js +38 -0
  32. package/dist/next/client-aliases.js.map +1 -0
  33. package/dist/next/dev-rewrites.d.ts +9 -0
  34. package/dist/next/dev-rewrites.d.ts.map +1 -0
  35. package/dist/next/dev-rewrites.js +53 -0
  36. package/dist/next/dev-rewrites.js.map +1 -0
  37. package/dist/next/guard.d.ts +15 -0
  38. package/dist/next/guard.d.ts.map +1 -0
  39. package/dist/next/guard.js +52 -0
  40. package/dist/next/guard.js.map +1 -0
  41. package/dist/next/index.d.ts +12 -0
  42. package/dist/next/index.d.ts.map +1 -0
  43. package/dist/next/index.js +11 -0
  44. package/dist/next/index.js.map +1 -0
  45. package/dist/next/runtime-env.d.ts +7 -0
  46. package/dist/next/runtime-env.d.ts.map +1 -0
  47. package/dist/next/runtime-env.js +13 -0
  48. package/dist/next/runtime-env.js.map +1 -0
  49. package/dist/next/server-external-packages.d.ts +10 -0
  50. package/dist/next/server-external-packages.d.ts.map +1 -0
  51. package/dist/next/server-external-packages.js +34 -0
  52. package/dist/next/server-external-packages.js.map +1 -0
  53. package/dist/next/target-url.d.ts +11 -0
  54. package/dist/next/target-url.d.ts.map +1 -0
  55. package/dist/next/target-url.js +36 -0
  56. package/dist/next/target-url.js.map +1 -0
  57. package/dist/next/turbopack-config.d.ts +9 -0
  58. package/dist/next/turbopack-config.d.ts.map +1 -0
  59. package/dist/next/turbopack-config.js +39 -0
  60. package/dist/next/turbopack-config.js.map +1 -0
  61. package/dist/next/types.d.ts +40 -0
  62. package/dist/next/types.d.ts.map +1 -0
  63. package/dist/next/types.js +5 -0
  64. package/dist/next/types.js.map +1 -0
  65. package/dist/next/webpack-config.d.ts +11 -0
  66. package/dist/next/webpack-config.d.ts.map +1 -0
  67. package/dist/next/webpack-config.js +51 -0
  68. package/dist/next/webpack-config.js.map +1 -0
  69. package/dist/next/with-pyric.d.ts +22 -0
  70. package/dist/next/with-pyric.d.ts.map +1 -0
  71. package/dist/next/with-pyric.js +49 -0
  72. package/dist/next/with-pyric.js.map +1 -0
  73. package/dist/register/app-bridge.d.ts +9 -0
  74. package/dist/register/app-bridge.d.ts.map +1 -0
  75. package/dist/register/app-bridge.js +56 -0
  76. package/dist/register/app-bridge.js.map +1 -0
  77. package/dist/register/hooks.d.ts.map +1 -1
  78. package/dist/register/hooks.js +6 -1
  79. package/dist/register/hooks.js.map +1 -1
  80. package/dist/register/index.js +1 -1
  81. package/dist/register/index.js.map +1 -1
  82. package/dist/register/mapping.d.ts +3 -1
  83. package/dist/register/mapping.d.ts.map +1 -1
  84. package/dist/register/mapping.js +41 -5
  85. package/dist/register/mapping.js.map +1 -1
  86. package/dist/rtdb/rules-json.d.ts +12 -0
  87. package/dist/rtdb/rules-json.d.ts.map +1 -1
  88. package/dist/rtdb/rules-json.js +98 -0
  89. package/dist/rtdb/rules-json.js.map +1 -1
  90. package/dist/serve/bundler.d.ts.map +1 -1
  91. package/dist/serve/bundler.js +2 -0
  92. package/dist/serve/bundler.js.map +1 -1
  93. package/dist/serve/discovery.d.ts +4 -4
  94. package/dist/serve/discovery.d.ts.map +1 -1
  95. package/dist/serve/discovery.js +59 -38
  96. package/dist/serve/discovery.js.map +1 -1
  97. package/dist/serve/entries/app-ai-passthrough.d.ts +8 -0
  98. package/dist/serve/entries/app-ai-passthrough.d.ts.map +1 -0
  99. package/dist/serve/entries/app-ai-passthrough.js +59 -0
  100. package/dist/serve/entries/app-ai-passthrough.js.map +1 -0
  101. package/dist/serve/entries/auth-helper-core.d.ts +9 -0
  102. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  103. package/dist/serve/entries/auth-helper-core.js +37 -8
  104. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  105. package/dist/serve/entries/auth.d.ts +1 -0
  106. package/dist/serve/entries/auth.d.ts.map +1 -1
  107. package/dist/serve/entries/auth.js +7 -4
  108. package/dist/serve/entries/auth.js.map +1 -1
  109. package/dist/serve/entries/bridge-url.d.ts.map +1 -1
  110. package/dist/serve/entries/bridge-url.js +7 -2
  111. package/dist/serve/entries/bridge-url.js.map +1 -1
  112. package/dist/serve/entries/database.d.ts +1 -0
  113. package/dist/serve/entries/database.d.ts.map +1 -1
  114. package/dist/serve/entries/database.js +1 -0
  115. package/dist/serve/entries/database.js.map +1 -1
  116. package/dist/serve/entries/firestore.d.ts +1 -0
  117. package/dist/serve/entries/firestore.d.ts.map +1 -1
  118. package/dist/serve/entries/firestore.js +1 -0
  119. package/dist/serve/entries/firestore.js.map +1 -1
  120. package/dist/serve/entries/init.d.ts.map +1 -1
  121. package/dist/serve/entries/init.js +4 -2
  122. package/dist/serve/entries/init.js.map +1 -1
  123. package/dist/serve/entries/runtime.js +23 -0
  124. package/dist/serve/entries/runtime.js.map +1 -1
  125. package/dist/serve/entries/storage.d.ts +2 -0
  126. package/dist/serve/entries/storage.d.ts.map +1 -1
  127. package/dist/serve/entries/storage.js +9 -2
  128. package/dist/serve/entries/storage.js.map +1 -1
  129. package/dist/serve/html-injection.d.ts +3 -1
  130. package/dist/serve/html-injection.d.ts.map +1 -1
  131. package/dist/serve/html-injection.js +27 -1
  132. package/dist/serve/html-injection.js.map +1 -1
  133. package/dist/serve/rules.js +2 -2
  134. package/dist/serve/rules.js.map +1 -1
  135. package/dist/serve/runtime/chip-config.d.ts +1 -1
  136. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  137. package/dist/serve/runtime/chip-config.js +16 -8
  138. package/dist/serve/runtime/chip-config.js.map +1 -1
  139. package/dist/serve/sandbox-session.d.ts +1 -0
  140. package/dist/serve/sandbox-session.d.ts.map +1 -1
  141. package/dist/serve/sandbox-session.js +30 -2
  142. package/dist/serve/sandbox-session.js.map +1 -1
  143. package/dist/serve/site-ui/_astro/_studio_.B6b_G1ev.css +1 -0
  144. package/dist/serve/site-ui/_astro/app.bnmVTkIY.js +11 -0
  145. package/dist/serve/site-ui/_astro/app.t6u-adB_.js +1 -0
  146. package/dist/serve/site-ui/_astro/{chess-showcase.DzPO6kz0.js → chess-showcase.kC8dXLKY.js} +1 -1
  147. package/dist/serve/site-ui/_astro/{example-runtime.CM0H02rx.js → example-runtime.D79PnoSk.js} +1 -1
  148. package/dist/serve/site-ui/_astro/index.DzVde04M.js +1 -0
  149. package/dist/serve/site-ui/_astro/reads.BYBRLbsE.js +1 -0
  150. package/dist/serve/site-ui/_astro/sandbox-controls.C9Aaazt8.js +1252 -0
  151. package/dist/serve/site-ui/_astro/{seed.BCn5DhHS.js → seed.DANAIyRw.js} +1 -1
  152. package/dist/serve/site-ui/auth/index.html +2 -2
  153. package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
  154. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +1 -1
  155. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
  156. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
  157. package/dist/serve/site-ui/docs/ai-compat/index.html +85 -85
  158. package/dist/serve/site-ui/docs/ai-compat.md +84 -84
  159. package/dist/serve/site-ui/docs/api-reference/index.html +3 -1
  160. package/dist/serve/site-ui/docs/api-reference.md +2 -0
  161. package/dist/serve/site-ui/docs/app-compat/index.html +28 -28
  162. package/dist/serve/site-ui/docs/app-compat.md +27 -27
  163. package/dist/serve/site-ui/docs/auth-compat/index.html +122 -122
  164. package/dist/serve/site-ui/docs/auth-compat.md +121 -121
  165. package/dist/serve/site-ui/docs/build/ai-logic/index.html +1 -1
  166. package/dist/serve/site-ui/docs/build/authentication/index.html +1 -1
  167. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +1 -1
  168. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
  169. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +1 -1
  170. package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
  171. package/dist/serve/site-ui/docs/conformance-scores/index.html +4 -4
  172. package/dist/serve/site-ui/docs/conformance-scores.md +3 -3
  173. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -6
  174. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +5 -5
  175. package/dist/serve/site-ui/docs/database-compat/index.html +200 -448
  176. package/dist/serve/site-ui/docs/database-compat.md +198 -461
  177. package/dist/serve/site-ui/docs/examples/chess/index.html +2 -2
  178. package/dist/serve/site-ui/docs/examples/index.html +1 -1
  179. package/dist/serve/site-ui/docs/firestore-compat/index.html +186 -195
  180. package/dist/serve/site-ui/docs/firestore-compat.md +184 -195
  181. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +15 -15
  182. package/dist/serve/site-ui/docs/functions-rtdb-compat.md +14 -14
  183. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
  184. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +57 -0
  185. package/dist/serve/site-ui/docs/get-started/nextjs.md +86 -0
  186. package/dist/serve/site-ui/docs/get-started/start-building/index.html +25 -8
  187. package/dist/serve/site-ui/docs/get-started/start-building.md +34 -5
  188. package/dist/serve/site-ui/docs/get-started/vite/index.html +26 -0
  189. package/dist/serve/site-ui/docs/get-started/vite.md +45 -0
  190. package/dist/serve/site-ui/docs/index.json +668 -103
  191. package/dist/serve/site-ui/docs/messaging-compat/index.html +56 -56
  192. package/dist/serve/site-ui/docs/messaging-compat.md +55 -55
  193. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +1 -1
  194. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
  195. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
  196. package/dist/serve/site-ui/docs/overview/index.html +1 -1
  197. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +39 -13
  198. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api.md +28 -2
  199. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
  200. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +38 -6
  201. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api.md +43 -0
  202. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +9 -1
  203. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +8 -0
  204. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
  205. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +27 -4
  206. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api.md +23 -0
  207. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
  208. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
  209. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
  210. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +2 -2
  211. package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +1 -1
  212. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
  213. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
  214. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
  215. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
  216. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
  217. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
  218. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
  219. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
  220. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
  221. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +123 -0
  222. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +99 -0
  223. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +127 -0
  224. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api.md +174 -0
  225. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
  226. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
  227. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +570 -326
  228. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +198 -6
  229. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +1 -1
  230. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +1 -1
  231. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +1 -1
  232. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +2971 -627
  233. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +2873 -517
  234. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
  235. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
  236. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +43 -3
  237. package/dist/serve/site-ui/docs/pyric-rules-reference-api.md +8 -0
  238. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +26 -2
  239. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +24 -0
  240. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
  241. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +77 -9
  242. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +28 -13
  243. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +240 -63
  244. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +164 -5
  245. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
  246. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
  247. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
  248. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
  249. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
  250. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
  251. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
  252. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
  253. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
  254. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
  255. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
  256. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
  257. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +2 -1
  258. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +1 -0
  259. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
  260. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
  261. package/dist/serve/site-ui/docs/rules-compat/index.html +87 -79
  262. package/dist/serve/site-ui/docs/rules-compat.md +86 -78
  263. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
  264. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
  265. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
  266. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
  267. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
  268. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
  269. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
  270. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
  271. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +1 -1
  272. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
  273. package/dist/serve/site-ui/docs/storage-compat/index.html +119 -125
  274. package/dist/serve/site-ui/docs/storage-compat.md +118 -124
  275. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
  276. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
  277. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +1 -1
  278. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
  279. package/dist/serve/site-ui/docs/tutorial/index.html +1 -1
  280. package/dist/serve/site-ui/examples/chess/index.html +1 -1
  281. package/dist/serve/site-ui/examples/firestore-first-write/index.html +1 -1
  282. package/dist/serve/site-ui/firestore/index.html +2 -2
  283. package/dist/serve/site-ui/index.html +2 -2
  284. package/dist/serve/site-ui/llms.txt +6 -2
  285. package/dist/serve/site-ui/rtdb/index.html +2 -2
  286. package/dist/serve/site-ui/settings/index.html +2 -2
  287. package/dist/serve/site-ui/storage/index.html +2 -2
  288. package/dist/serve/site-ui/traffic/index.html +2 -2
  289. package/dist/serve/vite-ai-config.d.ts +4 -1
  290. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  291. package/dist/serve/vite-ai-config.js +83 -19
  292. package/dist/serve/vite-ai-config.js.map +1 -1
  293. package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -1
  294. package/dist/serve/vite-generation-rules-watch.js +61 -14
  295. package/dist/serve/vite-generation-rules-watch.js.map +1 -1
  296. package/dist/serve/vite-module-swap.d.ts +4 -1
  297. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  298. package/dist/serve/vite-module-swap.js +106 -21
  299. package/dist/serve/vite-module-swap.js.map +1 -1
  300. package/dist/serve/vite-plugin.d.ts.map +1 -1
  301. package/dist/serve/vite-plugin.js +45 -5
  302. package/dist/serve/vite-plugin.js.map +1 -1
  303. package/dist/serve/vite-sandbox-generation.js +1 -1
  304. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  305. package/dist/serve/worker/client/resumable.d.ts +30 -0
  306. package/dist/serve/worker/client/resumable.d.ts.map +1 -0
  307. package/dist/serve/worker/client/resumable.js +416 -0
  308. package/dist/serve/worker/client/resumable.js.map +1 -0
  309. package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -1
  310. package/dist/serve/worker/client/rtdb-references.js +4 -1
  311. package/dist/serve/worker/client/rtdb-references.js.map +1 -1
  312. package/dist/serve/worker/client/storage.d.ts +16 -2
  313. package/dist/serve/worker/client/storage.d.ts.map +1 -1
  314. package/dist/serve/worker/client/storage.js +57 -6
  315. package/dist/serve/worker/client/storage.js.map +1 -1
  316. package/dist/serve/worker/host/rules.d.ts.map +1 -1
  317. package/dist/serve/worker/host/rules.js +2 -1
  318. package/dist/serve/worker/host/rules.js.map +1 -1
  319. package/dist/serve/worker/index.d.ts +1 -1
  320. package/dist/serve/worker/index.d.ts.map +1 -1
  321. package/dist/serve/worker/index.js +1 -1
  322. package/dist/serve/worker/index.js.map +1 -1
  323. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  324. package/dist/serve/worker/serve-init.js +31 -0
  325. package/dist/serve/worker/serve-init.js.map +1 -1
  326. package/package.json +15 -4
  327. package/src/assurance/.generated/conformance-verdicts.ts +80 -72
  328. package/src/bridge/client/dispatch.ts +1 -1
  329. package/src/cli/cli.test.ts +14 -0
  330. package/src/cli/database-rules.ts +6 -4
  331. package/src/cli/dev-runner.ts +21 -0
  332. package/src/cli/serve.ts +62 -5
  333. package/src/cli/verify.ts +2 -2
  334. package/src/conformance/.generated/can-i-use-browser.ts +1 -1
  335. package/src/conformance/.generated/can-i-use.ts +1 -1
  336. package/src/conformance/.generated/conformance-docs.ts +1 -1
  337. package/src/next/client-aliases.ts +39 -0
  338. package/src/next/dev-rewrites.ts +77 -0
  339. package/src/next/guard.ts +61 -0
  340. package/src/next/index.ts +16 -0
  341. package/src/next/runtime-env.ts +18 -0
  342. package/src/next/server-external-packages.ts +43 -0
  343. package/src/next/target-url.ts +46 -0
  344. package/src/next/turbopack-config.ts +54 -0
  345. package/src/next/types.ts +47 -0
  346. package/src/next/webpack-config.ts +71 -0
  347. package/src/next/with-pyric.ts +58 -0
  348. package/src/register/app-bridge.ts +79 -0
  349. package/src/register/hooks.ts +6 -1
  350. package/src/register/index.ts +1 -1
  351. package/src/register/mapping.ts +50 -4
  352. package/src/rtdb/rules-json.ts +110 -0
  353. package/src/serve/bundler.ts +2 -0
  354. package/src/serve/discovery.ts +65 -44
  355. package/src/serve/entries/app-ai-passthrough.ts +83 -0
  356. package/src/serve/entries/auth-helper-core.ts +44 -8
  357. package/src/serve/entries/auth.ts +9 -4
  358. package/src/serve/entries/bridge-url.ts +9 -2
  359. package/src/serve/entries/database.ts +1 -0
  360. package/src/serve/entries/firestore.ts +1 -0
  361. package/src/serve/entries/init.ts +5 -2
  362. package/src/serve/entries/runtime.ts +25 -0
  363. package/src/serve/entries/storage.ts +12 -1
  364. package/src/serve/html-injection.ts +26 -1
  365. package/src/serve/rules.ts +2 -2
  366. package/src/serve/runtime/chip-config.ts +19 -6
  367. package/src/serve/sandbox-session.ts +31 -2
  368. package/src/serve/vite-ai-config.ts +86 -19
  369. package/src/serve/vite-generation-rules-watch.ts +67 -15
  370. package/src/serve/vite-module-swap.ts +121 -21
  371. package/src/serve/vite-plugin.ts +44 -6
  372. package/src/serve/vite-sandbox-generation.ts +1 -1
  373. package/src/serve/worker/client/resumable.ts +506 -0
  374. package/src/serve/worker/client/rtdb-references.ts +4 -1
  375. package/src/serve/worker/client/storage.ts +77 -7
  376. package/src/serve/worker/host/rules.ts +2 -1
  377. package/src/serve/worker/index.ts +4 -0
  378. package/src/serve/worker/serve-init.ts +30 -0
  379. package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +0 -1
  380. package/dist/serve/site-ui/_astro/app.BnMC0ywl.js +0 -109
  381. package/dist/serve/site-ui/_astro/app.DVXXR-WI.js +0 -1
  382. package/dist/serve/site-ui/_astro/index.B4Kh80he.js +0 -1
  383. package/dist/serve/site-ui/_astro/reads.D1exkX1-.js +0 -1
  384. package/dist/serve/site-ui/_astro/sandbox-controls.BqMePr5V.js +0 -1153
@@ -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
  }
@@ -63,6 +63,7 @@ export interface SandboxSession {
63
63
  payload(): InitPayload;
64
64
  handle(req: IncomingMessage, res: ServerResponse, url: URL): boolean | Promise<boolean>;
65
65
  reloadFirestoreRules(): Promise<RulesReloadResult>;
66
+ reloadDatabaseRules(): Promise<RulesReloadResult>;
66
67
  close(): Promise<void>;
67
68
  }
68
69
 
@@ -93,6 +94,8 @@ export async function createSandboxSession(
93
94
  const live = {
94
95
  rules: firestore.rules,
95
96
  rulesHash: firestore.rulesHash,
97
+ databaseRules: database.rules,
98
+ databaseRulesHash: database.rulesHash,
96
99
  };
97
100
  const events = createEventHub();
98
101
  const capture: CaptureStore | undefined = (options.capture ?? true)
@@ -145,8 +148,8 @@ export async function createSandboxSession(
145
148
  const payload = (): InitPayload => ({
146
149
  rules: live.rules,
147
150
  rulesHash: live.rulesHash,
148
- databaseRules: database.rules,
149
- databaseRulesHash: database.rulesHash,
151
+ databaseRules: live.databaseRules,
152
+ databaseRulesHash: live.databaseRulesHash,
150
153
  databaseUrl: database.databaseUrl,
151
154
  storageRules: storage.rules,
152
155
  storageRulesHash: storage.rulesHash,
@@ -217,6 +220,31 @@ export async function createSandboxSession(
217
220
  return { kind: 'rejected', error: error instanceof Error ? error : new Error(String(error)) };
218
221
  }
219
222
  };
223
+ const reloadDatabaseRules = async (): Promise<RulesReloadResult> => {
224
+ const isMissingDatabaseRules = database.sourcePath === null;
225
+ if (isMissingDatabaseRules) {
226
+ return { kind: 'not-configured' };
227
+ }
228
+ try {
229
+ const updated = await loadProjectDatabaseRules(options.projectDir, options.firebaseConfig);
230
+ const isMissingUpdatedRules = updated.rules === null || updated.rulesHash === null;
231
+ if (isMissingUpdatedRules) {
232
+ return { kind: 'not-configured' };
233
+ }
234
+ live.databaseRules = updated.rules;
235
+ live.databaseRulesHash = updated.rulesHash;
236
+ events.broadcast('rtdb-rules-update', { rules: updated.rules, rulesHash: updated.rulesHash });
237
+ return { kind: 'reloaded', rulesHash: updated.rulesHash as string, clients: events.clientCount() };
238
+ } catch (error) {
239
+ const isErrorInstance = error instanceof Error;
240
+ let errorResult: Error = new Error(String(error));
241
+ if (isErrorInstance) {
242
+ errorResult = error as Error;
243
+ }
244
+ return { kind: 'rejected', error: errorResult };
245
+ }
246
+ };
247
+
220
248
  let closePromise: Promise<void> | null = null;
221
249
  const close = (): Promise<void> => {
222
250
  closePromise ??= Promise.resolve().then(() => events.close());
@@ -228,6 +256,7 @@ export async function createSandboxSession(
228
256
  payload,
229
257
  handle: namespace,
230
258
  reloadFirestoreRules,
259
+ reloadDatabaseRules,
231
260
  close,
232
261
  };
233
262
  }
@@ -9,6 +9,8 @@ const AI_PROXY_PATH = '/__pyric/ai-proxy';
9
9
  export type PyricAiEngineConfig = Extract<NonNullable<AIOptions['engine']>, { kind: string }>;
10
10
 
11
11
  export interface PyricAiOptions {
12
+ /** Mode for AI Logic: 'sandbox' (local mirrors) or 'production' (pass-through to Google AI / Vertex AI). */
13
+ mode?: 'sandbox' | 'production';
12
14
  /** Simple OpenAI-compatible model selection through Pyric's same-origin proxy. */
13
15
  model?: string;
14
16
  /** Advanced declarative engine configuration. */
@@ -18,6 +20,7 @@ export interface PyricAiOptions {
18
20
  }
19
21
 
20
22
  export interface ResolvedViteAiConfig {
23
+ mode: 'sandbox' | 'production';
21
24
  engineWire: AiEngineConfigWire | undefined;
22
25
  proxyUpstream: string | undefined;
23
26
  }
@@ -26,8 +29,9 @@ export interface ResolvedViteAiConfig {
26
29
  export function viteWorkerEpochSalt(
27
30
  projectKey: string,
28
31
  engineWire: AiEngineConfigWire | undefined,
32
+ mode: 'sandbox' | 'production' = 'sandbox',
29
33
  ): string {
30
- return JSON.stringify({ projectKey, aiEngine: engineWire ?? null });
34
+ return JSON.stringify({ projectKey, aiEngine: engineWire ?? null, aiMode: mode });
31
35
  }
32
36
 
33
37
  /** Load env using Vite's `envDir`-relative-to-root convention. */
@@ -45,20 +49,30 @@ export function loadViteAiEnv(
45
49
 
46
50
  /** Convert a public declarative engine into the JSON-safe worker wire shape. */
47
51
  export function engineConfigToWire(engine: PyricAiEngineConfig): AiEngineConfigWire {
48
- if (engine.kind === 'openai') {
49
- return {
52
+ const isOpenAiEngine = engine.kind === 'openai';
53
+ if (isOpenAiEngine) {
54
+ const result: Record<string, unknown> = {
50
55
  kind: 'openai',
51
- baseUrl: engine.baseUrl ?? AI_PROXY_PATH,
52
- ...(engine.model !== undefined ? { model: engine.model } : {}),
53
- ...(engine.modelMap !== undefined ? { modelMap: engine.modelMap } : {}),
56
+ baseUrl: engine.baseUrl !== undefined && engine.baseUrl !== null ? engine.baseUrl : AI_PROXY_PATH,
54
57
  };
58
+ const hasModel = engine.model !== undefined;
59
+ if (hasModel) {
60
+ result.model = engine.model;
61
+ }
62
+ const hasModelMap = engine.modelMap !== undefined;
63
+ if (hasModelMap) {
64
+ result.modelMap = engine.modelMap;
65
+ }
66
+ return result as AiEngineConfigWire;
55
67
  }
56
- return {
68
+ const result: Record<string, unknown> = {
57
69
  kind: 'scripted',
58
- ...(engine.script !== undefined
59
- ? { script: engine.script as unknown as Array<Record<string, unknown>> }
60
- : {}),
61
70
  };
71
+ const hasScript = engine.script !== undefined;
72
+ if (hasScript) {
73
+ result.script = engine.script as unknown as Array<Record<string, unknown>>;
74
+ }
75
+ return result as AiEngineConfigWire;
62
76
  }
63
77
 
64
78
  /** Resolve the plugin's explicit-options-over-Vite-env AI convention. */
@@ -66,20 +80,73 @@ export function resolveViteAiConfig(
66
80
  options: PyricAiOptions | undefined,
67
81
  env: Record<string, string | undefined>,
68
82
  ): ResolvedViteAiConfig {
69
- if (options?.model !== undefined && options.engine !== undefined) {
83
+ const explicitModel = options?.model;
84
+ const explicitEngine = options?.engine;
85
+ const hasModelOption = explicitModel !== undefined;
86
+ const hasEngineOption = explicitEngine !== undefined;
87
+ const hasBothModelAndEngine = hasModelOption && hasEngineOption;
88
+ if (hasBothModelAndEngine) {
70
89
  throw new Error('@pyric/cli/vite: Choose either ai.model or ai.engine, not both.');
71
90
  }
72
91
 
73
- const model = options?.model?.trim() || env.PYRIC_AI_MODEL?.trim();
74
- const engineWire = options?.engine
75
- ? engineConfigToWire(options.engine)
76
- : model
77
- ? engineConfigToWire({ kind: 'openai', baseUrl: AI_PROXY_PATH, model })
78
- : undefined;
92
+ let mode: 'sandbox' | 'production' = 'sandbox';
93
+ const explicitMode = options?.mode;
94
+ const hasExplicitMode = explicitMode !== undefined;
95
+ if (hasExplicitMode) {
96
+ mode = explicitMode;
97
+ } else {
98
+ const isEnvProductionMode = env.PYRIC_AI_MODE === 'production';
99
+ const isEnvPassthroughFlag = env.PYRIC_AI_PASSTHROUGH === '1';
100
+ const isProductionEnv = isEnvProductionMode || isEnvPassthroughFlag;
101
+ if (isProductionEnv) {
102
+ mode = 'production';
103
+ }
104
+ }
105
+
106
+ const isProductionMode = mode === 'production';
107
+ const hasAnyEngineConfig = hasModelOption || hasEngineOption;
108
+ const isInvalidProductionConfig = isProductionMode && hasAnyEngineConfig;
109
+ if (isInvalidProductionConfig) {
110
+ throw new Error('@pyric/cli/vite: Cannot configure ai.model or ai.engine when ai.mode is set to "production".');
111
+ }
112
+
113
+ let model: string | undefined = undefined;
114
+ const envModel = env.PYRIC_AI_MODEL;
115
+ if (explicitModel !== undefined) {
116
+ model = explicitModel.trim();
117
+ } else if (envModel !== undefined) {
118
+ model = envModel.trim();
119
+ }
120
+ const hasNonEmptyModel = model !== undefined && model !== '';
121
+ if (!hasNonEmptyModel) {
122
+ model = undefined;
123
+ }
124
+
125
+ let engineWire: AiEngineConfigWire | undefined = undefined;
126
+ if (!isProductionMode) {
127
+ if (explicitEngine !== undefined) {
128
+ engineWire = engineConfigToWire(explicitEngine);
129
+ } else if (model !== undefined) {
130
+ engineWire = engineConfigToWire({ kind: 'openai', baseUrl: AI_PROXY_PATH, model });
131
+ }
132
+ }
133
+
134
+ let proxyUpstream: string | undefined = undefined;
135
+ const explicitProxyUpstream = options?.proxyUpstream;
136
+ const envProxyUpstream = env.PYRIC_AI_PROXY_UPSTREAM;
137
+ if (explicitProxyUpstream !== undefined) {
138
+ proxyUpstream = explicitProxyUpstream.trim();
139
+ } else if (envProxyUpstream !== undefined) {
140
+ proxyUpstream = envProxyUpstream.trim();
141
+ }
142
+ const hasNonEmptyProxyUpstream = proxyUpstream !== undefined && proxyUpstream !== '';
143
+ if (!hasNonEmptyProxyUpstream) {
144
+ proxyUpstream = undefined;
145
+ }
79
146
 
80
147
  return {
148
+ mode,
81
149
  engineWire,
82
- proxyUpstream:
83
- options?.proxyUpstream?.trim() || env.PYRIC_AI_PROXY_UPSTREAM?.trim() || undefined,
150
+ proxyUpstream,
84
151
  };
85
152
  }
@@ -8,30 +8,82 @@ export function watchViteGenerationRules(input: {
8
8
  session: SandboxSession;
9
9
  }): (() => void) | null {
10
10
  const { server, session } = input;
11
- const rulesFile = session.summary.rules.firestore.sourcePath;
12
- if (!rulesFile) return null;
11
+ const firestoreFile = session.summary.rules.firestore.sourcePath;
12
+ const databaseFile = session.summary.rules.database.sourcePath;
13
+ const hasFirestoreFile = firestoreFile !== null;
14
+ const hasDatabaseFile = databaseFile !== null;
15
+ const hasNeitherFile = !hasFirestoreFile && !hasDatabaseFile;
16
+ if (hasNeitherFile) {
17
+ return null;
18
+ }
13
19
 
14
20
  let debounce: ReturnType<typeof setTimeout> | null = null;
15
21
  const onRulesChange = (file: string): void => {
16
- if (path.resolve(file) !== path.resolve(rulesFile)) return;
17
- if (debounce) clearTimeout(debounce);
22
+ const resolvedFile = path.resolve(file);
23
+ let isFirestoreMatch = false;
24
+ if (hasFirestoreFile) {
25
+ const firestoreResolved = path.resolve(firestoreFile);
26
+ isFirestoreMatch = resolvedFile === firestoreResolved;
27
+ }
28
+ let isDatabaseMatch = false;
29
+ if (hasDatabaseFile) {
30
+ const databaseResolved = path.resolve(databaseFile);
31
+ isDatabaseMatch = resolvedFile === databaseResolved;
32
+ }
33
+ const isNeitherMatch = !isFirestoreMatch && !isDatabaseMatch;
34
+ if (isNeitherMatch) {
35
+ return;
36
+ }
37
+ const hasDebounce = debounce !== null;
38
+ if (hasDebounce) {
39
+ clearTimeout(debounce as ReturnType<typeof setTimeout>);
40
+ }
18
41
  debounce = setTimeout(() => {
19
- void session.reloadFirestoreRules().then((result) => {
20
- if (result.kind === 'reloaded') {
21
- server.config.logger.info(` ↻ [pyric] rules reloaded (${result.rulesHash})`);
22
- } else if (result.kind === 'rejected') {
23
- server.config.logger.warn(
24
- ` ⚠ [pyric] rules NOT reloaded (last-good stays live): ${result.error.message}`,
25
- );
26
- }
27
- });
42
+ if (isFirestoreMatch) {
43
+ void session.reloadFirestoreRules().then((result) => {
44
+ const isReloaded = result.kind === 'reloaded';
45
+ if (isReloaded) {
46
+ server.config.logger.info(` ↻ [pyric] rules reloaded (${result.rulesHash})`);
47
+ } else {
48
+ const isRejected = result.kind === 'rejected';
49
+ if (isRejected) {
50
+ server.config.logger.warn(
51
+ ` ⚠ [pyric] rules NOT reloaded (last-good stays live): ${result.error.message}`,
52
+ );
53
+ }
54
+ }
55
+ });
56
+ }
57
+ if (isDatabaseMatch) {
58
+ void session.reloadDatabaseRules().then((result) => {
59
+ const isReloaded = result.kind === 'reloaded';
60
+ if (isReloaded) {
61
+ server.config.logger.info(` ↻ [pyric] rtdb rules reloaded (${result.rulesHash})`);
62
+ } else {
63
+ const isRejected = result.kind === 'rejected';
64
+ if (isRejected) {
65
+ server.config.logger.warn(
66
+ ` ⚠ [pyric] rtdb rules NOT reloaded (last-good stays live): ${result.error.message}`,
67
+ );
68
+ }
69
+ }
70
+ });
71
+ }
28
72
  }, 150);
29
73
  };
30
74
 
31
- server.watcher.add(rulesFile);
75
+ if (hasFirestoreFile) {
76
+ server.watcher.add(firestoreFile);
77
+ }
78
+ if (hasDatabaseFile) {
79
+ server.watcher.add(databaseFile);
80
+ }
32
81
  server.watcher.on('change', onRulesChange);
33
82
  return () => {
34
- if (debounce) clearTimeout(debounce);
83
+ const hasDebounce = debounce !== null;
84
+ if (hasDebounce) {
85
+ clearTimeout(debounce as ReturnType<typeof setTimeout>);
86
+ }
35
87
  server.watcher.off('change', onRulesChange);
36
88
  };
37
89
  }
@@ -45,10 +45,18 @@ export function createViteModuleContext(): ViteModuleContext {
45
45
  return { entries, cliRoot: packageRootOf(entries.init) };
46
46
  }
47
47
 
48
+ export interface ViteModuleSwapOptions {
49
+ getAiMode?: () => 'sandbox' | 'production';
50
+ }
51
+
48
52
  /** Own the Vite and optimizer forms of the Firebase-module swap. */
49
- export function createViteModuleSwap(context: ViteModuleContext): ViteModuleSwap {
53
+ export function createViteModuleSwap(
54
+ context: ViteModuleContext,
55
+ options?: ViteModuleSwapOptions,
56
+ ): ViteModuleSwap {
50
57
  const { entries, cliRoot } = context;
51
58
  const pyricRoot = pyricPackageRoot();
59
+ const aiMode = () => options?.getAiMode?.() ?? 'sandbox';
52
60
 
53
61
  const isPyricImporter = (importer: string | undefined): boolean => {
54
62
  if (!importer) return false;
@@ -68,28 +76,72 @@ export function createViteModuleSwap(context: ViteModuleContext): ViteModuleSwap
68
76
  name: 'pyric-sandbox-optimizer',
69
77
  setup(build) {
70
78
  build.onResolve({ filter: FIREBASE_SPECIFIER }, (args) => {
71
- const subpath = FIREBASE_SPECIFIER.exec(args.path)![1]!;
72
- if (SERVED_FIREBASE_SUBPATHS.has(subpath)) {
73
- return { path: entries[entryKey(subpath)]! };
79
+ const isShadowBridgeImporter = args.importer !== undefined && args.importer !== '' &&
80
+ (args.importer.includes('app-ai-passthrough') || args.importer.includes('app-bridge'));
81
+ const isFirebaseAppSpecifier = args.path === 'firebase/app';
82
+ const isBypassedBridgeImport = isShadowBridgeImporter && isFirebaseAppSpecifier;
83
+ if (isBypassedBridgeImport) {
84
+ return null;
85
+ }
86
+
87
+ const match = FIREBASE_SPECIFIER.exec(args.path);
88
+ const subpath = match !== null && match[1] !== undefined ? match[1] : '';
89
+ const isProductionAiMode = aiMode() === 'production';
90
+ if (isProductionAiMode) {
91
+ const isAiSubpath = subpath === 'ai';
92
+ if (isAiSubpath) {
93
+ return null;
94
+ }
95
+ const isAppSubpath = subpath === 'app';
96
+ const passthroughEntry = entries['app-ai-passthrough'];
97
+ const hasPassthroughEntry = passthroughEntry !== undefined;
98
+ const shouldUsePassthroughBridge = isAppSubpath && hasPassthroughEntry;
99
+ if (shouldUsePassthroughBridge) {
100
+ return { path: passthroughEntry };
101
+ }
102
+ }
103
+
104
+ const isServedSubpath = SERVED_FIREBASE_SUBPATHS.has(subpath);
105
+ if (isServedSubpath) {
106
+ const key = entryKey(subpath);
107
+ const entryPath = entries[key];
108
+ if (entryPath !== undefined) {
109
+ return { path: entryPath };
110
+ }
74
111
  }
75
112
  return null;
76
113
  });
77
114
  build.onResolve({ filter: NODE_BUILTIN_RE }, (args) => {
78
- if (!isOurCode(args.importer)) return null;
79
- return { path: args.path.replace(/^node:/, ''), namespace: 'pyric-node-shim' };
115
+ const isOwnedImporter = isOurCode(args.importer);
116
+ if (!isOwnedImporter) {
117
+ return null;
118
+ }
119
+ const shimPath = args.path.replace(/^node:/, '');
120
+ return { path: shimPath, namespace: 'pyric-node-shim' };
121
+ });
122
+ build.onLoad({ filter: /.*/, namespace: 'pyric-node-shim' }, (args) => {
123
+ const content = NODE_BUILTIN_SHIMS[args.path];
124
+ if (content !== undefined) {
125
+ return { contents: content, loader: 'js' };
126
+ }
127
+ return null;
80
128
  });
81
- build.onLoad({ filter: /.*/, namespace: 'pyric-node-shim' }, (args) => ({
82
- contents: NODE_BUILTIN_SHIMS[args.path]!,
83
- loader: 'js',
84
- }));
85
129
  },
86
130
  };
87
131
 
88
132
  return {
89
133
  config() {
134
+ const excludedModules = [
135
+ ...SDK_MODULES,
136
+ '@firebase/app',
137
+ '@firebase/component',
138
+ '@firebase/ai',
139
+ '@firebase/util',
140
+ '@firebase/logger',
141
+ ];
90
142
  return {
91
143
  optimizeDeps: {
92
- exclude: [...SDK_MODULES],
144
+ exclude: excludedModules,
93
145
  include: ['js-md5', 'js-sha256'],
94
146
  esbuildOptions: { plugins: [optimizerMirror] },
95
147
  },
@@ -97,23 +149,71 @@ export function createViteModuleSwap(context: ViteModuleContext): ViteModuleSwap
97
149
  },
98
150
  configResolved(config) {
99
151
  const allow = config.server?.fs?.allow;
100
- if (!allow) return;
152
+ const hasAllowList = allow !== undefined && Array.isArray(allow);
153
+ if (!hasAllowList) {
154
+ return;
155
+ }
101
156
  for (const dir of [pyricRoot, cliRoot]) {
102
- if (!allow.includes(dir)) allow.push(dir);
157
+ const isAlreadyAllowed = allow.includes(dir);
158
+ if (!isAlreadyAllowed) {
159
+ allow.push(dir);
160
+ }
103
161
  }
104
162
  },
105
163
  resolveId(source, importer) {
106
- const firebase = FIREBASE_SPECIFIER.exec(source);
107
- if (firebase) {
108
- const subpath = firebase[1]!;
109
- return SERVED_FIREBASE_SUBPATHS.has(subpath) ? entries[entryKey(subpath)]! : null;
164
+ const isShadowBridgeImporter = importer !== undefined &&
165
+ (importer.includes('app-ai-passthrough') || importer.includes('app-bridge'));
166
+ const isFirebaseAppSpecifier = source === 'firebase/app';
167
+ const isBypassedBridgeImport = isShadowBridgeImporter && isFirebaseAppSpecifier;
168
+ if (isBypassedBridgeImport) {
169
+ return null;
110
170
  }
111
- const node = NODE_BUILTIN_RE.exec(source);
112
- return node && isOurCode(importer) ? NODE_SHIM_PREFIX + node[2]! : null;
171
+
172
+ const firebaseMatch = FIREBASE_SPECIFIER.exec(source);
173
+ const isFirebaseSpecifier = firebaseMatch !== null;
174
+ if (isFirebaseSpecifier) {
175
+ const subpath = firebaseMatch[1] !== undefined ? firebaseMatch[1] : '';
176
+ const isProductionAiMode = aiMode() === 'production';
177
+ if (isProductionAiMode) {
178
+ const isAiSubpath = subpath === 'ai';
179
+ if (isAiSubpath) {
180
+ return null;
181
+ }
182
+ const isAppSubpath = subpath === 'app';
183
+ const passthroughEntry = entries['app-ai-passthrough'];
184
+ const hasPassthroughEntry = passthroughEntry !== undefined;
185
+ const shouldUsePassthroughBridge = isAppSubpath && hasPassthroughEntry;
186
+ if (shouldUsePassthroughBridge) {
187
+ return passthroughEntry;
188
+ }
189
+ }
190
+ const isServedSubpath = SERVED_FIREBASE_SUBPATHS.has(subpath);
191
+ if (isServedSubpath) {
192
+ const key = entryKey(subpath);
193
+ const entryPath = entries[key];
194
+ if (entryPath !== undefined) {
195
+ return entryPath;
196
+ }
197
+ }
198
+ return null;
199
+ }
200
+
201
+ const nodeMatch = NODE_BUILTIN_RE.exec(source);
202
+ const isNodeBuiltin = nodeMatch !== null && nodeMatch[2] !== undefined;
203
+ const isOwnedImporter = isOurCode(importer);
204
+ const shouldShimNodeBuiltin = isNodeBuiltin && isOwnedImporter;
205
+ if (shouldShimNodeBuiltin) {
206
+ return NODE_SHIM_PREFIX + nodeMatch[2];
207
+ }
208
+ return null;
113
209
  },
114
210
  load(id) {
115
- if (!id.startsWith(NODE_SHIM_PREFIX)) return null;
116
- return shimFor(id.slice(NODE_SHIM_PREFIX.length));
211
+ const isNodeShim = id.startsWith(NODE_SHIM_PREFIX);
212
+ if (!isNodeShim) {
213
+ return null;
214
+ }
215
+ const specifier = id.slice(NODE_SHIM_PREFIX.length);
216
+ return shimFor(specifier);
117
217
  },
118
218
  };
119
219
  }