@pyric/cli 0.1.0-alpha.14 → 0.1.0-alpha.16
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.
- package/dist/assurance/.generated/conformance-verdicts.d.ts +120 -75
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +120 -75
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/bridge/client/dispatch.js +1 -1
- package/dist/bridge/client/dispatch.js.map +1 -1
- package/dist/cli/serve.d.ts +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +207 -284
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/service-command-records/database-rules-generate.d.ts +4 -0
- package/dist/cli/service-command-records/database-rules-generate.d.ts.map +1 -0
- package/dist/cli/service-command-records/database-rules-generate.js +3 -0
- package/dist/cli/service-command-records/database-rules-generate.js.map +1 -0
- package/dist/cli/service-command-records/database-rules-lint.d.ts +4 -0
- package/dist/cli/service-command-records/database-rules-lint.d.ts.map +1 -0
- package/dist/cli/service-command-records/database-rules-lint.js +3 -0
- package/dist/cli/service-command-records/database-rules-lint.js.map +1 -0
- package/dist/cli/service-command-records/database-rules-simulate.d.ts +4 -0
- package/dist/cli/service-command-records/database-rules-simulate.d.ts.map +1 -0
- package/dist/cli/service-command-records/database-rules-simulate.js +3 -0
- package/dist/cli/service-command-records/database-rules-simulate.js.map +1 -0
- package/dist/cli/service-command-records/database-rules-validate.d.ts +4 -0
- package/dist/cli/service-command-records/database-rules-validate.d.ts.map +1 -0
- package/dist/cli/service-command-records/database-rules-validate.js +3 -0
- package/dist/cli/service-command-records/database-rules-validate.js.map +1 -0
- package/dist/cli/service-command-records/firestore-indexes-generate.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-indexes-generate.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-indexes-generate.js +3 -0
- package/dist/cli/service-command-records/firestore-indexes-generate.js.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-lint.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-rules-lint.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-lint.js +3 -0
- package/dist/cli/service-command-records/firestore-rules-lint.js.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-resolve.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-rules-resolve.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-resolve.js +3 -0
- package/dist/cli/service-command-records/firestore-rules-resolve.js.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-simulate.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-rules-simulate.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-simulate.js +3 -0
- package/dist/cli/service-command-records/firestore-rules-simulate.js.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-validate.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-rules-validate.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-validate.js +3 -0
- package/dist/cli/service-command-records/firestore-rules-validate.js.map +1 -0
- package/dist/cli/service-command-records/storage-rules-lint.d.ts +4 -0
- package/dist/cli/service-command-records/storage-rules-lint.d.ts.map +1 -0
- package/dist/cli/service-command-records/storage-rules-lint.js +3 -0
- package/dist/cli/service-command-records/storage-rules-lint.js.map +1 -0
- package/dist/cli/service-command-records/storage-rules-simulate.d.ts +4 -0
- package/dist/cli/service-command-records/storage-rules-simulate.d.ts.map +1 -0
- package/dist/cli/service-command-records/storage-rules-simulate.js +3 -0
- package/dist/cli/service-command-records/storage-rules-simulate.js.map +1 -0
- package/dist/cli/service-commands.d.ts +7 -0
- package/dist/cli/service-commands.d.ts.map +1 -1
- package/dist/cli/service-commands.generated.d.ts +35 -0
- package/dist/cli/service-commands.generated.d.ts.map +1 -0
- package/dist/cli/service-commands.generated.js +25 -0
- package/dist/cli/service-commands.generated.js.map +1 -0
- package/dist/cli/service-commands.js +23 -40
- package/dist/cli/service-commands.js.map +1 -1
- package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use-browser.js +1 -1
- package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
- package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use.js +1 -1
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
- package/dist/conformance/.generated/conformance-docs.js +1 -1
- package/dist/conformance/.generated/conformance-docs.js.map +1 -1
- package/dist/functions-rtdb/development-runtime.d.ts +63 -0
- package/dist/functions-rtdb/development-runtime.d.ts.map +1 -0
- package/dist/functions-rtdb/development-runtime.js +244 -0
- package/dist/functions-rtdb/development-runtime.js.map +1 -0
- package/dist/serve/bridge-mount.d.ts +32 -2
- package/dist/serve/bridge-mount.d.ts.map +1 -1
- package/dist/serve/bridge-mount.js +232 -18
- package/dist/serve/bridge-mount.js.map +1 -1
- package/dist/serve/bundler.d.ts +2 -18
- package/dist/serve/bundler.d.ts.map +1 -1
- package/dist/serve/bundler.js +7 -35
- package/dist/serve/bundler.js.map +1 -1
- package/dist/serve/entries/app-client.d.ts.map +1 -1
- package/dist/serve/entries/app-client.js +5 -5
- package/dist/serve/entries/app-client.js.map +1 -1
- package/dist/serve/entries/auth-helper-core.d.ts +32 -6
- package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
- package/dist/serve/entries/auth-helper-core.js +82 -24
- package/dist/serve/entries/auth-helper-core.js.map +1 -1
- package/dist/serve/entries/auth.d.ts.map +1 -1
- package/dist/serve/entries/auth.js +6 -4
- package/dist/serve/entries/auth.js.map +1 -1
- package/dist/serve/entries/database.d.ts +28 -0
- package/dist/serve/entries/database.d.ts.map +1 -1
- package/dist/serve/entries/database.js +95 -26
- package/dist/serve/entries/database.js.map +1 -1
- package/dist/serve/entries/init.d.ts.map +1 -1
- package/dist/serve/entries/init.js +21 -12
- package/dist/serve/entries/init.js.map +1 -1
- package/dist/serve/html-injection.d.ts +5 -0
- package/dist/serve/html-injection.d.ts.map +1 -0
- package/dist/serve/html-injection.js +59 -0
- package/dist/serve/html-injection.js.map +1 -0
- package/dist/serve/namespace.d.ts +6 -22
- package/dist/serve/namespace.d.ts.map +1 -1
- package/dist/serve/namespace.js +23 -145
- package/dist/serve/namespace.js.map +1 -1
- package/dist/serve/runtime/worker-replacement.d.ts +1 -2
- package/dist/serve/runtime/worker-replacement.d.ts.map +1 -1
- package/dist/serve/sandbox-session.d.ts +78 -0
- package/dist/serve/sandbox-session.d.ts.map +1 -0
- package/dist/serve/sandbox-session.js +171 -0
- package/dist/serve/sandbox-session.js.map +1 -0
- package/dist/serve/server.d.ts +5 -2
- package/dist/serve/server.d.ts.map +1 -1
- package/dist/serve/server.js +21 -5
- package/dist/serve/server.js.map +1 -1
- package/dist/serve/site-tree.d.ts +8 -0
- package/dist/serve/site-tree.d.ts.map +1 -0
- package/dist/serve/site-tree.js +113 -0
- package/dist/serve/site-tree.js.map +1 -0
- package/dist/serve/site-ui/_astro/RulesCodeEditor.CzwHdCi9.js +23 -0
- package/dist/serve/site-ui/_astro/_example_.jevZ7OdV.css +1 -0
- package/dist/serve/site-ui/_astro/_slug_.BoKXYrnu.css +1 -0
- package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +1 -0
- package/dist/serve/site-ui/_astro/app.4HeLP_FA.js +109 -0
- package/dist/serve/site-ui/_astro/app.BgSnCR5G.js +1 -0
- package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +1 -0
- package/dist/serve/site-ui/_astro/chess-showcase.CnoxIle5.js +1 -0
- package/dist/serve/site-ui/_astro/chess-source-explorer.C5k9c5yK.js +1 -0
- package/dist/serve/site-ui/_astro/chess-v2.CFHmd3UL.js +354 -0
- package/dist/serve/site-ui/_astro/client.D2ORs4B-.js +25 -0
- package/dist/serve/site-ui/_astro/example-runtime.R1d96L6-.js +291 -0
- package/dist/serve/site-ui/_astro/index.BJiOemMX.js +1 -0
- package/dist/serve/site-ui/_astro/index.DBy5LfQW.js +9 -0
- package/dist/serve/site-ui/_astro/index.DNyk7q8W.js +9 -0
- package/dist/serve/site-ui/_astro/jsx-runtime.D_zvdyIk.js +9 -0
- package/dist/serve/site-ui/_astro/reads.BrKNdKAa.js +1 -0
- package/dist/serve/site-ui/_astro/sandbox-controls.BTb3EbQp.js +1153 -0
- package/dist/serve/site-ui/_astro/seed.EyI3VYEu.js +20 -0
- package/dist/serve/site-ui/auth/index.html +11 -0
- package/dist/serve/site-ui/docs/_rhythm/index.html +100 -0
- package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +43 -0
- package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +26 -0
- package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +70 -0
- package/dist/serve/{docs-ui → site-ui}/docs/ai-compat/index.html +3 -3
- package/dist/serve/site-ui/docs/api-reference/index.html +68 -0
- package/dist/serve/{docs-ui → site-ui}/docs/app-compat/index.html +3 -3
- package/dist/serve/{docs-ui → site-ui}/docs/auth-compat/index.html +3 -3
- package/dist/serve/site-ui/docs/build/ai-logic/index.html +64 -0
- package/dist/serve/site-ui/docs/build/authentication/index.html +66 -0
- package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +84 -0
- package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +71 -0
- package/dist/serve/site-ui/docs/build/cloud-storage/index.html +66 -0
- package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-storage.md +2 -2
- package/dist/serve/site-ui/docs/build/realtime-database/index.html +67 -0
- package/dist/serve/site-ui/docs/conformance-scores/index.html +50 -0
- package/dist/serve/{docs-ui → site-ui}/docs/conformance-scores.md +3 -3
- package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +531 -0
- package/dist/serve/{docs-ui → site-ui}/docs/database-compat/index.html +211 -168
- package/dist/serve/{docs-ui → site-ui}/docs/database-compat.md +208 -170
- package/dist/serve/site-ui/docs/examples/chess/index.html +384 -0
- package/dist/serve/site-ui/docs/examples/chess.md +57 -0
- package/dist/serve/site-ui/docs/examples/index.html +3 -0
- package/dist/serve/site-ui/docs/examples.md +4 -0
- package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat/index.html +55 -91
- package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat.md +52 -88
- package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +73 -0
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +29 -0
- package/dist/serve/site-ui/docs/get-started/start-building/index.html +33 -0
- package/dist/serve/{docs-ui → site-ui}/docs/index.json +595 -26
- package/dist/serve/site-ui/docs/messaging-compat/index.html +324 -0
- package/dist/serve/{docs-ui → site-ui}/docs/messaging-compat.md +71 -1
- package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +28 -0
- package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +74 -0
- package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +45 -0
- package/dist/serve/site-ui/docs/overview/index.html +17 -0
- package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +186 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api/index.html +318 -202
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api.md +154 -27
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api/index.html +5 -5
- package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +318 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api/index.html +5 -5
- package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +160 -0
- package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +425 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api/index.html +6 -6
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +60 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +507 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +258 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +51 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +308 -0
- package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +68 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +11 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api/index.html +1186 -1384
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api.md +817 -1291
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +126 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-vite-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +2641 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-database-reference-api.md +1055 -158
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api/index.html +311 -249
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api.md +72 -54
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +509 -0
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +182 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api/index.html +7 -26
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api.md +13 -23
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +121 -0
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +203 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api/index.html +26 -5
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api.md +22 -22
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api/index.html +5 -15
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api.md +0 -13
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +639 -0
- package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +100 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +24 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +136 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api/index.html +7 -7
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api.md +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +16 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +176 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api/index.html +10 -11
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api.md +7 -8
- package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +188 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/rules-compat/index.html +87 -57
- package/dist/serve/{docs-ui → site-ui}/docs/rules-compat.md +84 -54
- package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +51 -0
- package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +106 -0
- package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +41 -0
- package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +67 -0
- package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +159 -0
- package/dist/serve/{docs-ui → site-ui}/docs/secure/rules-standard-library.md +2 -2
- package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +47 -0
- package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +95 -0
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +82 -0
- package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +37 -0
- package/dist/serve/site-ui/docs/ship/test-in-node/index.html +75 -0
- package/dist/serve/{docs-ui → site-ui}/docs/storage-compat/index.html +8 -8
- package/dist/serve/{docs-ui → site-ui}/docs/storage-compat.md +5 -5
- package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +132 -0
- package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +861 -0
- package/dist/serve/site-ui/docs/trust/rules-standard-library.md +344 -0
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +582 -0
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +448 -0
- package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +14 -0
- package/dist/serve/{docs-ui → site-ui}/docs/tutorial/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/tutorial.md +1 -1
- package/dist/serve/site-ui/examples/chess/index.html +2 -0
- package/dist/serve/site-ui/examples/firestore-first-write/index.html +2 -0
- package/dist/serve/site-ui/firestore/index.html +11 -0
- package/dist/serve/site-ui/index.html +11 -0
- package/dist/serve/{docs-ui → site-ui}/llms.txt +6 -2
- package/dist/serve/site-ui/rtdb/index.html +11 -0
- package/dist/serve/site-ui/settings/index.html +11 -0
- package/dist/serve/site-ui/storage/index.html +11 -0
- package/dist/serve/site-ui/studio-routes.json +1 -0
- package/dist/serve/site-ui/traffic/index.html +11 -0
- package/dist/serve/standalone-assets.d.ts +4 -10
- package/dist/serve/standalone-assets.d.ts.map +1 -1
- package/dist/serve/standalone-assets.js +8 -21
- package/dist/serve/standalone-assets.js.map +1 -1
- package/dist/serve/vite-functions-development.d.ts +29 -0
- package/dist/serve/vite-functions-development.d.ts.map +1 -0
- package/dist/serve/vite-functions-development.js +150 -0
- package/dist/serve/vite-functions-development.js.map +1 -0
- package/dist/serve/vite-generation-bridge.d.ts +17 -0
- package/dist/serve/vite-generation-bridge.d.ts.map +1 -0
- package/dist/serve/vite-generation-bridge.js +47 -0
- package/dist/serve/vite-generation-bridge.js.map +1 -0
- package/dist/serve/vite-generation-functions.d.ts +35 -0
- package/dist/serve/vite-generation-functions.d.ts.map +1 -0
- package/dist/serve/vite-generation-functions.js +46 -0
- package/dist/serve/vite-generation-functions.js.map +1 -0
- package/dist/serve/vite-generation-middleware.d.ts +10 -0
- package/dist/serve/vite-generation-middleware.d.ts.map +1 -0
- package/dist/serve/vite-generation-middleware.js +40 -0
- package/dist/serve/vite-generation-middleware.js.map +1 -0
- package/dist/serve/vite-generation-rules-watch.d.ts +8 -0
- package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -0
- package/dist/serve/vite-generation-rules-watch.js +33 -0
- package/dist/serve/vite-generation-rules-watch.js.map +1 -0
- package/dist/serve/vite-module-swap.d.ts +16 -0
- package/dist/serve/vite-module-swap.d.ts.map +1 -0
- package/dist/serve/vite-module-swap.js +96 -0
- package/dist/serve/vite-module-swap.js.map +1 -0
- package/dist/serve/vite-page-runtime.d.ts +29 -0
- package/dist/serve/vite-page-runtime.d.ts.map +1 -0
- package/dist/serve/vite-page-runtime.js +71 -0
- package/dist/serve/vite-page-runtime.js.map +1 -0
- package/dist/serve/vite-plugin.d.ts +44 -4
- package/dist/serve/vite-plugin.d.ts.map +1 -1
- package/dist/serve/vite-plugin.js +62 -864
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-sandbox-generation.d.ts +57 -0
- package/dist/serve/vite-sandbox-generation.d.ts.map +1 -0
- package/dist/serve/vite-sandbox-generation.js +178 -0
- package/dist/serve/vite-sandbox-generation.js.map +1 -0
- package/dist/serve/worker/client/disconnect.d.ts.map +1 -1
- package/dist/serve/worker/client/disconnect.js +2 -0
- package/dist/serve/worker/client/disconnect.js.map +1 -1
- package/dist/serve/worker/client/handles.d.ts +5 -0
- package/dist/serve/worker/client/handles.d.ts.map +1 -1
- package/dist/serve/worker/client/handles.js.map +1 -1
- package/dist/serve/worker/client/pagehide.d.ts +13 -0
- package/dist/serve/worker/client/pagehide.d.ts.map +1 -0
- package/dist/serve/worker/client/pagehide.js +19 -0
- package/dist/serve/worker/client/pagehide.js.map +1 -0
- package/dist/serve/worker/client/rtdb-admin.d.ts +8 -0
- package/dist/serve/worker/client/rtdb-admin.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-admin.js +39 -0
- package/dist/serve/worker/client/rtdb-admin.js.map +1 -0
- package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts +15 -0
- package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-connection-lifecycle.js +45 -0
- package/dist/serve/worker/client/rtdb-connection-lifecycle.js.map +1 -0
- package/dist/serve/worker/client/rtdb-controls.d.ts +6 -0
- package/dist/serve/worker/client/rtdb-controls.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-controls.js +8 -0
- package/dist/serve/worker/client/rtdb-controls.js.map +1 -0
- package/dist/serve/worker/client/rtdb-listeners.d.ts +24 -0
- package/dist/serve/worker/client/rtdb-listeners.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-listeners.js +262 -0
- package/dist/serve/worker/client/rtdb-listeners.js.map +1 -0
- package/dist/serve/worker/client/rtdb-reads.d.ts +4 -0
- package/dist/serve/worker/client/rtdb-reads.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-reads.js +11 -0
- package/dist/serve/worker/client/rtdb-reads.js.map +1 -0
- package/dist/serve/worker/client/rtdb-references.d.ts +19 -0
- package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-references.js +63 -0
- package/dist/serve/worker/client/rtdb-references.js.map +1 -0
- package/dist/serve/worker/client/rtdb-snapshots.d.ts +20 -0
- package/dist/serve/worker/client/rtdb-snapshots.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-snapshots.js +64 -0
- package/dist/serve/worker/client/rtdb-snapshots.js.map +1 -0
- package/dist/serve/worker/client/rtdb-transactions.d.ts +14 -0
- package/dist/serve/worker/client/rtdb-transactions.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-transactions.js +34 -0
- package/dist/serve/worker/client/rtdb-transactions.js.map +1 -0
- package/dist/serve/worker/client/rtdb-writes.d.ts +8 -0
- package/dist/serve/worker/client/rtdb-writes.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-writes.js +65 -0
- package/dist/serve/worker/client/rtdb-writes.js.map +1 -0
- package/dist/serve/worker/client.d.ts +0 -2
- package/dist/serve/worker/client.d.ts.map +1 -1
- package/dist/serve/worker/client.js +0 -2
- package/dist/serve/worker/client.js.map +1 -1
- package/dist/serve/worker/entry.js +2 -2
- package/dist/serve/worker/entry.js.map +1 -1
- package/dist/serve/worker/host/dispatch.d.ts +2 -0
- package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
- package/dist/serve/worker/host/dispatch.js +24 -2
- package/dist/serve/worker/host/dispatch.js.map +1 -1
- package/dist/serve/worker/host/rtdb.d.ts +6 -2
- package/dist/serve/worker/host/rtdb.d.ts.map +1 -1
- package/dist/serve/worker/host/rtdb.js +224 -2
- package/dist/serve/worker/host/rtdb.js.map +1 -1
- package/dist/serve/worker/host/studio.d.ts.map +1 -1
- package/dist/serve/worker/host/studio.js +2 -0
- package/dist/serve/worker/host/studio.js.map +1 -1
- package/dist/serve/worker/host/subscriptions.d.ts.map +1 -1
- package/dist/serve/worker/host/subscriptions.js +3 -3
- package/dist/serve/worker/host/subscriptions.js.map +1 -1
- package/dist/serve/worker/host.d.ts +1 -1
- package/dist/serve/worker/host.d.ts.map +1 -1
- package/dist/serve/worker/host.js +1 -1
- package/dist/serve/worker/host.js.map +1 -1
- package/dist/serve/worker/index.d.ts +16 -1
- package/dist/serve/worker/index.d.ts.map +1 -1
- package/dist/serve/worker/index.js +17 -4
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/protocol.d.ts +57 -0
- package/dist/serve/worker/protocol.d.ts.map +1 -1
- package/dist/serve/worker/protocol.js.map +1 -1
- package/dist/serve/worker/rtdb-value-equality.d.ts +3 -0
- package/dist/serve/worker/rtdb-value-equality.d.ts.map +1 -0
- package/dist/serve/worker/rtdb-value-equality.js +18 -0
- package/dist/serve/worker/rtdb-value-equality.js.map +1 -0
- package/dist/serve/worker/serve-init.js +2 -2
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/dist/serve/worker/service-worker-relay.js +2 -2
- package/dist/serve/worker/service-worker-relay.js.map +1 -1
- package/package.json +7 -5
- package/src/assurance/.generated/conformance-verdicts.ts +120 -75
- package/src/bridge/client/dispatch.ts +1 -1
- package/src/cli/serve.ts +215 -307
- package/src/cli/service-command-records/database-rules-generate.ts +3 -0
- package/src/cli/service-command-records/database-rules-lint.ts +3 -0
- package/src/cli/service-command-records/database-rules-simulate.ts +3 -0
- package/src/cli/service-command-records/database-rules-validate.ts +3 -0
- package/src/cli/service-command-records/firestore-indexes-generate.ts +3 -0
- package/src/cli/service-command-records/firestore-rules-lint.ts +3 -0
- package/src/cli/service-command-records/firestore-rules-resolve.ts +3 -0
- package/src/cli/service-command-records/firestore-rules-simulate.ts +3 -0
- package/src/cli/service-command-records/firestore-rules-validate.ts +3 -0
- package/src/cli/service-command-records/storage-rules-lint.ts +3 -0
- package/src/cli/service-command-records/storage-rules-simulate.ts +3 -0
- package/src/cli/service-commands.generated.ts +27 -0
- package/src/cli/service-commands.test.ts +43 -0
- package/src/cli/service-commands.ts +36 -51
- package/src/conformance/.generated/can-i-use-browser.ts +1 -1
- package/src/conformance/.generated/can-i-use.ts +1 -1
- package/src/conformance/.generated/conformance-docs.ts +1 -1
- package/src/functions-rtdb/development-runtime.ts +299 -0
- package/src/serve/bridge-mount.ts +253 -19
- package/src/serve/bundler.ts +8 -34
- package/src/serve/entries/app-client.ts +5 -4
- package/src/serve/entries/auth-helper-core.ts +117 -30
- package/src/serve/entries/auth.ts +8 -4
- package/src/serve/entries/database.ts +180 -57
- package/src/serve/entries/init.ts +30 -20
- package/src/serve/html-injection.ts +65 -0
- package/src/serve/namespace.ts +26 -169
- package/src/serve/runtime/worker-replacement.ts +1 -1
- package/src/serve/sandbox-session.ts +233 -0
- package/src/serve/server.ts +20 -5
- package/src/serve/site-tree.ts +146 -0
- package/src/serve/standalone-assets.ts +9 -26
- package/src/serve/vite-functions-development.ts +201 -0
- package/src/serve/vite-generation-bridge.ts +66 -0
- package/src/serve/vite-generation-functions.ts +78 -0
- package/src/serve/vite-generation-middleware.ts +56 -0
- package/src/serve/vite-generation-rules-watch.ts +37 -0
- package/src/serve/vite-module-swap.ts +119 -0
- package/src/serve/vite-page-runtime.ts +100 -0
- package/src/serve/vite-plugin.ts +78 -883
- package/src/serve/vite-sandbox-generation.ts +255 -0
- package/src/serve/worker/client/disconnect.ts +3 -1
- package/src/serve/worker/client/handles.ts +5 -0
- package/src/serve/worker/client/pagehide.ts +31 -0
- package/src/serve/worker/client/rtdb-admin.ts +74 -0
- package/src/serve/worker/client/rtdb-connection-lifecycle.ts +52 -0
- package/src/serve/worker/client/rtdb-controls.ts +8 -0
- package/src/serve/worker/client/rtdb-listeners.ts +337 -0
- package/src/serve/worker/client/rtdb-reads.ts +12 -0
- package/src/serve/worker/client/rtdb-references.ts +85 -0
- package/src/serve/worker/client/rtdb-snapshots.ts +118 -0
- package/src/serve/worker/client/rtdb-transactions.ts +51 -0
- package/src/serve/worker/client/rtdb-writes.ts +74 -0
- package/src/serve/worker/client.ts +0 -2
- package/src/serve/worker/entry.ts +2 -2
- package/src/serve/worker/host/dispatch.ts +22 -2
- package/src/serve/worker/host/rtdb.ts +243 -2
- package/src/serve/worker/host/studio.ts +2 -0
- package/src/serve/worker/host/subscriptions.ts +8 -4
- package/src/serve/worker/host.ts +1 -1
- package/src/serve/worker/index.ts +58 -10
- package/src/serve/worker/protocol.ts +23 -2
- package/src/serve/worker/rtdb-value-equality.ts +17 -0
- package/src/serve/worker/serve-init.ts +2 -2
- package/src/serve/worker/service-worker-relay.ts +2 -2
- package/dist/serve/docs-ui/_astro/_slug_.DUci-duz.css +0 -1
- package/dist/serve/docs-ui/docs/_rhythm/index.html +0 -100
- package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +0 -43
- package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +0 -26
- package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +0 -70
- package/dist/serve/docs-ui/docs/api-reference/index.html +0 -68
- package/dist/serve/docs-ui/docs/build/ai-logic/index.html +0 -64
- package/dist/serve/docs-ui/docs/build/authentication/index.html +0 -66
- package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +0 -70
- package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +0 -71
- package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +0 -66
- package/dist/serve/docs-ui/docs/build/realtime-database/index.html +0 -67
- package/dist/serve/docs-ui/docs/conformance-scores/index.html +0 -50
- package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +0 -531
- package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +0 -73
- package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +0 -29
- package/dist/serve/docs-ui/docs/get-started/start-building/index.html +0 -33
- package/dist/serve/docs-ui/docs/messaging-compat/index.html +0 -265
- package/dist/serve/docs-ui/docs/observe/resolve-runtime-status/index.html +0 -28
- package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +0 -74
- package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +0 -45
- package/dist/serve/docs-ui/docs/overview/index.html +0 -17
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +0 -186
- package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +0 -318
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +0 -160
- package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +0 -425
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +0 -60
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +0 -507
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +0 -258
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +0 -51
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +0 -308
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +0 -68
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +0 -11
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +0 -126
- package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +0 -1852
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +0 -509
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +0 -182
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +0 -121
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +0 -203
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +0 -639
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +0 -100
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +0 -24
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +0 -136
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +0 -16
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +0 -176
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +0 -188
- package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +0 -51
- package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +0 -106
- package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +0 -41
- package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +0 -67
- package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +0 -159
- package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +0 -47
- package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +0 -95
- package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +0 -82
- package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +0 -37
- package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +0 -75
- package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +0 -132
- package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +0 -14
- package/dist/serve/docs-ui/index.html +0 -1
- package/dist/serve/studio-ui/assets/RulesCodeEditor-BDlH-5lp.js +0 -23
- package/dist/serve/studio-ui/assets/index-Bf9SSE8L.js +0 -1218
- package/dist/serve/studio-ui/assets/index-BlSGru_r.css +0 -1
- package/dist/serve/studio-ui/assets/seed-D_UjxfOU.js +0 -20
- package/dist/serve/studio-ui/index.html +0 -32
- package/dist/serve/worker/client/rtdb.d.ts +0 -36
- package/dist/serve/worker/client/rtdb.d.ts.map +0 -1
- package/dist/serve/worker/client/rtdb.js +0 -241
- package/dist/serve/worker/client/rtdb.js.map +0 -1
- package/src/serve/worker/client/rtdb.ts +0 -311
- /package/dist/serve/{docs-ui → site-ui}/404.html +0 -0
- /package/dist/serve/{docs-ui → site-ui}/_astro/_slug_.CXh9yTP1.css +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/_rhythm.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/agent/set-up-your-agent.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/agent/watch-and-review.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/agent/work-with-an-agent.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/ai-compat.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/api-reference.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/app-compat.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/auth-compat.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/ai-logic.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/authentication.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-firestore.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-messaging.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/realtime-database.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/create-pyric-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/functions-rtdb-compat.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/get-started/how-the-swap-works.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/get-started/start-building.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/index.html +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/observe/resolve-runtime-status.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/observe/see-whats-happening.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/observe/shape-your-data.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/overview.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-app-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-storage-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-scripting-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-app-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-browser-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-browser-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-docs-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-credentials-node-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-register-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-sw-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-database-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-firestore-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-agents-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/audit-your-rules.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/firestore-rules-limits.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/read-a-denial.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/rtdb-rules-in-typescript.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/secure-it-with-rules.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/simulate-and-lint.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/write-a-rules-test-suite.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/ship/ship-to-production.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/ship/test-in-node.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/trust/how-we-know-it-matches-firebase.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/trust/versioning-and-compatibility.md +0 -0
- /package/dist/serve/{studio-ui → site-ui}/pyric-logo.svg +0 -0
|
@@ -1,92 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `@pyric/cli/vite` — the firebase→pyric-sandbox swap as a Vite plugin.
|
|
3
|
-
*
|
|
4
|
-
* The serve analog for SOURCE-driven apps: instead of `vite build && pyric dev
|
|
5
|
-
* dist`, a team keeps `vite dev` (HMR, source maps) with the in-process sandbox
|
|
6
|
-
* standing in for Firebase. The app's `firebase/*` imports are UNCHANGED — the
|
|
7
|
-
* plugin swaps them at the module-resolution layer (`resolveId`), the same way
|
|
8
|
-
* `pyric dev` swaps via a runtime import map. (Design: `plans/pyric-vite-plugin.md`.)
|
|
9
|
-
*
|
|
10
|
-
* Two flavors, one `apply` function. Under `vite dev` the swap is ALWAYS on.
|
|
11
|
-
* For `vite build` the swap is MODE-gated: a plain `vite build` (mode
|
|
12
|
-
* `production`) ships the real `firebase` package — the swap never reaches the
|
|
13
|
-
* prod artifact — while `vite build --mode development` (any NON-production
|
|
14
|
-
* mode) produces a SANDBOX build that bundles pyric's in-page adapters instead
|
|
15
|
-
* of the real SDK: self-contained, meant to be previewed under `pyric dev`, and
|
|
16
|
-
* stamped with the sandbox-build marker so it can never be deployed (`pyric
|
|
17
|
-
* deploy hosting` refuses it). `pyric({ swapInBuild })` forces the build
|
|
18
|
-
* behavior on/off regardless of mode. See `sandbox-marker.ts`.
|
|
19
|
-
*
|
|
20
|
-
* This is a thin adapter over serve's proven machinery. It REUSES, not reimplements:
|
|
21
|
-
* - the node-builtin shims — `NODE_BUILTIN_SHIMS`;
|
|
22
|
-
* - the swap targets — `defaultSdkEntries()` (the `serve/entries/*` wrappers,
|
|
23
|
-
* compiled-dist preferred, src fallback);
|
|
24
|
-
* - the `/__pyric/*` namespace — `createPyricNamespace` mounted verbatim behind
|
|
25
|
-
* a connect-middleware adapter;
|
|
26
|
-
* - rules load + prepare — `loadProjectRules` / `prepareRulesSource`;
|
|
27
|
-
* - the SharedWorker host — `bundleWorker` served at `/__pyric/sdk/worker.js`;
|
|
28
|
-
* - durable stores — `createStateStore` (persist) / `createCaptureStore`.
|
|
29
|
-
*
|
|
30
|
-
* Scope = M1 (swap + rules) + M2 (SharedWorker multi-tab + persist/capture/seed)
|
|
31
|
-
* + M3 (the MCP bridge fold — `{ bridge }`). M3 reuses `createBridgeMount` (the
|
|
32
|
-
* proven serve-flavored bridge behind `pyric dev --bridge`), composing it into
|
|
33
|
-
* the same `/__pyric` middleware; on the worker path the bridge peer routes
|
|
34
|
-
* agent tool-calls THROUGH the SharedWorker (`connectBridgePeer`), so the agent
|
|
35
|
-
* and the app share one backend without forcing the page in-page.
|
|
36
|
-
*
|
|
37
|
-
* Serving `worker.js` flips `runtime.ts` to the worker path (one backend across
|
|
38
|
-
* tabs, IndexedDB-durable); on that path the WORKER owns persist/capture/seed via
|
|
39
|
-
* the same `/__pyric/*` routes. If the worker bundle fails, the plugin falls back
|
|
40
|
-
* to the in-page sandbox (single-tab, ephemeral).
|
|
41
|
-
*/
|
|
42
|
-
import { readFile } from 'node:fs/promises';
|
|
43
|
-
import { existsSync, readFileSync, rmSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
44
|
-
import path from 'node:path';
|
|
45
|
-
import { SDK_MODULES, defaultSdkEntries, resolveStudioUiDir, pyricPackageRoot, NODE_BUILTIN_RE, NODE_BUILTIN_SHIMS, } from './bundler.js';
|
|
46
1
|
import { createViteWorkerRuntime } from './vite-worker-runtime.js';
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
import { readFirebaseJson, readFirebaseRc } from '../cli/firebase-json.js';
|
|
57
|
-
import { discoverFunctionsRtdbProject, } from '../functions-rtdb/project.js';
|
|
58
|
-
import { spawnFunctionsRtdbChild, } from '../functions-rtdb/child.js';
|
|
59
|
-
import { buildChildEnv, createLinePrefixer, registerModuleUrl, } from '../cli/dev-runner.js';
|
|
60
|
-
import { loadViteAiEnv, resolveViteAiConfig, viteWorkerEpochSalt, } from './vite-ai-config.js';
|
|
61
|
-
import { resolveViteRulesConfig } from './vite-rules-source.js';
|
|
62
|
-
import { PYRIC_RUNTIME_CHIP_META, runtimeChipMetaValue, } from './runtime/chip-config.js';
|
|
63
|
-
/**
|
|
64
|
-
* Whether a `vite build` should run the firebase→pyric swap (produce a SANDBOX
|
|
65
|
-
* build). MODE-based with a plugin-config override:
|
|
66
|
-
* - `options.swapInBuild` wins outright when set (force on/off);
|
|
67
|
-
* - otherwise swap for any NON-production mode. A plain `vite build` (mode
|
|
68
|
-
* `production`) ships real firebase; `vite build --mode development` (or any
|
|
69
|
-
* custom non-prod mode) is a sandbox build.
|
|
70
|
-
* `vite dev` is handled separately in `apply` (always on).
|
|
71
|
-
*/
|
|
72
|
-
function swapsInBuild(env, swapInBuild) {
|
|
73
|
-
if (swapInBuild !== undefined)
|
|
74
|
-
return swapInBuild;
|
|
75
|
-
return env.mode !== 'production';
|
|
76
|
-
}
|
|
77
|
-
/** Any `firebase/<sub>` specifier. */
|
|
78
|
-
const FB_ANY = /^firebase\/([a-z-]+(?:\/[a-z-]+)*)$/;
|
|
79
|
-
/** The firebase subpaths with swap entries. */
|
|
80
|
-
const SERVED = new Set(SDK_MODULES.map((specifier) => specifier.slice('firebase/'.length)));
|
|
81
|
-
const entryKey = (subpath) => subpath.replaceAll('/', '-');
|
|
82
|
-
const NODE_SHIM_PREFIX = '\0pyric:node-shim:';
|
|
83
|
-
/** Walk up from a file to the nearest directory containing a package.json. */
|
|
84
|
-
function packageRootOf(file) {
|
|
85
|
-
let dir = path.dirname(file);
|
|
86
|
-
while (dir !== path.dirname(dir) && !existsSync(path.join(dir, 'package.json'))) {
|
|
87
|
-
dir = path.dirname(dir);
|
|
88
|
-
}
|
|
89
|
-
return dir;
|
|
2
|
+
import { createViteSandboxGeneration, } from './vite-sandbox-generation.js';
|
|
3
|
+
import { createViteModuleContext, createViteModuleSwap } from './vite-module-swap.js';
|
|
4
|
+
import { createVitePageRuntime } from './vite-page-runtime.js';
|
|
5
|
+
function resolveFunctionsOptions(options) {
|
|
6
|
+
if (options === false)
|
|
7
|
+
return false;
|
|
8
|
+
if (typeof options === 'object')
|
|
9
|
+
return options;
|
|
10
|
+
return {};
|
|
90
11
|
}
|
|
91
12
|
/**
|
|
92
13
|
* The dev-only Vite plugin. Add to `vite.config`:
|
|
@@ -95,102 +16,22 @@ function packageRootOf(file) {
|
|
|
95
16
|
* export default defineConfig({ plugins: [pyric()] });
|
|
96
17
|
*/
|
|
97
18
|
export function pyric(options = {}) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const entries = defaultSdkEntries(); // { app, auth, firestore, init } → abs paths
|
|
102
|
-
const pyricRoot = pyricPackageRoot();
|
|
103
|
-
// The @pyric/cli package root — covers the served entries AND their siblings
|
|
104
|
-
// (`worker/client.js`, the bridge client) that the entries statically import.
|
|
105
|
-
const cliRoot = packageRootOf(entries.init);
|
|
106
|
-
// section 8 refinement: a firebase import is "pyric-internal" iff its importer lives
|
|
107
|
-
// under the resolved pyric package root — keyed on the root, not a `/pyric/`
|
|
108
|
-
// substring (which a user project path could false-positive).
|
|
109
|
-
const isPyricImporter = (importer) => {
|
|
110
|
-
if (!importer)
|
|
111
|
-
return false;
|
|
112
|
-
const f = importer.split('?')[0];
|
|
113
|
-
return f === pyricRoot || f.startsWith(pyricRoot + path.sep);
|
|
114
|
-
};
|
|
115
|
-
// Node builtins are reached only from OUR code (pyric internals + the served
|
|
116
|
-
// entries) — shim those, but NEVER hijack a user app or third-party library's
|
|
117
|
-
// own `fs`/`path`/`url` (which Vite, or the user's polyfill plugin, should
|
|
118
|
-
// resolve). The firebase branch stays scoped to pyric; this is the wider "ours".
|
|
119
|
-
const isOurCode = (importer) => {
|
|
120
|
-
if (!importer)
|
|
121
|
-
return false;
|
|
122
|
-
if (isPyricImporter(importer))
|
|
123
|
-
return true;
|
|
124
|
-
const f = importer.split('?')[0];
|
|
125
|
-
return f === cliRoot || f.startsWith(cliRoot + path.sep);
|
|
126
|
-
};
|
|
127
|
-
const shimFor = (spec) => NODE_BUILTIN_SHIMS[spec.replace(/^node:/, '')];
|
|
128
|
-
// The esbuild mirror for Vite's dep optimizer — REQUIRED so a node_modules
|
|
129
|
-
// library's `firebase/*` swaps too (the optimizer's esbuild pass bypasses the
|
|
130
|
-
// Rollup-pipeline resolveId below and would otherwise pre-bake real firebase).
|
|
131
|
-
const esbuildMirror = {
|
|
132
|
-
name: 'pyric-sandbox-optimizer',
|
|
133
|
-
setup(build) {
|
|
134
|
-
build.onResolve({ filter: FB_ANY }, (args) => {
|
|
135
|
-
const sub = FB_ANY.exec(args.path)[1];
|
|
136
|
-
if (SERVED.has(sub))
|
|
137
|
-
return { path: entries[entryKey(sub)] };
|
|
138
|
-
return null; // non-served firebase from a lib → real firebase
|
|
139
|
-
});
|
|
140
|
-
build.onResolve({ filter: NODE_BUILTIN_RE }, (args) => {
|
|
141
|
-
if (!isOurCode(args.importer))
|
|
142
|
-
return null; // user/lib node builtins → Vite/their polyfill
|
|
143
|
-
return { path: args.path.replace(/^node:/, ''), namespace: 'pyric-node-shim' };
|
|
144
|
-
});
|
|
145
|
-
build.onLoad({ filter: /.*/, namespace: 'pyric-node-shim' }, (args) => ({
|
|
146
|
-
contents: NODE_BUILTIN_SHIMS[args.path],
|
|
147
|
-
loader: 'js',
|
|
148
|
-
}));
|
|
149
|
-
},
|
|
150
|
-
};
|
|
151
|
-
// Live rules box — the watcher swaps it; the init payload always serves the
|
|
152
|
-
// current version.
|
|
153
|
-
const live = {
|
|
154
|
-
rules: null,
|
|
155
|
-
rulesHash: null,
|
|
156
|
-
databaseRules: null,
|
|
157
|
-
databaseRulesHash: null,
|
|
158
|
-
databaseUrl: null,
|
|
159
|
-
storageRules: null,
|
|
160
|
-
storageRulesHash: null,
|
|
161
|
-
};
|
|
162
|
-
// M2: the SharedWorker bundle's content hash (sync) — stamped into the page so
|
|
163
|
-
// a still-running OLD worker is detected as stale. The collaborator becomes
|
|
164
|
-
// ready once its bundle succeeds; until then (or on bundle failure) the page
|
|
165
|
-
// is forced onto the in-page sandbox path. transformIndexHtml reads its tag.
|
|
19
|
+
const moduleContext = createViteModuleContext();
|
|
20
|
+
const moduleSwap = createViteModuleSwap(moduleContext);
|
|
21
|
+
const { entries, cliRoot } = moduleContext;
|
|
166
22
|
const workerRuntime = createViteWorkerRuntime();
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
// which is a separately-bundled second runtime copy (the double-init bug:
|
|
178
|
-
// two banners, two bridge registrations). `pyric dev` sees the marker and
|
|
179
|
-
// skips its injection for these pages (see injectServeTags).
|
|
180
|
-
let initChunkRef;
|
|
181
|
-
let initChunkFile;
|
|
182
|
-
// M3 bridge fold: normalize `bridge` once (true ⇒ `{}`, falsy ⇒ null). When
|
|
183
|
-
// on, the MCP mount is composed into the /__pyric middleware (createBridgeMount,
|
|
184
|
-
// shared with `pyric dev --bridge`) AND the page is forced onto the in-page
|
|
185
|
-
// sandbox path — the bridge peer is the in-page sandbox, never the SharedWorker,
|
|
186
|
-
// so multi-tab is disabled under bridge to keep agent + app on one backend.
|
|
23
|
+
const studioEnabled = options.ui !== false;
|
|
24
|
+
const pageRuntimeInput = {
|
|
25
|
+
options,
|
|
26
|
+
studioEnabled,
|
|
27
|
+
initEntry: entries.init,
|
|
28
|
+
workerRuntime,
|
|
29
|
+
};
|
|
30
|
+
const pageRuntime = createVitePageRuntime(pageRuntimeInput);
|
|
31
|
+
// Normalize the public bridge shorthand once. The active generation owns the
|
|
32
|
+
// bridge/session attachment and routes the peer through the SharedWorker.
|
|
187
33
|
const bridgeOpts = options.bridge === true ? {} : options.bridge || null;
|
|
188
|
-
|
|
189
|
-
// to the worker host via the init payload (→ ctx.aiEngine) AND to the in-page
|
|
190
|
-
// fallback via an injected synchronous global (see transformIndexHtml).
|
|
191
|
-
// An explicit engine is available immediately (some hook tests call the HTML
|
|
192
|
-
// transform directly); Vite's config hook may otherwise select the simple
|
|
193
|
-
// PYRIC_AI_MODEL environment path for the active mode/root.
|
|
34
|
+
let activeGeneration = null;
|
|
194
35
|
return {
|
|
195
36
|
name: 'pyric:sandbox',
|
|
196
37
|
// Active for `vite dev` ALWAYS, and for `vite build` only when it is a
|
|
@@ -201,643 +42,57 @@ export function pyric(options = {}) {
|
|
|
201
42
|
// `pyric dev`, never deploy it).
|
|
202
43
|
apply(config, env) {
|
|
203
44
|
void config;
|
|
204
|
-
|
|
205
|
-
return true;
|
|
206
|
-
return swapsInBuild(env, options.swapInBuild);
|
|
45
|
+
return pageRuntime.applies(env);
|
|
207
46
|
},
|
|
208
47
|
enforce: 'pre',
|
|
209
48
|
config(config, env) {
|
|
210
|
-
sandboxBuild = env.command === 'build';
|
|
211
|
-
const loadedEnv = loadViteAiEnv(env.mode, config.root, config.envDir);
|
|
212
|
-
resolvedAi = resolveViteAiConfig(options.ai, loadedEnv);
|
|
213
|
-
// Cast: the `esbuild` package's `Plugin` type skews slightly from Vite's
|
|
214
|
-
// bundled esbuild types (benign — the Plugin shape is stable across the
|
|
215
|
-
// versions in range).
|
|
216
49
|
return {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
// per-importer at request time.
|
|
220
|
-
exclude: [...SDK_MODULES],
|
|
221
|
-
// The excluded SDK is served as ESM straight from dist, so Vite never
|
|
222
|
-
// scans it for dependencies. js-md5 / js-sha256 are CJS-only (no ESM
|
|
223
|
-
// named exports); without a forced pre-bundle the browser gets the raw
|
|
224
|
-
// UMD source and `import { md5 }` throws a SyntaxError. Force-including
|
|
225
|
-
// them gives the dist imports the interop-wrapped optimized copies.
|
|
226
|
-
include: ['js-md5', 'js-sha256'],
|
|
227
|
-
esbuildOptions: { plugins: [esbuildMirror] },
|
|
228
|
-
},
|
|
229
|
-
// Sandbox build only: the swapped-in runtime chunk uses TOP-LEVEL AWAIT
|
|
230
|
-
// (it deploys rules before app code runs — load-bearing, see
|
|
231
|
-
// entries/runtime.ts). Vite's default build target predates TLA and the
|
|
232
|
-
// esbuild transpile would fail. A sandbox build is a throwaway preview
|
|
233
|
-
// served under `pyric dev` (modern browser), so pin an ESNext target
|
|
234
|
-
// that keeps TLA. A plain production `vite build` never runs this plugin,
|
|
235
|
-
// so the user's own target is untouched there.
|
|
236
|
-
...(sandboxBuild ? { build: { target: 'esnext' } } : {}),
|
|
50
|
+
...moduleSwap.config(),
|
|
51
|
+
...pageRuntime.config(config, env),
|
|
237
52
|
};
|
|
238
53
|
},
|
|
239
54
|
configResolved(resolved) {
|
|
240
|
-
|
|
241
|
-
// tree live outside the app root, but setting `server.fs.allow` in config()
|
|
242
|
-
// would clobber Vite's auto-added root/workspace entries and 403 the app's
|
|
243
|
-
// own source. Push the two PACKAGE ROOTS — @pyric/cli' root (not just the
|
|
244
|
-
// entries dir) is needed because the served init entry statically imports
|
|
245
|
-
// siblings (`worker/client.js`, the bridge client) outside entries/.
|
|
246
|
-
const allow = resolved.server?.fs?.allow;
|
|
247
|
-
if (allow) {
|
|
248
|
-
for (const dir of [pyricRoot, cliRoot]) {
|
|
249
|
-
if (!allow.includes(dir))
|
|
250
|
-
allow.push(dir);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
55
|
+
moduleSwap.configResolved(resolved);
|
|
253
56
|
},
|
|
254
57
|
resolveId(source, importer) {
|
|
255
|
-
|
|
256
|
-
if (fb) {
|
|
257
|
-
const sub = fb[1];
|
|
258
|
-
if (SERVED.has(sub))
|
|
259
|
-
return entries[entryKey(sub)]; // swap served set for user/lib
|
|
260
|
-
return null; // non-served firebase from user → real firebase
|
|
261
|
-
}
|
|
262
|
-
const node = NODE_BUILTIN_RE.exec(source);
|
|
263
|
-
// Shim node builtins ONLY when reached from our own code — never hijack a
|
|
264
|
-
// user app or library's own fs/path/url (Vite/their polyfill handles those).
|
|
265
|
-
if (node && isOurCode(importer))
|
|
266
|
-
return NODE_SHIM_PREFIX + node[2];
|
|
267
|
-
return null;
|
|
58
|
+
return moduleSwap.resolveId(source, importer);
|
|
268
59
|
},
|
|
269
60
|
load(id) {
|
|
270
|
-
|
|
271
|
-
return shimFor(id.slice(NODE_SHIM_PREFIX.length));
|
|
272
|
-
return null;
|
|
61
|
+
return moduleSwap.load(id);
|
|
273
62
|
},
|
|
274
63
|
async configureServer(server) {
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
fbJson = await readFirebaseJson(cwd);
|
|
280
|
-
}
|
|
281
|
-
catch {
|
|
282
|
-
/* optional — serve without a firebase.json */
|
|
283
|
-
}
|
|
284
|
-
// Convention-first development source: an explicit option wins; otherwise
|
|
285
|
-
// an authored 2+modules file wins over firebase.json's generated deployment
|
|
286
|
-
// target. Projects without that convention retain the normal Firebase
|
|
287
|
-
// discovery path.
|
|
288
|
-
const config = resolveViteRulesConfig(cwd, options.rules, fbJson);
|
|
289
|
-
const loaded = await loadProjectRules(cwd, config);
|
|
290
|
-
const loadedDatabase = await loadProjectDatabaseRules(cwd, config);
|
|
291
|
-
const loadedStorage = await loadProjectStorageRules(cwd, config);
|
|
292
|
-
live.rules = loaded.rules;
|
|
293
|
-
live.rulesHash = loaded.rulesHash;
|
|
294
|
-
live.databaseRules = loadedDatabase.rules;
|
|
295
|
-
live.databaseRulesHash = loadedDatabase.rulesHash;
|
|
296
|
-
live.databaseUrl = loadedDatabase.databaseUrl;
|
|
297
|
-
live.storageRules = loadedStorage.rules;
|
|
298
|
-
live.storageRulesHash = loadedStorage.rulesHash;
|
|
299
|
-
// ── M2 durable stores (mirrors serve's startServe orchestration) ──────
|
|
300
|
-
// Capture (default-on): the worker/page pushes its session fixture to
|
|
301
|
-
// /__pyric/capture; the store writes .pyric/last-session.json for `pyric verify`.
|
|
302
|
-
const capture = (options.capture ?? true) ? createCaptureStore(cwd) : undefined;
|
|
303
|
-
// Persist: createStateStore IS the durable sandbox. Load eagerly so a
|
|
304
|
-
// corrupt/mismatched file fails the start (not silently ephemeral).
|
|
305
|
-
const state = options.persist ? createStateStore(cwd) : undefined;
|
|
306
|
-
if (state && options.fresh) {
|
|
307
|
-
for (const p of [state.path, state.backupPath])
|
|
308
|
-
if (existsSync(p))
|
|
309
|
-
rmSync(p);
|
|
310
|
-
server.config.logger.info(' ⓘ [pyric] fresh: discarded the existing state file; re-seeding');
|
|
311
|
-
}
|
|
312
|
-
// Eager load (mirrors serve.ts:158) — parse the file NOW so a corrupt or
|
|
313
|
-
// version-mismatched state file throws StateFileError and FAILS THE START
|
|
314
|
-
// with the actionable inspect-or-delete message. Without this the first
|
|
315
|
-
// parse is deferred into initPayload() at request time, where it throws
|
|
316
|
-
// synchronously AFTER namespace.ts has committed `writeHead(200)`: the
|
|
317
|
-
// client gets a 200 with an empty body, the page/worker swallow the JSON
|
|
318
|
-
// error, and the sandbox silently runs WITHOUT the persisted data + rules.
|
|
319
|
-
// (No-op on first run: load() returns null for a missing file.)
|
|
320
|
-
// configureServer is async, so an uncaught throw aborts the dev start.
|
|
321
|
-
if (state)
|
|
322
|
-
state.load();
|
|
323
|
-
// Seed: a "collection/doc" → fields map, OR a `pyric snapshot` state-file
|
|
324
|
-
// envelope (detected by its `version` key). Ported from serve.ts.
|
|
325
|
-
let seed = null;
|
|
326
|
-
let seedState = null;
|
|
327
|
-
let seedUsers = null;
|
|
328
|
-
if (options.seed) {
|
|
329
|
-
const seedPath = path.resolve(cwd, options.seed);
|
|
330
|
-
let parsed;
|
|
331
|
-
try {
|
|
332
|
-
parsed = JSON.parse(readFileSync(seedPath, 'utf8'));
|
|
333
|
-
}
|
|
334
|
-
catch (e) {
|
|
335
|
-
throw new Error(`@pyric/cli/vite: failed to read seed ${seedPath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
336
|
-
}
|
|
337
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
338
|
-
throw new Error('@pyric/cli/vite: seed must be a JSON object of "collection/doc" → fields');
|
|
339
|
-
}
|
|
340
|
-
const obj = parsed;
|
|
341
|
-
if (obj.version === STATE_FILE_VERSION && ('firestore' in obj || 'auth' in obj)) {
|
|
342
|
-
const fixture = obj;
|
|
343
|
-
if (state && !state.exists()) {
|
|
344
|
-
// persist first run from a fixture: prime the store, then the normal
|
|
345
|
-
// persist path restores it like any lived state.
|
|
346
|
-
if (fixture.firestore != null)
|
|
347
|
-
state.writeSection('firestore', fixture.firestore);
|
|
348
|
-
if (fixture.auth != null)
|
|
349
|
-
state.writeSection('auth', fixture.auth);
|
|
350
|
-
}
|
|
351
|
-
else if (!state) {
|
|
352
|
-
seedState = fixture.firestore ?? null;
|
|
353
|
-
seedUsers = fixture.auth?.users ?? null;
|
|
354
|
-
}
|
|
355
|
-
// persist + existing state: lived state wins; the fixture is inert.
|
|
356
|
-
}
|
|
357
|
-
else {
|
|
358
|
-
seed = parsed;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
// ── M2 SharedWorker host: bundle it (cached per version) and serve it at
|
|
362
|
-
// /__pyric/sdk/worker.js. This is what flips runtime.ts to the worker path.
|
|
363
|
-
// On bundle failure, the collaborator stays unready and its HTML tag
|
|
364
|
-
// forces the in-page sandbox.
|
|
365
|
-
try {
|
|
366
|
-
await workerRuntime.prepare(viteWorkerEpochSalt(cwd, resolvedAi.engineWire));
|
|
367
|
-
}
|
|
368
|
-
catch (e) {
|
|
369
|
-
server.config.logger.warn(` ⚠ [pyric] SharedWorker bundle failed — using the in-page sandbox (single-tab, ephemeral): ${e instanceof Error ? e.message : String(e)}`);
|
|
370
|
-
}
|
|
371
|
-
// ── Functions (RTDB triggers) — the `pyric dev` parity fold ───────────
|
|
372
|
-
// Discover the one supported Functions codebase from the same resolved
|
|
373
|
-
// firebase.json the rules used (project.ts reads it itself). Reuses the
|
|
374
|
-
// exact serve module, so absent `functions` → null (silently off) and a
|
|
375
|
-
// malformed config throws serve's own error text — which, thrown from an
|
|
376
|
-
// async configureServer, fails the dev start the same way serve's
|
|
377
|
-
// `return 2` aborts. The Functions child connects to the sandbox over the
|
|
378
|
-
// bridge WS, so a discovered codebase forces the bridge mount on (mirrors
|
|
379
|
-
// serve's `bridgeEnabledFor(..., functionsProject)`). `functions: false`
|
|
380
|
-
// is the off switch: discovery never runs, so neither does the mount.
|
|
381
|
-
const functionsOpts = typeof options.functions === 'object' ? options.functions : {};
|
|
382
|
-
let functionsProject = null;
|
|
383
|
-
if (options.functions !== false) {
|
|
384
|
-
try {
|
|
385
|
-
functionsProject = discoverFunctionsRtdbProject(cwd);
|
|
386
|
-
}
|
|
387
|
-
catch (error) {
|
|
388
|
-
// Malformed functions config: fail the start with serve's exact message.
|
|
389
|
-
throw error instanceof Error ? error : new Error(String(error));
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
const functionsProjectId = functionsProject
|
|
393
|
-
? (process.env.PYRIC_PROJECT ?? (await readFirebaseRc(cwd))?.projects?.default ?? 'demo-project')
|
|
394
|
-
: null;
|
|
395
|
-
// ── M3 MCP bridge (mirrors serve.ts:221–274) ─────────────────────────
|
|
396
|
-
// The mount is long-lived (one bridge per dev session); its MCP transport
|
|
397
|
-
// is rebuilt per request (stateless). Composed into the /__pyric middleware
|
|
398
|
-
// below (handler tier) + the server's WS upgrade. middlewareMode has no
|
|
399
|
-
// httpServer → HTTP routes still work, no WS peer.
|
|
400
|
-
// Guard the WS upgrade with the SAME allow rule Vite's own host check
|
|
401
|
-
// uses (host + allowedHosts, where `true` = opted into all hosts). Vite's
|
|
402
|
-
// upgrade path bypasses connect middleware, so this is the only guard on it.
|
|
403
|
-
const mount = bridgeOpts || functionsProject
|
|
404
|
-
? createBridgeMount({
|
|
405
|
-
...(bridgeOpts ?? {}),
|
|
406
|
-
// A functions-only session still needs a labeled bridge; prefer an
|
|
407
|
-
// explicit bridge project, else the resolved functions project id.
|
|
408
|
-
project: bridgeOpts?.project ?? functionsProjectId ?? undefined,
|
|
409
|
-
upgradeGuard: {
|
|
410
|
-
boundHost: typeof server.config.server.host === 'string' ? server.config.server.host : 'localhost',
|
|
411
|
-
allowedHosts: server.config.server.allowedHosts === true
|
|
412
|
-
? true
|
|
413
|
-
: Array.isArray(server.config.server.allowedHosts)
|
|
414
|
-
? server.config.server.allowedHosts
|
|
415
|
-
: [],
|
|
416
|
-
},
|
|
417
|
-
})
|
|
418
|
-
: null;
|
|
419
|
-
// The /__pyric/* namespace, reused VERBATIM (now with the sdk dir + state +
|
|
420
|
-
// capture routes live).
|
|
421
|
-
const events = createEventHub();
|
|
422
|
-
const initPayload = () => ({
|
|
423
|
-
rules: live.rules,
|
|
424
|
-
rulesHash: live.rulesHash,
|
|
425
|
-
databaseRules: live.databaseRules,
|
|
426
|
-
databaseRulesHash: live.databaseRulesHash,
|
|
427
|
-
databaseUrl: live.databaseUrl,
|
|
428
|
-
storageRules: live.storageRules,
|
|
429
|
-
storageRulesHash: live.storageRulesHash,
|
|
430
|
-
// Project identity: scopes the storage IDB name per served project
|
|
431
|
-
// (issue #359). Local-only — a dev path never leaves the machine.
|
|
432
|
-
projectKey: cwd,
|
|
433
|
-
// The bound port is known only after `listen`; initPayload runs per
|
|
434
|
-
// request (after listen), so resolve it lazily here. Absolute ws://host:port
|
|
435
|
-
// mirrors serve (the browser reads this as the bridge peer URL).
|
|
436
|
-
bridgeUrl: (() => {
|
|
437
|
-
if (!mount)
|
|
438
|
-
return null;
|
|
439
|
-
const addr = server.httpServer?.address();
|
|
440
|
-
const port = addr && typeof addr === 'object' ? addr.port : 0;
|
|
441
|
-
const host = (typeof server.config.server.host === 'string' && server.config.server.host) || 'localhost';
|
|
442
|
-
return port > 0 ? mount.wsUrl({ host, port }) : null;
|
|
443
|
-
})(),
|
|
444
|
-
// Precedence: once a state file exists, lived state is the truth — seed
|
|
445
|
-
// applies only on the first (state-less) run.
|
|
446
|
-
seed: state?.exists() ? null : seed,
|
|
447
|
-
seedState,
|
|
448
|
-
persist: Boolean(state),
|
|
449
|
-
capture: Boolean(capture),
|
|
450
|
-
authUsers: state
|
|
451
|
-
? (state.readSection('auth')?.users ?? null)
|
|
452
|
-
: seedUsers,
|
|
453
|
-
// Messaging is part of the canonical firebase/* sandbox swap.
|
|
454
|
-
messaging: true,
|
|
455
|
-
// Plugin-level engine → the worker host's ctx.aiEngine (host-ai.ts),
|
|
456
|
-
// which wins over any op-carried engine. Null when unset.
|
|
457
|
-
ai: resolvedAi.engineWire ? { engine: resolvedAi.engineWire } : null,
|
|
458
|
-
});
|
|
459
|
-
// Pyric Studio: mount the disk-backed workspace/project routes that
|
|
460
|
-
// Studio's `local` mode talks to + serve the built Studio app at
|
|
461
|
-
// /__pyric/ui/. Mirrors `pyric dev --ui`; the studio-ui assets are
|
|
462
|
-
// vendored in this package's dist (resolveStudioUiDir).
|
|
463
|
-
//
|
|
464
|
-
// ON BY DEFAULT, including under `bridge`: the bridge now routes agent
|
|
465
|
-
// tool-calls THROUGH the SharedWorker (see `connectBridgePeer`), so the
|
|
466
|
-
// app, Studio, and agent all observe the ONE sandbox. Explicit `ui: false`
|
|
467
|
-
// still wins.
|
|
64
|
+
const priorGeneration = activeGeneration;
|
|
65
|
+
activeGeneration = null;
|
|
66
|
+
await priorGeneration?.close();
|
|
67
|
+
const projectDir = options.root ?? server.config.root;
|
|
468
68
|
const uiEnabled = options.ui ?? true;
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
:
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
'(run the full build, or reinstall @pyric/cli).');
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
const { sdkDir } = workerRuntime.status();
|
|
484
|
-
const namespace = createPyricNamespace({
|
|
485
|
-
sdkDir,
|
|
486
|
-
initPayload,
|
|
487
|
-
events,
|
|
488
|
-
activity: (incident) => server.config.logger.warn(formatActivityWarning(incident)),
|
|
489
|
-
state,
|
|
490
|
-
capture,
|
|
491
|
-
studio,
|
|
492
|
-
studioUiDir,
|
|
493
|
-
// `ai.proxyUpstream`: what `/__pyric/ai-proxy` forwards to (beats the
|
|
494
|
-
// PYRIC_AI_PROXY_UPSTREAM env var; falls back to the default when unset).
|
|
495
|
-
aiProxyUpstream: resolvedAi.proxyUpstream,
|
|
496
|
-
// Adapt Vite's logger to the plain info/note shape the namespace's
|
|
497
|
-
// diagnostics (denial relay, future hot-reload lines) expect —
|
|
498
|
-
// matches the `↻`/`⚠ [pyric]` lines already logged elsewhere in this
|
|
499
|
-
// plugin via `server.config.logger` directly.
|
|
500
|
-
logger: {
|
|
501
|
-
info: (m) => server.config.logger.info(m),
|
|
502
|
-
note: (m) => server.config.logger.warn(m),
|
|
503
|
-
},
|
|
504
|
-
});
|
|
505
|
-
// DNS-rebinding guard for the /__pyric/* surface. Vite has its own host
|
|
506
|
-
// check, but a `configureServer` hook that doesn't return a function mounts
|
|
507
|
-
// BEFORE it (and the ordering differs across Vite 5/6/7), so guard here too
|
|
508
|
-
// — independent of Vite's internals. Reuses serve's `isAllowedHost`.
|
|
509
|
-
const srvOpts = server.config.server;
|
|
510
|
-
const hostAllowed = (req) => {
|
|
511
|
-
if (srvOpts.allowedHosts === true)
|
|
512
|
-
return true; // user opted into all hosts
|
|
513
|
-
const boundHost = typeof srvOpts.host === 'string' ? srvOpts.host : 'localhost';
|
|
514
|
-
const extra = Array.isArray(srvOpts.allowedHosts) ? srvOpts.allowedHosts : [];
|
|
515
|
-
return isAllowedHost(req.headers.host, boundHost, extra);
|
|
69
|
+
const functionsOptions = resolveFunctionsOptions(options.functions);
|
|
70
|
+
const ai = pageRuntime.ai();
|
|
71
|
+
const generationOptions = {
|
|
72
|
+
rules: options.rules,
|
|
73
|
+
seed: options.seed,
|
|
74
|
+
persist: options.persist,
|
|
75
|
+
fresh: options.fresh,
|
|
76
|
+
capture: options.capture,
|
|
77
|
+
bridge: bridgeOpts,
|
|
78
|
+
ui: uiEnabled,
|
|
79
|
+
functions: functionsOptions,
|
|
516
80
|
};
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
if (!handled)
|
|
533
|
-
next();
|
|
534
|
-
})
|
|
535
|
-
.catch((err) => {
|
|
536
|
-
if (!res.headersSent)
|
|
537
|
-
res.statusCode = 500;
|
|
538
|
-
res.end(err instanceof Error ? err.message : String(err));
|
|
539
|
-
});
|
|
540
|
-
});
|
|
541
|
-
// WS upgrade for the in-page sandbox peer (ws://…/__pyric/sandbox). The
|
|
542
|
-
// listener only fires once upgrades arrive (after listen), so adding it in
|
|
543
|
-
// configureServer is safe. middlewareMode has no httpServer → HTTP bridge
|
|
544
|
-
// routes still work, just no WS peer.
|
|
545
|
-
// Cast: Vite types `httpServer` as http.Server | http2.Http2SecureServer;
|
|
546
|
-
// attachUpgrade only needs `.on('upgrade')`, present on both. (serve passes
|
|
547
|
-
// a plain http.Server, so this widening is plugin-specific.)
|
|
548
|
-
if (mount && server.httpServer)
|
|
549
|
-
mount.attachUpgrade(server.httpServer);
|
|
550
|
-
// A2 discovery pointer: the stdio `mcp-proxy` (the sanctioned Claude Code
|
|
551
|
-
// entrypoint) reads `.pyric/serve.json` to find the bridge without a fixed
|
|
552
|
-
// URL -- it takes the PORT and probes BOTH loopback families, defeating the
|
|
553
|
-
// IPv6/IPv4 trap that broke the hand-written `.mcp.json`. serve writes this
|
|
554
|
-
// pointer; the Vite plugin must too. Written after listen (port known),
|
|
555
|
-
// removed on close.
|
|
556
|
-
if (mount && server.httpServer) {
|
|
557
|
-
const httpServer = server.httpServer;
|
|
558
|
-
const pointer = path.join(cwd, '.pyric', 'serve.json');
|
|
559
|
-
const host = (typeof server.config.server.host === 'string' && server.config.server.host) || 'localhost';
|
|
560
|
-
const writePointer = () => {
|
|
561
|
-
const addr = httpServer.address();
|
|
562
|
-
const port = addr && typeof addr === 'object' ? addr.port : 0;
|
|
563
|
-
if (!port)
|
|
564
|
-
return;
|
|
565
|
-
try {
|
|
566
|
-
mkdirSync(path.dirname(pointer), { recursive: true });
|
|
567
|
-
writeFileSync(pointer, JSON.stringify({
|
|
568
|
-
url: `http://${host}:${port}`,
|
|
569
|
-
mcpUrl: mount.mcpUrl({ host, port }),
|
|
570
|
-
port,
|
|
571
|
-
pid: process.pid,
|
|
572
|
-
instanceId: mount.instanceId,
|
|
573
|
-
project: bridgeOpts?.project ?? 'sandbox',
|
|
574
|
-
}, null, 2) + '\n');
|
|
575
|
-
}
|
|
576
|
-
catch {
|
|
577
|
-
/* best-effort: the proxy falls back to a port scan */
|
|
578
|
-
}
|
|
579
|
-
};
|
|
580
|
-
// Cross-family collision guard: once listening, probe BOTH loopback
|
|
581
|
-
// families on our port. If a DIFFERENT sandbox answers on the other
|
|
582
|
-
// family, two dev servers are colliding (IPv4 `*:P` + IPv6 `[::1]:P`)
|
|
583
|
-
// and the agent/browser can split across them (writes seem to vanish).
|
|
584
|
-
// #697's dual-bind can't apply here — Vite owns the single listen — so
|
|
585
|
-
// we can only warn, loudly. (Our own family answers with our instanceId
|
|
586
|
-
// and is skipped; a dual-stack bind owns both and never trips this.)
|
|
587
|
-
const warnOnCollision = async () => {
|
|
588
|
-
const a = httpServer.address();
|
|
589
|
-
const p = a && typeof a === 'object' ? a.port : 0;
|
|
590
|
-
if (!p)
|
|
591
|
-
return;
|
|
592
|
-
for (const probe of [`http://127.0.0.1:${p}`, `http://[::1]:${p}`]) {
|
|
593
|
-
try {
|
|
594
|
-
const res = await fetch(`${probe}/__pyric/health`, { signal: AbortSignal.timeout(1000) });
|
|
595
|
-
if (res.status !== 200)
|
|
596
|
-
continue;
|
|
597
|
-
const body = (await res.json());
|
|
598
|
-
if (body.mode === 'sandbox' && body.instanceId && body.instanceId !== mount.instanceId) {
|
|
599
|
-
server.config.logger.warn(`\n⚠ pyric: another sandbox already serves port ${p} on a different loopback ` +
|
|
600
|
-
`family (${probe}). Two dev servers are colliding across IPv4/IPv6 — your MCP ` +
|
|
601
|
-
`agent and browser can land on DIFFERENT sandboxes (writes seem to vanish). ` +
|
|
602
|
-
`Stop the other server, or give this app a unique \`server.port\` so the two ` +
|
|
603
|
-
`don't share one (pinning server.host to a family the squatter holds would ` +
|
|
604
|
-
`just EADDRINUSE).\n`, { timestamp: true });
|
|
605
|
-
return; // one warning is enough
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
catch {
|
|
609
|
-
/* other family silent — no collision */
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
|
-
const announce = () => {
|
|
614
|
-
writePointer();
|
|
615
|
-
void warnOnCollision();
|
|
616
|
-
};
|
|
617
|
-
if (httpServer.listening)
|
|
618
|
-
announce();
|
|
619
|
-
else
|
|
620
|
-
httpServer.once('listening', announce);
|
|
621
|
-
httpServer.once('close', () => {
|
|
622
|
-
try {
|
|
623
|
-
rmSync(pointer);
|
|
624
|
-
}
|
|
625
|
-
catch {
|
|
626
|
-
/* gone already */
|
|
627
|
-
}
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
// ── Functions child lifecycle (mirrors serve's runServe) ─────────────
|
|
631
|
-
// The Functions runtime executes in an isolated node child (child.ts),
|
|
632
|
-
// exactly as `pyric dev` runs it: the child loads the user's unchanged
|
|
633
|
-
// functions module, and `--import @pyric/cli/register` + `PYRIC_SANDBOX=
|
|
634
|
-
// remote:<serveUrl>` route its `firebase-admin/app` to a RemoteSandbox that
|
|
635
|
-
// dials the bridge WS (`/__pyric/sandbox`). onValueCreated triggers observe
|
|
636
|
-
// RTDB writes and write their effects back through that one shared sandbox.
|
|
637
|
-
// Started once a sandbox peer (a browser tab / SharedWorker relay) has
|
|
638
|
-
// connected — the trigger's baseline needs a live backend — and stopped on
|
|
639
|
-
// server close. Vite restarts re-run configureServer, so the child respawns
|
|
640
|
-
// with the new server. Unlike `pyric dev` (which does not watch functions
|
|
641
|
-
// source), the plugin hot-reloads it via Vite's own watcher — see the
|
|
642
|
-
// watch block below; `functions: { watch: false }` restores dev's
|
|
643
|
-
// restart-to-reload behavior.
|
|
644
|
-
if (functionsProject && functionsProjectId && mount && server.httpServer) {
|
|
645
|
-
const httpServer = server.httpServer;
|
|
646
|
-
const project = functionsProject;
|
|
647
|
-
const projectId = functionsProjectId;
|
|
648
|
-
const bridgeMount = mount;
|
|
649
|
-
const host = (typeof server.config.server.host === 'string' && server.config.server.host) || 'localhost';
|
|
650
|
-
// Prefer the compiled child (node cannot execute the .ts source when the
|
|
651
|
-
// plugin runs from source in tests); fall back to spawnFunctionsRtdbChild's
|
|
652
|
-
// own default (correct when the plugin runs from dist in production).
|
|
653
|
-
const builtChild = path.join(cliRoot, 'dist/functions-rtdb/child.js');
|
|
654
|
-
const childModuleUrl = existsSync(builtChild) ? builtChild : undefined;
|
|
655
|
-
let functionsChild = null;
|
|
656
|
-
let disposed = false;
|
|
657
|
-
const start = async (mode = 'initial') => {
|
|
658
|
-
const addr = httpServer.address();
|
|
659
|
-
const port = addr && typeof addr === 'object' ? addr.port : 0;
|
|
660
|
-
if (!port || disposed)
|
|
661
|
-
return;
|
|
662
|
-
const serveUrl = `http://${host}:${port}`;
|
|
663
|
-
// Wait (bounded) for a sandbox peer — the SharedWorker relay / browser
|
|
664
|
-
// tab that holds the backend. Poll the mount directly (no self-fetch).
|
|
665
|
-
// On a hot reload the peer is usually still connected (the loop exits
|
|
666
|
-
// immediately); when it dropped mid-session, wait briefly rather than
|
|
667
|
-
// the full initial 30s.
|
|
668
|
-
const deadline = Date.now() + (mode === 'reload' ? 5_000 : 30_000);
|
|
669
|
-
while (!disposed && !bridgeMount.sandboxConnected()) {
|
|
670
|
-
if (Date.now() >= deadline)
|
|
671
|
-
break;
|
|
672
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
673
|
-
}
|
|
674
|
-
if (disposed)
|
|
675
|
-
return;
|
|
676
|
-
if (!bridgeMount.sandboxConnected()) {
|
|
677
|
-
server.config.logger.warn(mode === 'reload'
|
|
678
|
-
? ` ✖ [pyric] functions not restarted — no sandbox peer connected. ` +
|
|
679
|
-
`Functions stay down until the next save with ${serveUrl} open.`
|
|
680
|
-
: ` ⚠ [pyric] functions not started — no browser tab connected after 30s. ` +
|
|
681
|
-
`Open ${serveUrl} and restart the dev server.`);
|
|
682
|
-
return;
|
|
683
|
-
}
|
|
684
|
-
functionsChild = spawnFunctionsRtdbChild({
|
|
685
|
-
cwd: project.sourceDir,
|
|
686
|
-
entry: project.entry,
|
|
687
|
-
env: buildChildEnv(process.env, { serveUrl, registerUrl: registerModuleUrl() }),
|
|
688
|
-
// Precedence (per field): plugin option > env var > firebase files
|
|
689
|
-
// > default. projectId already folds PYRIC_PROJECT > .firebaserc >
|
|
690
|
-
// demo-project.
|
|
691
|
-
instance: functionsOpts.instance ?? `${projectId}-default-rtdb`,
|
|
692
|
-
location: functionsOpts.region ?? process.env.PYRIC_FUNCTIONS_RTDB_REGION ?? 'us-central1',
|
|
693
|
-
...(childModuleUrl ? { childModuleUrl } : {}),
|
|
694
|
-
onEvent(event) {
|
|
695
|
-
if (event.type === 'execution') {
|
|
696
|
-
const params = Object.entries(event.params)
|
|
697
|
-
.map(([name, value]) => `${name}=${value}`)
|
|
698
|
-
.join(', ');
|
|
699
|
-
const suffix = params ? ` (${params})` : '';
|
|
700
|
-
if (event.status === 'fulfilled') {
|
|
701
|
-
server.config.logger.info(` ✔ [pyric] function ${event.exportName} ← /${event.ref}${suffix}`);
|
|
702
|
-
}
|
|
703
|
-
else {
|
|
704
|
-
server.config.logger.error(` ✖ [pyric] function ${event.exportName} ← /${event.ref}${suffix}: ${event.error.message}`);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
else {
|
|
708
|
-
server.config.logger.error(` ✖ [pyric] functions delivery for ${event.exportName}: ${event.error.message}`);
|
|
709
|
-
}
|
|
710
|
-
},
|
|
711
|
-
});
|
|
712
|
-
const out = createLinePrefixer('[functions] ', (line) => server.config.logger.info(line.replace(/\n$/, '')));
|
|
713
|
-
const err = createLinePrefixer('[functions] ', (line) => server.config.logger.warn(line.replace(/\n$/, '')));
|
|
714
|
-
functionsChild.child.stdout?.setEncoding('utf8');
|
|
715
|
-
functionsChild.child.stderr?.setEncoding('utf8');
|
|
716
|
-
functionsChild.child.stdout?.on('data', (chunk) => out.push(chunk));
|
|
717
|
-
functionsChild.child.stderr?.on('data', (chunk) => err.push(chunk));
|
|
718
|
-
functionsChild.child.stdout?.once('end', () => out.flush());
|
|
719
|
-
functionsChild.child.stderr?.once('end', () => err.flush());
|
|
720
|
-
try {
|
|
721
|
-
const ready = await functionsChild.ready;
|
|
722
|
-
server.config.logger.info(mode === 'reload'
|
|
723
|
-
? ` ↻ [pyric] functions reloaded (${ready.triggerCount} trigger${ready.triggerCount === 1 ? '' : 's'})`
|
|
724
|
-
: ` ✔ [pyric] functions ${ready.triggerCount} onValueCreated ` +
|
|
725
|
-
`trigger${ready.triggerCount === 1 ? '' : 's'} from ${path.relative(cwd, project.entry)}`);
|
|
726
|
-
for (const unsupported of ready.unsupportedTriggers) {
|
|
727
|
-
server.config.logger.warn(` ⚠ [pyric] functions export ${unsupported.exportName} uses unsupported trigger ` +
|
|
728
|
-
`${unsupported.eventType}; it will not run.`);
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
catch (error) {
|
|
732
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
733
|
-
server.config.logger.error(mode === 'reload'
|
|
734
|
-
? // Unlike rules, last-good cannot stay live — the old child is
|
|
735
|
-
// already stopped — so a broken save takes functions down.
|
|
736
|
-
` ✖ [pyric] functions failed to reload: ${message}\n` +
|
|
737
|
-
` ✖ [pyric] functions are down until the next good save.`
|
|
738
|
-
: ` ✖ [pyric] functions failed to start: ${message}`);
|
|
739
|
-
await functionsChild.stop().catch(() => undefined);
|
|
740
|
-
functionsChild = null;
|
|
741
|
-
}
|
|
742
|
-
};
|
|
743
|
-
let reloadDebounce = null;
|
|
744
|
-
httpServer.once('close', () => {
|
|
745
|
-
disposed = true;
|
|
746
|
-
if (reloadDebounce)
|
|
747
|
-
clearTimeout(reloadDebounce);
|
|
748
|
-
void functionsChild?.stop().catch(() => undefined);
|
|
749
|
-
});
|
|
750
|
-
if (httpServer.listening)
|
|
751
|
-
void start();
|
|
752
|
-
else
|
|
753
|
-
httpServer.once('listening', () => void start());
|
|
754
|
-
// Functions hot-reload from Vite's OWN watcher (mirrors the rules block
|
|
755
|
-
// below). Restart = redeploy: stop the old child, respawn via the same
|
|
756
|
-
// start path — there is no in-place swap, so in-flight executions in the
|
|
757
|
-
// old child may drop and writes landing in the swap gap become the new
|
|
758
|
-
// child's baseline (execution.ts consumes each trigger's first observed
|
|
759
|
-
// value as baseline; they do not fire). Debounced 300ms — a save fans
|
|
760
|
-
// out several fs events and a child respawn is far heavier than a rules
|
|
761
|
-
// re-parse. Restarts are serialized: a save landing mid-restart queues
|
|
762
|
-
// exactly one follow-up run.
|
|
763
|
-
if (functionsOpts.watch !== false) {
|
|
764
|
-
const sourceDir = project.sourceDir;
|
|
765
|
-
// Usually redundant (Vite watches its root, which contains the
|
|
766
|
-
// functions dir in the common layout) but load-bearing when the
|
|
767
|
-
// functions source lives outside Vite's root. node_modules stays
|
|
768
|
-
// ignored: Vite's watcher ignores `**/node_modules/**` globally, and
|
|
769
|
-
// the handler below filters it again for explicitly-added trees.
|
|
770
|
-
server.watcher.add(sourceDir);
|
|
771
|
-
let restarting = false;
|
|
772
|
-
let queued = false;
|
|
773
|
-
const restart = async () => {
|
|
774
|
-
if (restarting) {
|
|
775
|
-
queued = true;
|
|
776
|
-
return;
|
|
777
|
-
}
|
|
778
|
-
restarting = true;
|
|
779
|
-
try {
|
|
780
|
-
do {
|
|
781
|
-
queued = false;
|
|
782
|
-
if (disposed)
|
|
783
|
-
return;
|
|
784
|
-
const old = functionsChild;
|
|
785
|
-
functionsChild = null;
|
|
786
|
-
if (old)
|
|
787
|
-
await old.stop().catch(() => undefined);
|
|
788
|
-
await start('reload');
|
|
789
|
-
} while (queued && !disposed);
|
|
790
|
-
}
|
|
791
|
-
finally {
|
|
792
|
-
restarting = false;
|
|
793
|
-
}
|
|
794
|
-
};
|
|
795
|
-
const onFunctionsFsEvent = (file) => {
|
|
796
|
-
const resolved = path.resolve(file);
|
|
797
|
-
const rel = path.relative(sourceDir, resolved);
|
|
798
|
-
if (rel === '' || rel.startsWith('..') || path.isAbsolute(rel))
|
|
799
|
-
return;
|
|
800
|
-
if (rel.split(path.sep).includes('node_modules'))
|
|
801
|
-
return;
|
|
802
|
-
if (reloadDebounce)
|
|
803
|
-
clearTimeout(reloadDebounce);
|
|
804
|
-
reloadDebounce = setTimeout(() => void restart(), 300);
|
|
805
|
-
};
|
|
806
|
-
server.watcher.on('change', onFunctionsFsEvent);
|
|
807
|
-
server.watcher.on('add', onFunctionsFsEvent);
|
|
808
|
-
server.watcher.on('unlink', onFunctionsFsEvent);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
// Rules hot-reload from Vite's OWN watcher (no second fs watcher). Reuse
|
|
812
|
-
// prepareRulesSource (resolve + lint); last-good stays live on a broken save.
|
|
813
|
-
// Debounced (editors emit several change events per save) — matches
|
|
814
|
-
// watchProjectRules' 150ms cadence, which we can't reuse here (it opens its
|
|
815
|
-
// own fs watcher).
|
|
816
|
-
if (loaded.sourcePath) {
|
|
817
|
-
const rulesFile = loaded.sourcePath;
|
|
818
|
-
let debounce = null;
|
|
819
|
-
server.watcher.add(rulesFile);
|
|
820
|
-
server.watcher.on('change', (file) => {
|
|
821
|
-
if (path.resolve(file) !== path.resolve(rulesFile))
|
|
822
|
-
return;
|
|
823
|
-
if (debounce)
|
|
824
|
-
clearTimeout(debounce);
|
|
825
|
-
debounce = setTimeout(() => {
|
|
826
|
-
void readFile(rulesFile, 'utf8').then((raw) => {
|
|
827
|
-
try {
|
|
828
|
-
const rules = prepareRulesSource(raw, rulesFile);
|
|
829
|
-
live.rules = rules;
|
|
830
|
-
live.rulesHash = rulesHashOf(rules);
|
|
831
|
-
events.broadcast('rules-changed', { rules, rulesHash: live.rulesHash });
|
|
832
|
-
server.config.logger.info(` ↻ [pyric] rules reloaded (${live.rulesHash})`);
|
|
833
|
-
}
|
|
834
|
-
catch (e) {
|
|
835
|
-
server.config.logger.warn(` ⚠ [pyric] rules NOT reloaded (last-good stays live): ${e instanceof Error ? e.message : String(e)}`);
|
|
836
|
-
}
|
|
837
|
-
}, () => { });
|
|
838
|
-
}, 150);
|
|
839
|
-
});
|
|
840
|
-
}
|
|
81
|
+
const generationInput = {
|
|
82
|
+
server,
|
|
83
|
+
projectDir,
|
|
84
|
+
cliRoot,
|
|
85
|
+
workerRuntime,
|
|
86
|
+
options: generationOptions,
|
|
87
|
+
ai,
|
|
88
|
+
};
|
|
89
|
+
const generation = await createViteSandboxGeneration(generationInput);
|
|
90
|
+
activeGeneration = generation;
|
|
91
|
+
},
|
|
92
|
+
async closeBundle() {
|
|
93
|
+
const generation = activeGeneration;
|
|
94
|
+
activeGeneration = null;
|
|
95
|
+
await generation?.close();
|
|
841
96
|
},
|
|
842
97
|
// Sandbox build only: emit the serve init entry as its own chunk. Emitted in
|
|
843
98
|
// buildStart (module graph time); its final filename is resolved in
|
|
@@ -845,70 +100,13 @@ export function pyric(options = {}) {
|
|
|
845
100
|
// BEFORE Vite's build-html plugin applies transformIndexHtml — the filename
|
|
846
101
|
// is always available when the script tag is injected below.
|
|
847
102
|
buildStart() {
|
|
848
|
-
|
|
849
|
-
initChunkRef = this.emitFile({
|
|
850
|
-
type: 'chunk',
|
|
851
|
-
id: entries.init,
|
|
852
|
-
name: 'pyric-sandbox-init',
|
|
853
|
-
});
|
|
854
|
-
}
|
|
103
|
+
pageRuntime.buildStart((chunk) => this.emitFile(chunk));
|
|
855
104
|
},
|
|
856
105
|
generateBundle() {
|
|
857
|
-
|
|
858
|
-
initChunkFile = this.getFileName(initChunkRef);
|
|
106
|
+
pageRuntime.generateBundle((referenceId) => this.getFileName(referenceId));
|
|
859
107
|
},
|
|
860
108
|
transformIndexHtml(html) {
|
|
861
|
-
|
|
862
|
-
// Sandbox BUILD: the app's own `firebase/*` imports were already swapped
|
|
863
|
-
// (resolveId, above) to pyric's in-page adapters and BUNDLED into the app
|
|
864
|
-
// chunk, and the emitted init chunk (script-tagged here) carries the
|
|
865
|
-
// runtime bootstrap + the ServeAuthHelper popup picker — rollup shares
|
|
866
|
-
// ONE runtime module between the two, so the output is fully
|
|
867
|
-
// self-contained. `pyric dev` sees the marker below and skips its own
|
|
868
|
-
// serve-time injection for this page (a second injected runtime would
|
|
869
|
-
// double-init: two banners, two bridge peers). The marker is also the
|
|
870
|
-
// signal that makes `pyric dev` trust this dist (skip the inlined-SDK
|
|
871
|
-
// scan). transformIndexHtml runs BEFORE Vite writes index.html, so both
|
|
872
|
-
// land in the emitted asset.
|
|
873
|
-
if (sandboxBuild) {
|
|
874
|
-
if (html.includes(SANDBOX_BUILD_META))
|
|
875
|
-
return html;
|
|
876
|
-
const initTag = initChunkFile
|
|
877
|
-
? `<script type="module" crossorigin src="/${initChunkFile}" data-pyric-sandbox-init></script>`
|
|
878
|
-
: '';
|
|
879
|
-
const tags = SANDBOX_BUILD_META + runtimeChipTag + initTag;
|
|
880
|
-
return html.includes('</head>')
|
|
881
|
-
? html.replace('</head>', `${tags}</head>`)
|
|
882
|
-
: tags + html;
|
|
883
|
-
}
|
|
884
|
-
const MARKER = 'data-pyric-sandbox';
|
|
885
|
-
if (html.includes(MARKER))
|
|
886
|
-
return html;
|
|
887
|
-
// Worker path (default): stamp the served worker's content hash so the page
|
|
888
|
-
// can WARN when a still-running OLD worker is stale (a SharedWorker can't
|
|
889
|
-
// hot-update). In-page path: force it via the explicit flag before the init
|
|
890
|
-
// module evaluates — a classic inline script runs before the deferred module.
|
|
891
|
-
// The flag (not nulling `window.SharedWorker`) leaves the user's own
|
|
892
|
-
// SharedWorker usage intact. We force in-page ONLY when the worker bundle
|
|
893
|
-
// failed (worker runtime unready) — the ephemeral fallback. `bridge` no longer
|
|
894
|
-
// forces in-page: the bridge peer routes agent tool-calls THROUGH the
|
|
895
|
-
// worker (see `connectBridgePeer`), so the agent shares the one sandbox the
|
|
896
|
-
// app + Studio use.
|
|
897
|
-
const head = workerRuntime.headTag(MARKER);
|
|
898
|
-
// Plugin-level engine for the IN-PAGE path: a classic inline script runs
|
|
899
|
-
// before the deferred init module AND before app code's `getAI`, so the
|
|
900
|
-
// served `getAI` (entries/ai.ts) reads it synchronously — init.json can't
|
|
901
|
-
// be awaited there. Harmless on the worker path (that branch ignores the
|
|
902
|
-
// global; the worker reads ctx.aiEngine from init.json). `<` is escaped so
|
|
903
|
-
// an engine value can never break out of the script tag.
|
|
904
|
-
const aiEngineTag = resolvedAi.engineWire
|
|
905
|
-
? `<script ${MARKER}>globalThis.__PYRIC_AI_ENGINE__=${JSON.stringify(resolvedAi.engineWire).replace(/</g, '\\u003c')};</script>`
|
|
906
|
-
: '';
|
|
907
|
-
// Boot the sandbox by loading the real init entry as a module (Vite
|
|
908
|
-
// serves + transforms it). The init module's top-level await deploys rules
|
|
909
|
-
// before app code runs. Mirrors serve's injectServeTags.
|
|
910
|
-
const tag = head + aiEngineTag + runtimeChipTag + `<script type="module" src="/@fs/${entries.init}" ${MARKER}></script>`;
|
|
911
|
-
return html.includes('</head>') ? html.replace('</head>', `${tag}</head>`) : tag + html;
|
|
109
|
+
return pageRuntime.transformIndexHtml(html);
|
|
912
110
|
},
|
|
913
111
|
};
|
|
914
112
|
}
|