@pyric/cli 0.1.0-alpha.16 → 0.1.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -12
- package/dist/assurance/.generated/conformance-verdicts.d.ts +80 -72
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +80 -72
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/bridge/server/bridge.d.ts.map +1 -1
- package/dist/bridge/server/bridge.js +4 -2
- package/dist/bridge/server/bridge.js.map +1 -1
- package/dist/bridge/server/peer.d.ts.map +1 -1
- package/dist/bridge/server/peer.js +1 -0
- package/dist/bridge/server/peer.js.map +1 -1
- package/dist/cli/database-rules.d.ts.map +1 -1
- package/dist/cli/database-rules.js +6 -4
- package/dist/cli/database-rules.js.map +1 -1
- package/dist/cli/dev-runner.d.ts +9 -0
- package/dist/cli/dev-runner.d.ts.map +1 -1
- package/dist/cli/dev-runner.js +18 -0
- package/dist/cli/dev-runner.js.map +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +62 -6
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/verify.js +2 -2
- package/dist/cli/verify.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/child.d.ts +1 -0
- package/dist/functions-rtdb/child.d.ts.map +1 -1
- package/dist/functions-rtdb/child.js +11 -1
- package/dist/functions-rtdb/child.js.map +1 -1
- package/dist/functions-rtdb/development-runtime.d.ts +1 -0
- package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
- package/dist/functions-rtdb/development-runtime.js +1 -0
- package/dist/functions-rtdb/development-runtime.js.map +1 -1
- package/dist/next/client-aliases.d.ts +11 -0
- package/dist/next/client-aliases.d.ts.map +1 -0
- package/dist/next/client-aliases.js +38 -0
- package/dist/next/client-aliases.js.map +1 -0
- package/dist/next/dev-rewrites.d.ts +9 -0
- package/dist/next/dev-rewrites.d.ts.map +1 -0
- package/dist/next/dev-rewrites.js +53 -0
- package/dist/next/dev-rewrites.js.map +1 -0
- package/dist/next/guard.d.ts +15 -0
- package/dist/next/guard.d.ts.map +1 -0
- package/dist/next/guard.js +52 -0
- package/dist/next/guard.js.map +1 -0
- package/dist/next/index.d.ts +12 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +11 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/runtime-env.d.ts +7 -0
- package/dist/next/runtime-env.d.ts.map +1 -0
- package/dist/next/runtime-env.js +13 -0
- package/dist/next/runtime-env.js.map +1 -0
- package/dist/next/server-external-packages.d.ts +10 -0
- package/dist/next/server-external-packages.d.ts.map +1 -0
- package/dist/next/server-external-packages.js +34 -0
- package/dist/next/server-external-packages.js.map +1 -0
- package/dist/next/target-url.d.ts +11 -0
- package/dist/next/target-url.d.ts.map +1 -0
- package/dist/next/target-url.js +36 -0
- package/dist/next/target-url.js.map +1 -0
- package/dist/next/turbopack-config.d.ts +9 -0
- package/dist/next/turbopack-config.d.ts.map +1 -0
- package/dist/next/turbopack-config.js +39 -0
- package/dist/next/turbopack-config.js.map +1 -0
- package/dist/next/types.d.ts +40 -0
- package/dist/next/types.d.ts.map +1 -0
- package/dist/next/types.js +5 -0
- package/dist/next/types.js.map +1 -0
- package/dist/next/webpack-config.d.ts +11 -0
- package/dist/next/webpack-config.d.ts.map +1 -0
- package/dist/next/webpack-config.js +51 -0
- package/dist/next/webpack-config.js.map +1 -0
- package/dist/next/with-pyric.d.ts +22 -0
- package/dist/next/with-pyric.d.ts.map +1 -0
- package/dist/next/with-pyric.js +49 -0
- package/dist/next/with-pyric.js.map +1 -0
- package/dist/register/app-bridge.d.ts +9 -0
- package/dist/register/app-bridge.d.ts.map +1 -0
- package/dist/register/app-bridge.js +56 -0
- package/dist/register/app-bridge.js.map +1 -0
- package/dist/register/hooks.d.ts.map +1 -1
- package/dist/register/hooks.js +6 -1
- package/dist/register/hooks.js.map +1 -1
- package/dist/register/index.js +1 -1
- package/dist/register/index.js.map +1 -1
- package/dist/register/mapping.d.ts +3 -1
- package/dist/register/mapping.d.ts.map +1 -1
- package/dist/register/mapping.js +41 -5
- package/dist/register/mapping.js.map +1 -1
- package/dist/remote/index.d.ts.map +1 -1
- package/dist/remote/index.js +5 -3
- package/dist/remote/index.js.map +1 -1
- package/dist/rtdb/rules-json.d.ts +12 -0
- package/dist/rtdb/rules-json.d.ts.map +1 -1
- package/dist/rtdb/rules-json.js +98 -0
- package/dist/rtdb/rules-json.js.map +1 -1
- package/dist/serve/bundler.d.ts.map +1 -1
- package/dist/serve/bundler.js +2 -0
- package/dist/serve/bundler.js.map +1 -1
- package/dist/serve/discovery.d.ts +4 -4
- package/dist/serve/discovery.d.ts.map +1 -1
- package/dist/serve/discovery.js +59 -38
- package/dist/serve/discovery.js.map +1 -1
- package/dist/serve/entries/app-ai-passthrough.d.ts +8 -0
- package/dist/serve/entries/app-ai-passthrough.d.ts.map +1 -0
- package/dist/serve/entries/app-ai-passthrough.js +59 -0
- package/dist/serve/entries/app-ai-passthrough.js.map +1 -0
- package/dist/serve/entries/auth-helper-core.js +9 -7
- package/dist/serve/entries/auth-helper-core.js.map +1 -1
- package/dist/serve/entries/auth.d.ts +1 -0
- package/dist/serve/entries/auth.d.ts.map +1 -1
- package/dist/serve/entries/auth.js +1 -0
- package/dist/serve/entries/auth.js.map +1 -1
- package/dist/serve/entries/bridge-url.d.ts.map +1 -1
- package/dist/serve/entries/bridge-url.js +7 -2
- package/dist/serve/entries/bridge-url.js.map +1 -1
- package/dist/serve/entries/database.d.ts +1 -0
- package/dist/serve/entries/database.d.ts.map +1 -1
- package/dist/serve/entries/database.js +1 -0
- package/dist/serve/entries/database.js.map +1 -1
- package/dist/serve/entries/firestore.d.ts +1 -0
- package/dist/serve/entries/firestore.d.ts.map +1 -1
- package/dist/serve/entries/firestore.js +1 -0
- package/dist/serve/entries/firestore.js.map +1 -1
- package/dist/serve/entries/init.d.ts.map +1 -1
- package/dist/serve/entries/init.js +4 -2
- package/dist/serve/entries/init.js.map +1 -1
- package/dist/serve/entries/runtime.js +23 -0
- package/dist/serve/entries/runtime.js.map +1 -1
- package/dist/serve/entries/storage.d.ts +2 -0
- package/dist/serve/entries/storage.d.ts.map +1 -1
- package/dist/serve/entries/storage.js +9 -2
- package/dist/serve/entries/storage.js.map +1 -1
- package/dist/serve/html-injection.d.ts +3 -1
- package/dist/serve/html-injection.d.ts.map +1 -1
- package/dist/serve/html-injection.js +27 -1
- package/dist/serve/html-injection.js.map +1 -1
- package/dist/serve/rules.js +2 -2
- package/dist/serve/rules.js.map +1 -1
- package/dist/serve/runtime/chip-config.d.ts +1 -1
- package/dist/serve/runtime/chip-config.d.ts.map +1 -1
- package/dist/serve/runtime/chip-config.js +16 -8
- package/dist/serve/runtime/chip-config.js.map +1 -1
- package/dist/serve/runtime/chip.d.ts.map +1 -1
- package/dist/serve/runtime/chip.js +24 -3
- package/dist/serve/runtime/chip.js.map +1 -1
- package/dist/serve/runtime/status.d.ts +1 -0
- package/dist/serve/runtime/status.d.ts.map +1 -1
- package/dist/serve/runtime/status.js +71 -13
- package/dist/serve/runtime/status.js.map +1 -1
- package/dist/serve/sandbox-session.d.ts +1 -0
- package/dist/serve/sandbox-session.d.ts.map +1 -1
- package/dist/serve/sandbox-session.js +30 -2
- package/dist/serve/sandbox-session.js.map +1 -1
- package/dist/serve/site-ui/_astro/_slug_.C6QfVOxJ.css +1 -0
- package/dist/serve/site-ui/_astro/_studio_.B6b_G1ev.css +1 -0
- package/dist/serve/site-ui/_astro/app.B7pBzz5N.js +11 -0
- package/dist/serve/site-ui/_astro/app.boex5SnQ.js +1 -0
- package/dist/serve/site-ui/_astro/{chess-showcase.CnoxIle5.js → chess-showcase.DDqE-QGe.js} +1 -1
- package/dist/serve/site-ui/_astro/{example-runtime.R1d96L6-.js → example-runtime.B0byNQOl.js} +1 -1
- package/dist/serve/site-ui/_astro/index.uwPvjH_1.js +1 -0
- package/dist/serve/site-ui/_astro/reads.Dh3z0fJy.js +1 -0
- package/dist/serve/site-ui/_astro/sandbox-controls.C2IqtoSw.js +1252 -0
- package/dist/serve/site-ui/_astro/{seed.EyI3VYEu.js → seed.CCmj00su.js} +1 -1
- package/dist/serve/site-ui/auth/index.html +2 -2
- package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
- package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +48 -13
- package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +74 -11
- package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
- package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
- package/dist/serve/site-ui/docs/ai-compat/index.html +85 -85
- package/dist/serve/site-ui/docs/ai-compat.md +84 -84
- package/dist/serve/site-ui/docs/api-reference/index.html +3 -1
- package/dist/serve/site-ui/docs/api-reference.md +2 -0
- package/dist/serve/site-ui/docs/app-compat/index.html +28 -28
- package/dist/serve/site-ui/docs/app-compat.md +27 -27
- package/dist/serve/site-ui/docs/auth-compat/index.html +122 -122
- package/dist/serve/site-ui/docs/auth-compat.md +121 -121
- package/dist/serve/site-ui/docs/build/ai-logic/index.html +19 -2
- package/dist/serve/site-ui/docs/build/ai-logic.md +28 -0
- package/dist/serve/site-ui/docs/build/authentication/index.html +1 -1
- package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +1 -1
- package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
- package/dist/serve/site-ui/docs/build/cloud-storage/index.html +1 -1
- package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
- package/dist/serve/site-ui/docs/conformance-scores/index.html +25 -10
- package/dist/serve/site-ui/docs/conformance-scores.md +23 -8
- package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -6
- package/dist/serve/site-ui/docs/create-pyric-reference-api.md +5 -5
- package/dist/serve/site-ui/docs/database-compat/index.html +200 -448
- package/dist/serve/site-ui/docs/database-compat.md +198 -461
- package/dist/serve/site-ui/docs/examples/chess/index.html +2 -2
- package/dist/serve/site-ui/docs/examples/index.html +1 -1
- package/dist/serve/site-ui/docs/firestore-compat/index.html +186 -195
- package/dist/serve/site-ui/docs/firestore-compat.md +184 -195
- package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +15 -15
- package/dist/serve/site-ui/docs/functions-rtdb-compat.md +14 -14
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
- package/dist/serve/site-ui/docs/get-started/nextjs/index.html +57 -0
- package/dist/serve/site-ui/docs/get-started/nextjs.md +86 -0
- package/dist/serve/site-ui/docs/get-started/start-building/index.html +38 -9
- package/dist/serve/site-ui/docs/get-started/start-building.md +62 -7
- package/dist/serve/site-ui/docs/get-started/vite/index.html +26 -0
- package/dist/serve/site-ui/docs/get-started/vite.md +45 -0
- package/dist/serve/site-ui/docs/index.json +711 -111
- package/dist/serve/site-ui/docs/messaging-compat/index.html +56 -56
- package/dist/serve/site-ui/docs/messaging-compat.md +55 -55
- package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
- package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
- package/dist/serve/site-ui/docs/overview/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +39 -13
- package/dist/serve/site-ui/docs/pyric-admin-app-reference-api.md +28 -2
- package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +38 -6
- package/dist/serve/site-ui/docs/pyric-admin-database-reference-api.md +43 -0
- package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +9 -1
- package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +8 -0
- package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +27 -4
- package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api.md +23 -0
- package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +123 -0
- package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +99 -0
- package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +127 -0
- package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api.md +174 -0
- package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +570 -326
- package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +198 -6
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +2971 -627
- package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +2873 -517
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +43 -3
- package/dist/serve/site-ui/docs/pyric-rules-reference-api.md +8 -0
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +26 -2
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +24 -0
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +77 -9
- package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +28 -13
- package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +240 -63
- package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +164 -5
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -10
- package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api.md +0 -9
- package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +2 -1
- package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +1 -0
- package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
- package/dist/serve/site-ui/docs/rules-compat/index.html +87 -79
- package/dist/serve/site-ui/docs/rules-compat.md +86 -78
- package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
- package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +1 -1
- package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
- package/dist/serve/site-ui/docs/storage-compat/index.html +119 -125
- package/dist/serve/site-ui/docs/storage-compat.md +118 -124
- package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
- package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +1 -1
- package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
- package/dist/serve/site-ui/docs/tutorial/index.html +2 -1
- package/dist/serve/site-ui/docs/tutorial.md +2 -0
- package/dist/serve/site-ui/examples/chess/index.html +1 -1
- package/dist/serve/site-ui/examples/firestore-first-write/index.html +1 -1
- package/dist/serve/site-ui/firestore/index.html +2 -2
- package/dist/serve/site-ui/index.html +2 -2
- package/dist/serve/site-ui/llms.txt +8 -4
- package/dist/serve/site-ui/rtdb/index.html +2 -2
- package/dist/serve/site-ui/settings/index.html +2 -2
- package/dist/serve/site-ui/storage/index.html +2 -2
- package/dist/serve/site-ui/traffic/index.html +2 -2
- package/dist/serve/vite-ai-config.d.ts +4 -1
- package/dist/serve/vite-ai-config.d.ts.map +1 -1
- package/dist/serve/vite-ai-config.js +83 -19
- package/dist/serve/vite-ai-config.js.map +1 -1
- package/dist/serve/vite-functions-development.d.ts.map +1 -1
- package/dist/serve/vite-functions-development.js +1 -0
- package/dist/serve/vite-functions-development.js.map +1 -1
- package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -1
- package/dist/serve/vite-generation-rules-watch.js +61 -14
- package/dist/serve/vite-generation-rules-watch.js.map +1 -1
- package/dist/serve/vite-module-swap.d.ts +4 -1
- package/dist/serve/vite-module-swap.d.ts.map +1 -1
- package/dist/serve/vite-module-swap.js +106 -21
- package/dist/serve/vite-module-swap.js.map +1 -1
- package/dist/serve/vite-plugin.d.ts.map +1 -1
- package/dist/serve/vite-plugin.js +45 -5
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-sandbox-generation.js +1 -1
- package/dist/serve/vite-sandbox-generation.js.map +1 -1
- package/dist/serve/worker/client/resumable.d.ts +30 -0
- package/dist/serve/worker/client/resumable.d.ts.map +1 -0
- package/dist/serve/worker/client/resumable.js +416 -0
- package/dist/serve/worker/client/resumable.js.map +1 -0
- package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -1
- package/dist/serve/worker/client/rtdb-references.js +4 -1
- package/dist/serve/worker/client/rtdb-references.js.map +1 -1
- package/dist/serve/worker/client/storage.d.ts +16 -2
- package/dist/serve/worker/client/storage.d.ts.map +1 -1
- package/dist/serve/worker/client/storage.js +57 -6
- package/dist/serve/worker/client/storage.js.map +1 -1
- package/dist/serve/worker/host/rules.d.ts.map +1 -1
- package/dist/serve/worker/host/rules.js +2 -1
- package/dist/serve/worker/host/rules.js.map +1 -1
- package/dist/serve/worker/index.d.ts +1 -1
- package/dist/serve/worker/index.d.ts.map +1 -1
- package/dist/serve/worker/index.js +1 -1
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/serve-init.d.ts.map +1 -1
- package/dist/serve/worker/serve-init.js +31 -0
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/package.json +15 -4
- package/src/assurance/.generated/conformance-verdicts.ts +80 -72
- package/src/bridge/server/bridge.ts +5 -2
- package/src/bridge/server/peer.ts +2 -1
- package/src/cli/cli.test.ts +14 -0
- package/src/cli/database-rules.ts +6 -4
- package/src/cli/dev-runner.ts +21 -0
- package/src/cli/serve.ts +63 -5
- package/src/cli/verify.ts +2 -2
- 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/child.ts +12 -1
- package/src/functions-rtdb/development-runtime.ts +2 -0
- package/src/next/client-aliases.ts +39 -0
- package/src/next/dev-rewrites.ts +77 -0
- package/src/next/guard.ts +61 -0
- package/src/next/index.ts +16 -0
- package/src/next/runtime-env.ts +18 -0
- package/src/next/server-external-packages.ts +43 -0
- package/src/next/target-url.ts +46 -0
- package/src/next/turbopack-config.ts +54 -0
- package/src/next/types.ts +47 -0
- package/src/next/webpack-config.ts +71 -0
- package/src/next/with-pyric.ts +58 -0
- package/src/register/app-bridge.ts +79 -0
- package/src/register/hooks.ts +6 -1
- package/src/register/index.ts +1 -1
- package/src/register/mapping.ts +50 -4
- package/src/remote/index.ts +7 -5
- package/src/rtdb/rules-json.ts +110 -0
- package/src/serve/bundler.ts +2 -0
- package/src/serve/discovery.ts +65 -44
- package/src/serve/entries/app-ai-passthrough.ts +83 -0
- package/src/serve/entries/auth-helper-core.ts +9 -7
- package/src/serve/entries/auth.ts +1 -0
- package/src/serve/entries/bridge-url.ts +9 -2
- package/src/serve/entries/database.ts +1 -0
- package/src/serve/entries/firestore.ts +1 -0
- package/src/serve/entries/init.ts +5 -2
- package/src/serve/entries/runtime.ts +25 -0
- package/src/serve/entries/storage.ts +12 -1
- package/src/serve/html-injection.ts +26 -1
- package/src/serve/rules.ts +2 -2
- package/src/serve/runtime/chip-config.ts +19 -6
- package/src/serve/runtime/chip.ts +24 -3
- package/src/serve/runtime/status.ts +76 -13
- package/src/serve/sandbox-session.ts +31 -2
- package/src/serve/vite-ai-config.ts +86 -19
- package/src/serve/vite-functions-development.ts +1 -0
- package/src/serve/vite-generation-rules-watch.ts +67 -15
- package/src/serve/vite-module-swap.ts +121 -21
- package/src/serve/vite-plugin.ts +44 -6
- package/src/serve/vite-sandbox-generation.ts +1 -1
- package/src/serve/worker/client/resumable.ts +506 -0
- package/src/serve/worker/client/rtdb-references.ts +4 -1
- package/src/serve/worker/client/storage.ts +77 -7
- package/src/serve/worker/host/rules.ts +2 -1
- package/src/serve/worker/index.ts +4 -0
- package/src/serve/worker/serve-init.ts +30 -0
- package/dist/serve/site-ui/_astro/_slug_.BoKXYrnu.css +0 -1
- package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +0 -1
- package/dist/serve/site-ui/_astro/app.4HeLP_FA.js +0 -109
- package/dist/serve/site-ui/_astro/app.BgSnCR5G.js +0 -1
- package/dist/serve/site-ui/_astro/index.BJiOemMX.js +0 -1
- package/dist/serve/site-ui/_astro/reads.BrKNdKAa.js +0 -1
- package/dist/serve/site-ui/_astro/sandbox-controls.BTb3EbQp.js +0 -1153
|
@@ -17,14 +17,27 @@ interface RuntimeChipDocument {
|
|
|
17
17
|
querySelector(selector: string): { getAttribute(name: string): string | null } | null;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
function hasBundlerRuntimeChipConfig(): boolean {
|
|
21
|
+
return typeof process !== 'undefined' && typeof process.env !== 'undefined' && typeof process.env.PYRIC_RUNTIME_CHIP === 'string';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Read plugin-authored values from DOM metadata or bundler environment variables, defaulting to collapsed UI when omitted. */
|
|
21
25
|
export function readPyricRuntimeChipConfig(
|
|
22
26
|
documentLike: RuntimeChipDocument,
|
|
23
27
|
): PyricRuntimeChipConfig | null {
|
|
24
28
|
const meta = documentLike.querySelector(`meta[name="${PYRIC_RUNTIME_CHIP_META}"]`);
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
const hasMetaTag = meta !== null;
|
|
30
|
+
let value = hasMetaTag ? meta.getAttribute('content') : null;
|
|
31
|
+
|
|
32
|
+
const shouldFallbackToEnv = !hasMetaTag && hasBundlerRuntimeChipConfig();
|
|
33
|
+
if (shouldFallbackToEnv) {
|
|
34
|
+
value = process.env.PYRIC_RUNTIME_CHIP as string;
|
|
35
|
+
}
|
|
36
|
+
if (value === 'off') {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const studioEnabled = !hasMetaTag || meta.getAttribute('data-studio') !== 'off';
|
|
41
|
+
const initiallyOpen = value === 'expanded';
|
|
42
|
+
return { initiallyOpen, studioEnabled };
|
|
30
43
|
}
|
|
@@ -94,9 +94,12 @@ const styles = `
|
|
|
94
94
|
.errors { background: var(--pyric-content); border-bottom: 1px solid var(--pyric-border-soft); border-top: 1px solid var(--pyric-border-soft); max-height: 184px; min-height: 58px; overflow-y: auto; }
|
|
95
95
|
.errors::-webkit-scrollbar { width: 8px; }
|
|
96
96
|
.errors::-webkit-scrollbar-thumb { background: #33333f; border-radius: 4px; }
|
|
97
|
-
.error-row { align-items: flex-start; border-bottom: 1px solid rgba(42,42,53,.7); display: grid; gap: 8px; grid-template-columns: 18px minmax(0,1fr) 28px; padding: 10px 8px 10px 12px; }
|
|
97
|
+
.error-row { align-items: flex-start; border-bottom: 1px solid rgba(42,42,53,.7); display: grid; gap: 8px; grid-template-columns: 18px minmax(0,1fr) 28px 28px; padding: 10px 8px 10px 12px; }
|
|
98
98
|
.error-row:last-child { border-bottom: 0; }
|
|
99
99
|
.error-number { color: var(--pyric-error); font: 10px/20px ui-monospace, monospace; }
|
|
100
|
+
.panel-controls { align-items: center; display: inline-flex; gap: 4px; }
|
|
101
|
+
.clear-button { background: transparent; border: 0; color: var(--pyric-muted); cursor: pointer; font-size: 11px; margin-left: 8px; padding: 2px 6px; }
|
|
102
|
+
.clear-button:hover { color: var(--pyric-text); }
|
|
100
103
|
.error-body { min-width: 0; }
|
|
101
104
|
.error-body code { color: #d7d7df; display: block; font-size: 11px; line-height: 1.55; overflow-wrap: anywhere; white-space: pre-wrap; }
|
|
102
105
|
.error-meta { color: var(--pyric-muted); font: 9px/1.4 ui-monospace, monospace; margin-top: 4px; overflow-wrap: anywhere; }
|
|
@@ -122,6 +125,7 @@ const styles = `
|
|
|
122
125
|
|
|
123
126
|
const icons = {
|
|
124
127
|
close: '<svg class="icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="m6 6 12 12M18 6 6 18"/></svg>',
|
|
128
|
+
minimize: '<svg class="icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M5 12h14"/></svg>',
|
|
125
129
|
copy: '<svg class="icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="8" y="8" width="11" height="11" rx="1"/><path d="M16 8V5H5v11h3"/></svg>',
|
|
126
130
|
chevron: '<svg class="chevron" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="m6 15 6-6 6 6"/></svg>',
|
|
127
131
|
external: '<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M14 5h5v5M19 5l-8 8"/><path d="M19 13v6H5V5h6"/></svg>',
|
|
@@ -148,6 +152,7 @@ function renderErrors(snapshot: PyricRuntimeSnapshot, canCopy: boolean): string
|
|
|
148
152
|
<span class="error-number">${String(index + 1).padStart(2, '0')}</span>
|
|
149
153
|
<div class="error-body"><code></code><div class="error-meta"></div></div>
|
|
150
154
|
<button class="icon-button" type="button" data-copy-error="${escapeAttribute(error.id)}" aria-label="${canCopy ? `Copy error ${index + 1}` : 'Copy unavailable'}" title="${canCopy ? 'Copy error' : 'Clipboard unavailable'}" ${canCopy ? '' : 'disabled'}>${icons.copy}</button>
|
|
155
|
+
<button class="icon-button" type="button" data-dismiss-error="${escapeAttribute(error.id)}" aria-label="Dismiss error ${index + 1}" title="Dismiss error">${icons.close}</button>
|
|
151
156
|
</div>
|
|
152
157
|
`).join('');
|
|
153
158
|
}
|
|
@@ -202,8 +207,11 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
|
|
|
202
207
|
view.innerHTML = `${open ? `
|
|
203
208
|
<section class="panel" role="dialog" aria-label="Pyric runtime">
|
|
204
209
|
<header class="panel-header">
|
|
205
|
-
<div class="panel-title"><span class="brand-mark">>_</span><strong>Pyric runtime</strong>${errorCount > 0 ? `<span class="count">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span>` : ''}</div>
|
|
206
|
-
<
|
|
210
|
+
<div class="panel-title"><span class="brand-mark">>_</span><strong>Pyric runtime</strong>${errorCount > 0 ? `<span class="count">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span><button class="clear-button" type="button" data-clear-errors aria-label="Clear all errors">Clear</button>` : ''}</div>
|
|
211
|
+
<div class="panel-controls">
|
|
212
|
+
<button class="icon-button" type="button" data-collapse aria-label="Minimize Pyric runtime">${icons.minimize}</button>
|
|
213
|
+
<button class="icon-button" type="button" data-dismiss-chip aria-label="Dismiss Pyric runtime from page">${icons.close}</button>
|
|
214
|
+
</div>
|
|
207
215
|
</header>
|
|
208
216
|
<div class="worker-state"><span class="state-label${snapshot.updateAvailable ? ' available' : ''}"><span class="mini-dot"></span>${workerLabel}</span><span class="epochs">${epochs}</span></div>
|
|
209
217
|
<div class="errors" data-error-viewport>${renderErrors(snapshot, Boolean(clipboard))}</div>
|
|
@@ -247,6 +255,12 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
|
|
|
247
255
|
render();
|
|
248
256
|
root.querySelector<HTMLButtonElement>('[data-expand]')?.focus();
|
|
249
257
|
});
|
|
258
|
+
root.querySelector('[data-clear-errors]')?.addEventListener('click', () => {
|
|
259
|
+
options.runtime.clearErrors();
|
|
260
|
+
});
|
|
261
|
+
root.querySelector('[data-dismiss-chip]')?.addEventListener('click', () => {
|
|
262
|
+
host.style.display = 'none';
|
|
263
|
+
});
|
|
250
264
|
root.querySelector('[data-update-worker]')?.addEventListener('click', () => {
|
|
251
265
|
if (!snapshot.updateAvailable || snapshot.updatingWorker) return;
|
|
252
266
|
void options.runtime.updateWorker().catch(() => { /* status records and renders the failure */ });
|
|
@@ -262,6 +276,13 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
|
|
|
262
276
|
});
|
|
263
277
|
});
|
|
264
278
|
}
|
|
279
|
+
for (const button of root.querySelectorAll<HTMLButtonElement>('[data-dismiss-error]')) {
|
|
280
|
+
button.addEventListener('click', () => {
|
|
281
|
+
if (button.dataset.dismissError) {
|
|
282
|
+
options.runtime.dismissError(button.dataset.dismissError);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
265
286
|
if (focusToken) {
|
|
266
287
|
const candidates = root.querySelectorAll<HTMLElement>(`[${focusToken.attribute}]`);
|
|
267
288
|
const replacement = [...candidates].find((candidate) =>
|
|
@@ -36,6 +36,7 @@ export interface PyricRuntimeStatus {
|
|
|
36
36
|
reportError(error: unknown, source: PyricRuntimeErrorSource): void;
|
|
37
37
|
recordSandboxEvents(events: readonly SandboxEvent[]): void;
|
|
38
38
|
clearErrors(): void;
|
|
39
|
+
dismissError(id: string): void;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
let nextErrorId = 0;
|
|
@@ -77,41 +78,95 @@ export function normalizePyricRuntimeError(
|
|
|
77
78
|
return { id, source, at, message: String(value) };
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
function isOperationOrRequestEvent(event: SandboxEvent): boolean {
|
|
82
|
+
const isOperationKind = event.kind === 'operation';
|
|
83
|
+
const isRequestKind = event.kind === 'request';
|
|
84
|
+
return isOperationKind || isRequestKind;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isDeniedOperationEvent(event: SandboxEvent): boolean {
|
|
88
|
+
const isTargetEventKind = isOperationOrRequestEvent(event);
|
|
89
|
+
const hasResultProperty = 'result' in event;
|
|
90
|
+
const isDeniedResult = hasResultProperty && event.result === 'deny';
|
|
91
|
+
return isTargetEventKind && isDeniedResult;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function isRuntimeErrorEvent(event: SandboxEvent): boolean {
|
|
95
|
+
return event.kind === 'runtime_error';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function isListenerErroredEvent(event: SandboxEvent): boolean {
|
|
99
|
+
const isListenerErroredKind = event.kind === 'listener_errored';
|
|
100
|
+
const hasErrorPayload = 'error' in event && Boolean(event.error);
|
|
101
|
+
return isListenerErroredKind && hasErrorPayload;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function isListenerPhaseErroredEvent(event: SandboxEvent): boolean {
|
|
105
|
+
const isListenerKind = event.kind === 'listener';
|
|
106
|
+
const isErroredPhase = 'phase' in event && event.phase === 'errored';
|
|
107
|
+
const hasErrorPayload = 'error' in event && Boolean(event.error);
|
|
108
|
+
return isListenerKind && isErroredPhase && hasErrorPayload;
|
|
109
|
+
}
|
|
110
|
+
|
|
80
111
|
function sandboxError(event: SandboxEvent): PyricRuntimeError | null {
|
|
81
|
-
if (event
|
|
112
|
+
if (isRuntimeErrorEvent(event)) {
|
|
113
|
+
const hasPathProperty = 'path' in event && typeof event.path === 'string';
|
|
114
|
+
const targetPath = hasPathProperty ? event.path : undefined;
|
|
115
|
+
const hasMethodProperty = 'method' in event && typeof event.method === 'string';
|
|
116
|
+
const targetMethod = hasMethodProperty ? event.method : 'unknown';
|
|
117
|
+
const hasErrorPayload = 'error' in event && Boolean(event.error);
|
|
118
|
+
const errorPayload = hasErrorPayload ? (event as { error: { code?: string; message: string } }).error : undefined;
|
|
82
119
|
return {
|
|
83
120
|
id: event.id,
|
|
84
121
|
source: 'sandbox',
|
|
85
122
|
at: event.at,
|
|
86
123
|
service: event.service,
|
|
87
|
-
method:
|
|
88
|
-
...(
|
|
89
|
-
...(
|
|
90
|
-
message:
|
|
124
|
+
method: targetMethod,
|
|
125
|
+
...(targetPath ? { path: targetPath } : {}),
|
|
126
|
+
...(errorPayload?.code ? { code: errorPayload.code } : {}),
|
|
127
|
+
message: errorPayload?.message ? errorPayload.message : 'Sandbox runtime error',
|
|
91
128
|
};
|
|
92
129
|
}
|
|
93
|
-
if (event
|
|
130
|
+
if (isListenerErroredEvent(event)) {
|
|
131
|
+
const errorPayload = (event as { error: { code?: string; message: string } }).error;
|
|
94
132
|
return {
|
|
95
133
|
id: event.id,
|
|
96
134
|
source: 'sandbox',
|
|
97
135
|
at: event.at,
|
|
98
136
|
service: 'firestore',
|
|
99
137
|
method: 'listener',
|
|
100
|
-
...('path' in event.target ? { path: event.target.path } : {}),
|
|
101
|
-
code:
|
|
102
|
-
message:
|
|
138
|
+
...('target' in event && event.target && 'path' in event.target ? { path: event.target.path } : {}),
|
|
139
|
+
code: errorPayload.code,
|
|
140
|
+
message: errorPayload.message,
|
|
103
141
|
};
|
|
104
142
|
}
|
|
105
|
-
if (event
|
|
143
|
+
if (isListenerPhaseErroredEvent(event)) {
|
|
144
|
+
const errorPayload = (event as { error: { code?: string; message: string } }).error;
|
|
106
145
|
return {
|
|
107
146
|
id: event.id,
|
|
108
147
|
source: 'sandbox',
|
|
109
148
|
at: event.at,
|
|
110
149
|
service: event.service,
|
|
111
150
|
method: 'listener',
|
|
112
|
-
...(event.target
|
|
113
|
-
...(
|
|
114
|
-
message:
|
|
151
|
+
...('target' in event && event.target && 'path' in event.target ? { path: event.target.path } : {}),
|
|
152
|
+
...(errorPayload.code ? { code: errorPayload.code } : {}),
|
|
153
|
+
message: errorPayload.message,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (isDeniedOperationEvent(event)) {
|
|
157
|
+
const hasPathProperty = 'path' in event && typeof event.path === 'string';
|
|
158
|
+
const targetPath = hasPathProperty ? event.path : '(service)';
|
|
159
|
+
const hasMethodProperty = 'method' in event && typeof event.method === 'string';
|
|
160
|
+
const targetMethod = hasMethodProperty ? event.method : 'operation';
|
|
161
|
+
return {
|
|
162
|
+
id: event.id,
|
|
163
|
+
source: 'sandbox',
|
|
164
|
+
at: event.at,
|
|
165
|
+
service: event.service,
|
|
166
|
+
method: targetMethod,
|
|
167
|
+
path: targetPath,
|
|
168
|
+
code: 'PERMISSION_DENIED',
|
|
169
|
+
message: `PERMISSION_DENIED: ${targetMethod} on ${targetPath} denied by rules`,
|
|
115
170
|
};
|
|
116
171
|
}
|
|
117
172
|
return null;
|
|
@@ -201,6 +256,14 @@ export function createPyricRuntimeStatus(
|
|
|
201
256
|
errorIds.clear();
|
|
202
257
|
publish({ ...snapshot, errors: [] });
|
|
203
258
|
},
|
|
259
|
+
dismissError(id) {
|
|
260
|
+
if (!errorIds.has(id)) return;
|
|
261
|
+
errorIds.delete(id);
|
|
262
|
+
publish({
|
|
263
|
+
...snapshot,
|
|
264
|
+
errors: snapshot.errors.filter((err) => err.id !== id),
|
|
265
|
+
});
|
|
266
|
+
},
|
|
204
267
|
};
|
|
205
268
|
}
|
|
206
269
|
|
|
@@ -63,6 +63,7 @@ export interface SandboxSession {
|
|
|
63
63
|
payload(): InitPayload;
|
|
64
64
|
handle(req: IncomingMessage, res: ServerResponse, url: URL): boolean | Promise<boolean>;
|
|
65
65
|
reloadFirestoreRules(): Promise<RulesReloadResult>;
|
|
66
|
+
reloadDatabaseRules(): Promise<RulesReloadResult>;
|
|
66
67
|
close(): Promise<void>;
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -93,6 +94,8 @@ export async function createSandboxSession(
|
|
|
93
94
|
const live = {
|
|
94
95
|
rules: firestore.rules,
|
|
95
96
|
rulesHash: firestore.rulesHash,
|
|
97
|
+
databaseRules: database.rules,
|
|
98
|
+
databaseRulesHash: database.rulesHash,
|
|
96
99
|
};
|
|
97
100
|
const events = createEventHub();
|
|
98
101
|
const capture: CaptureStore | undefined = (options.capture ?? true)
|
|
@@ -145,8 +148,8 @@ export async function createSandboxSession(
|
|
|
145
148
|
const payload = (): InitPayload => ({
|
|
146
149
|
rules: live.rules,
|
|
147
150
|
rulesHash: live.rulesHash,
|
|
148
|
-
databaseRules:
|
|
149
|
-
databaseRulesHash:
|
|
151
|
+
databaseRules: live.databaseRules,
|
|
152
|
+
databaseRulesHash: live.databaseRulesHash,
|
|
150
153
|
databaseUrl: database.databaseUrl,
|
|
151
154
|
storageRules: storage.rules,
|
|
152
155
|
storageRulesHash: storage.rulesHash,
|
|
@@ -217,6 +220,31 @@ export async function createSandboxSession(
|
|
|
217
220
|
return { kind: 'rejected', error: error instanceof Error ? error : new Error(String(error)) };
|
|
218
221
|
}
|
|
219
222
|
};
|
|
223
|
+
const reloadDatabaseRules = async (): Promise<RulesReloadResult> => {
|
|
224
|
+
const isMissingDatabaseRules = database.sourcePath === null;
|
|
225
|
+
if (isMissingDatabaseRules) {
|
|
226
|
+
return { kind: 'not-configured' };
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
const updated = await loadProjectDatabaseRules(options.projectDir, options.firebaseConfig);
|
|
230
|
+
const isMissingUpdatedRules = updated.rules === null || updated.rulesHash === null;
|
|
231
|
+
if (isMissingUpdatedRules) {
|
|
232
|
+
return { kind: 'not-configured' };
|
|
233
|
+
}
|
|
234
|
+
live.databaseRules = updated.rules;
|
|
235
|
+
live.databaseRulesHash = updated.rulesHash;
|
|
236
|
+
events.broadcast('rtdb-rules-update', { rules: updated.rules, rulesHash: updated.rulesHash });
|
|
237
|
+
return { kind: 'reloaded', rulesHash: updated.rulesHash as string, clients: events.clientCount() };
|
|
238
|
+
} catch (error) {
|
|
239
|
+
const isErrorInstance = error instanceof Error;
|
|
240
|
+
let errorResult: Error = new Error(String(error));
|
|
241
|
+
if (isErrorInstance) {
|
|
242
|
+
errorResult = error as Error;
|
|
243
|
+
}
|
|
244
|
+
return { kind: 'rejected', error: errorResult };
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
220
248
|
let closePromise: Promise<void> | null = null;
|
|
221
249
|
const close = (): Promise<void> => {
|
|
222
250
|
closePromise ??= Promise.resolve().then(() => events.close());
|
|
@@ -228,6 +256,7 @@ export async function createSandboxSession(
|
|
|
228
256
|
payload,
|
|
229
257
|
handle: namespace,
|
|
230
258
|
reloadFirestoreRules,
|
|
259
|
+
reloadDatabaseRules,
|
|
231
260
|
close,
|
|
232
261
|
};
|
|
233
262
|
}
|
|
@@ -9,6 +9,8 @@ const AI_PROXY_PATH = '/__pyric/ai-proxy';
|
|
|
9
9
|
export type PyricAiEngineConfig = Extract<NonNullable<AIOptions['engine']>, { kind: string }>;
|
|
10
10
|
|
|
11
11
|
export interface PyricAiOptions {
|
|
12
|
+
/** Mode for AI Logic: 'sandbox' (local mirrors) or 'production' (pass-through to Google AI / Vertex AI). */
|
|
13
|
+
mode?: 'sandbox' | 'production';
|
|
12
14
|
/** Simple OpenAI-compatible model selection through Pyric's same-origin proxy. */
|
|
13
15
|
model?: string;
|
|
14
16
|
/** Advanced declarative engine configuration. */
|
|
@@ -18,6 +20,7 @@ export interface PyricAiOptions {
|
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export interface ResolvedViteAiConfig {
|
|
23
|
+
mode: 'sandbox' | 'production';
|
|
21
24
|
engineWire: AiEngineConfigWire | undefined;
|
|
22
25
|
proxyUpstream: string | undefined;
|
|
23
26
|
}
|
|
@@ -26,8 +29,9 @@ export interface ResolvedViteAiConfig {
|
|
|
26
29
|
export function viteWorkerEpochSalt(
|
|
27
30
|
projectKey: string,
|
|
28
31
|
engineWire: AiEngineConfigWire | undefined,
|
|
32
|
+
mode: 'sandbox' | 'production' = 'sandbox',
|
|
29
33
|
): string {
|
|
30
|
-
return JSON.stringify({ projectKey, aiEngine: engineWire ?? null });
|
|
34
|
+
return JSON.stringify({ projectKey, aiEngine: engineWire ?? null, aiMode: mode });
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
/** Load env using Vite's `envDir`-relative-to-root convention. */
|
|
@@ -45,20 +49,30 @@ export function loadViteAiEnv(
|
|
|
45
49
|
|
|
46
50
|
/** Convert a public declarative engine into the JSON-safe worker wire shape. */
|
|
47
51
|
export function engineConfigToWire(engine: PyricAiEngineConfig): AiEngineConfigWire {
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
const isOpenAiEngine = engine.kind === 'openai';
|
|
53
|
+
if (isOpenAiEngine) {
|
|
54
|
+
const result: Record<string, unknown> = {
|
|
50
55
|
kind: 'openai',
|
|
51
|
-
baseUrl: engine.baseUrl
|
|
52
|
-
...(engine.model !== undefined ? { model: engine.model } : {}),
|
|
53
|
-
...(engine.modelMap !== undefined ? { modelMap: engine.modelMap } : {}),
|
|
56
|
+
baseUrl: engine.baseUrl !== undefined && engine.baseUrl !== null ? engine.baseUrl : AI_PROXY_PATH,
|
|
54
57
|
};
|
|
58
|
+
const hasModel = engine.model !== undefined;
|
|
59
|
+
if (hasModel) {
|
|
60
|
+
result.model = engine.model;
|
|
61
|
+
}
|
|
62
|
+
const hasModelMap = engine.modelMap !== undefined;
|
|
63
|
+
if (hasModelMap) {
|
|
64
|
+
result.modelMap = engine.modelMap;
|
|
65
|
+
}
|
|
66
|
+
return result as AiEngineConfigWire;
|
|
55
67
|
}
|
|
56
|
-
|
|
68
|
+
const result: Record<string, unknown> = {
|
|
57
69
|
kind: 'scripted',
|
|
58
|
-
...(engine.script !== undefined
|
|
59
|
-
? { script: engine.script as unknown as Array<Record<string, unknown>> }
|
|
60
|
-
: {}),
|
|
61
70
|
};
|
|
71
|
+
const hasScript = engine.script !== undefined;
|
|
72
|
+
if (hasScript) {
|
|
73
|
+
result.script = engine.script as unknown as Array<Record<string, unknown>>;
|
|
74
|
+
}
|
|
75
|
+
return result as AiEngineConfigWire;
|
|
62
76
|
}
|
|
63
77
|
|
|
64
78
|
/** Resolve the plugin's explicit-options-over-Vite-env AI convention. */
|
|
@@ -66,20 +80,73 @@ export function resolveViteAiConfig(
|
|
|
66
80
|
options: PyricAiOptions | undefined,
|
|
67
81
|
env: Record<string, string | undefined>,
|
|
68
82
|
): ResolvedViteAiConfig {
|
|
69
|
-
|
|
83
|
+
const explicitModel = options?.model;
|
|
84
|
+
const explicitEngine = options?.engine;
|
|
85
|
+
const hasModelOption = explicitModel !== undefined;
|
|
86
|
+
const hasEngineOption = explicitEngine !== undefined;
|
|
87
|
+
const hasBothModelAndEngine = hasModelOption && hasEngineOption;
|
|
88
|
+
if (hasBothModelAndEngine) {
|
|
70
89
|
throw new Error('@pyric/cli/vite: Choose either ai.model or ai.engine, not both.');
|
|
71
90
|
}
|
|
72
91
|
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
92
|
+
let mode: 'sandbox' | 'production' = 'sandbox';
|
|
93
|
+
const explicitMode = options?.mode;
|
|
94
|
+
const hasExplicitMode = explicitMode !== undefined;
|
|
95
|
+
if (hasExplicitMode) {
|
|
96
|
+
mode = explicitMode;
|
|
97
|
+
} else {
|
|
98
|
+
const isEnvProductionMode = env.PYRIC_AI_MODE === 'production';
|
|
99
|
+
const isEnvPassthroughFlag = env.PYRIC_AI_PASSTHROUGH === '1';
|
|
100
|
+
const isProductionEnv = isEnvProductionMode || isEnvPassthroughFlag;
|
|
101
|
+
if (isProductionEnv) {
|
|
102
|
+
mode = 'production';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const isProductionMode = mode === 'production';
|
|
107
|
+
const hasAnyEngineConfig = hasModelOption || hasEngineOption;
|
|
108
|
+
const isInvalidProductionConfig = isProductionMode && hasAnyEngineConfig;
|
|
109
|
+
if (isInvalidProductionConfig) {
|
|
110
|
+
throw new Error('@pyric/cli/vite: Cannot configure ai.model or ai.engine when ai.mode is set to "production".');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let model: string | undefined = undefined;
|
|
114
|
+
const envModel = env.PYRIC_AI_MODEL;
|
|
115
|
+
if (explicitModel !== undefined) {
|
|
116
|
+
model = explicitModel.trim();
|
|
117
|
+
} else if (envModel !== undefined) {
|
|
118
|
+
model = envModel.trim();
|
|
119
|
+
}
|
|
120
|
+
const hasNonEmptyModel = model !== undefined && model !== '';
|
|
121
|
+
if (!hasNonEmptyModel) {
|
|
122
|
+
model = undefined;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let engineWire: AiEngineConfigWire | undefined = undefined;
|
|
126
|
+
if (!isProductionMode) {
|
|
127
|
+
if (explicitEngine !== undefined) {
|
|
128
|
+
engineWire = engineConfigToWire(explicitEngine);
|
|
129
|
+
} else if (model !== undefined) {
|
|
130
|
+
engineWire = engineConfigToWire({ kind: 'openai', baseUrl: AI_PROXY_PATH, model });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let proxyUpstream: string | undefined = undefined;
|
|
135
|
+
const explicitProxyUpstream = options?.proxyUpstream;
|
|
136
|
+
const envProxyUpstream = env.PYRIC_AI_PROXY_UPSTREAM;
|
|
137
|
+
if (explicitProxyUpstream !== undefined) {
|
|
138
|
+
proxyUpstream = explicitProxyUpstream.trim();
|
|
139
|
+
} else if (envProxyUpstream !== undefined) {
|
|
140
|
+
proxyUpstream = envProxyUpstream.trim();
|
|
141
|
+
}
|
|
142
|
+
const hasNonEmptyProxyUpstream = proxyUpstream !== undefined && proxyUpstream !== '';
|
|
143
|
+
if (!hasNonEmptyProxyUpstream) {
|
|
144
|
+
proxyUpstream = undefined;
|
|
145
|
+
}
|
|
79
146
|
|
|
80
147
|
return {
|
|
148
|
+
mode,
|
|
81
149
|
engineWire,
|
|
82
|
-
proxyUpstream
|
|
83
|
-
options?.proxyUpstream?.trim() || env.PYRIC_AI_PROXY_UPSTREAM?.trim() || undefined,
|
|
150
|
+
proxyUpstream,
|
|
84
151
|
};
|
|
85
152
|
}
|
|
@@ -144,6 +144,7 @@ export function attachViteFunctionsDevelopment(
|
|
|
144
144
|
registerUrl: options.registerUrl,
|
|
145
145
|
instance: options.instance ?? `${options.projectId}-default-rtdb`,
|
|
146
146
|
location: options.region ?? options.baseEnv.PYRIC_FUNCTIONS_RTDB_REGION ?? 'us-central1',
|
|
147
|
+
projectId: options.projectId,
|
|
147
148
|
readiness: createInProcessFunctionsPeerReadiness(bridge.sandboxConnected),
|
|
148
149
|
onEvent: (event) => reportEvent(options.logger, event),
|
|
149
150
|
...(options.childModuleUrl === undefined ? {} : { childModuleUrl: options.childModuleUrl }),
|
|
@@ -8,30 +8,82 @@ export function watchViteGenerationRules(input: {
|
|
|
8
8
|
session: SandboxSession;
|
|
9
9
|
}): (() => void) | null {
|
|
10
10
|
const { server, session } = input;
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const firestoreFile = session.summary.rules.firestore.sourcePath;
|
|
12
|
+
const databaseFile = session.summary.rules.database.sourcePath;
|
|
13
|
+
const hasFirestoreFile = firestoreFile !== null;
|
|
14
|
+
const hasDatabaseFile = databaseFile !== null;
|
|
15
|
+
const hasNeitherFile = !hasFirestoreFile && !hasDatabaseFile;
|
|
16
|
+
if (hasNeitherFile) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
13
19
|
|
|
14
20
|
let debounce: ReturnType<typeof setTimeout> | null = null;
|
|
15
21
|
const onRulesChange = (file: string): void => {
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
const resolvedFile = path.resolve(file);
|
|
23
|
+
let isFirestoreMatch = false;
|
|
24
|
+
if (hasFirestoreFile) {
|
|
25
|
+
const firestoreResolved = path.resolve(firestoreFile);
|
|
26
|
+
isFirestoreMatch = resolvedFile === firestoreResolved;
|
|
27
|
+
}
|
|
28
|
+
let isDatabaseMatch = false;
|
|
29
|
+
if (hasDatabaseFile) {
|
|
30
|
+
const databaseResolved = path.resolve(databaseFile);
|
|
31
|
+
isDatabaseMatch = resolvedFile === databaseResolved;
|
|
32
|
+
}
|
|
33
|
+
const isNeitherMatch = !isFirestoreMatch && !isDatabaseMatch;
|
|
34
|
+
if (isNeitherMatch) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const hasDebounce = debounce !== null;
|
|
38
|
+
if (hasDebounce) {
|
|
39
|
+
clearTimeout(debounce as ReturnType<typeof setTimeout>);
|
|
40
|
+
}
|
|
18
41
|
debounce = setTimeout(() => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
if (isFirestoreMatch) {
|
|
43
|
+
void session.reloadFirestoreRules().then((result) => {
|
|
44
|
+
const isReloaded = result.kind === 'reloaded';
|
|
45
|
+
if (isReloaded) {
|
|
46
|
+
server.config.logger.info(` ↻ [pyric] rules reloaded (${result.rulesHash})`);
|
|
47
|
+
} else {
|
|
48
|
+
const isRejected = result.kind === 'rejected';
|
|
49
|
+
if (isRejected) {
|
|
50
|
+
server.config.logger.warn(
|
|
51
|
+
` ⚠ [pyric] rules NOT reloaded (last-good stays live): ${result.error.message}`,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (isDatabaseMatch) {
|
|
58
|
+
void session.reloadDatabaseRules().then((result) => {
|
|
59
|
+
const isReloaded = result.kind === 'reloaded';
|
|
60
|
+
if (isReloaded) {
|
|
61
|
+
server.config.logger.info(` ↻ [pyric] rtdb rules reloaded (${result.rulesHash})`);
|
|
62
|
+
} else {
|
|
63
|
+
const isRejected = result.kind === 'rejected';
|
|
64
|
+
if (isRejected) {
|
|
65
|
+
server.config.logger.warn(
|
|
66
|
+
` ⚠ [pyric] rtdb rules NOT reloaded (last-good stays live): ${result.error.message}`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
28
72
|
}, 150);
|
|
29
73
|
};
|
|
30
74
|
|
|
31
|
-
|
|
75
|
+
if (hasFirestoreFile) {
|
|
76
|
+
server.watcher.add(firestoreFile);
|
|
77
|
+
}
|
|
78
|
+
if (hasDatabaseFile) {
|
|
79
|
+
server.watcher.add(databaseFile);
|
|
80
|
+
}
|
|
32
81
|
server.watcher.on('change', onRulesChange);
|
|
33
82
|
return () => {
|
|
34
|
-
|
|
83
|
+
const hasDebounce = debounce !== null;
|
|
84
|
+
if (hasDebounce) {
|
|
85
|
+
clearTimeout(debounce as ReturnType<typeof setTimeout>);
|
|
86
|
+
}
|
|
35
87
|
server.watcher.off('change', onRulesChange);
|
|
36
88
|
};
|
|
37
89
|
}
|