@pyric/cli 0.1.0-alpha.19 → 0.1.0-alpha.21
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 +64 -89
- package/dist/assurance/.generated/conformance-verdicts.d.ts +68 -1
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +68 -1
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/bridge/client/dispatch.d.ts +25 -19
- package/dist/bridge/client/dispatch.d.ts.map +1 -1
- package/dist/bridge/client/dispatch.js +41 -48
- package/dist/bridge/client/dispatch.js.map +1 -1
- package/dist/bridge/client/tool-family-factories.d.ts +26 -0
- package/dist/bridge/client/tool-family-factories.d.ts.map +1 -0
- package/dist/bridge/client/tool-family-factories.js +10 -0
- package/dist/bridge/client/tool-family-factories.js.map +1 -0
- package/dist/bridge/server/mcp-contract.d.ts +7 -6
- package/dist/bridge/server/mcp-contract.d.ts.map +1 -1
- package/dist/bridge/server/mcp-contract.js +9 -48
- package/dist/bridge/server/mcp-contract.js.map +1 -1
- package/dist/bridge/server/peer.d.ts +11 -1
- package/dist/bridge/server/peer.d.ts.map +1 -1
- package/dist/bridge/server/peer.js +22 -1
- package/dist/bridge/server/peer.js.map +1 -1
- package/dist/bridge/server/tool-family-factories.d.ts +30 -0
- package/dist/bridge/server/tool-family-factories.d.ts.map +1 -0
- package/dist/bridge/server/tool-family-factories.js +22 -0
- package/dist/bridge/server/tool-family-factories.js.map +1 -0
- package/dist/bridge/server/tool-metadata.d.ts +17 -18
- package/dist/bridge/server/tool-metadata.d.ts.map +1 -1
- package/dist/bridge/server/tool-metadata.js +24 -59
- package/dist/bridge/server/tool-metadata.js.map +1 -1
- package/dist/bridge/tool-families.d.ts +48 -0
- package/dist/bridge/tool-families.d.ts.map +1 -0
- package/dist/bridge/tool-families.generated.d.ts +32 -0
- package/dist/bridge/tool-families.generated.d.ts.map +1 -0
- package/dist/bridge/tool-families.generated.js +15 -0
- package/dist/bridge/tool-families.generated.js.map +1 -0
- package/dist/bridge/tool-families.js +51 -0
- package/dist/bridge/tool-families.js.map +1 -0
- package/dist/bridge/tool-family-records/conformance.d.ts +7 -0
- package/dist/bridge/tool-family-records/conformance.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/conformance.js +6 -0
- package/dist/bridge/tool-family-records/conformance.js.map +1 -0
- package/dist/bridge/tool-family-records/firestore-data.d.ts +7 -0
- package/dist/bridge/tool-family-records/firestore-data.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/firestore-data.js +15 -0
- package/dist/bridge/tool-family-records/firestore-data.js.map +1 -0
- package/dist/bridge/tool-family-records/firestore-inspect.d.ts +7 -0
- package/dist/bridge/tool-family-records/firestore-inspect.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/firestore-inspect.js +6 -0
- package/dist/bridge/tool-family-records/firestore-inspect.js.map +1 -0
- package/dist/bridge/tool-family-records/firestore-rules.d.ts +7 -0
- package/dist/bridge/tool-family-records/firestore-rules.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/firestore-rules.js +15 -0
- package/dist/bridge/tool-family-records/firestore-rules.js.map +1 -0
- package/dist/bridge/tool-family-records/firestore-simulator.d.ts +7 -0
- package/dist/bridge/tool-family-records/firestore-simulator.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/firestore-simulator.js +16 -0
- package/dist/bridge/tool-family-records/firestore-simulator.js.map +1 -0
- package/dist/bridge/tool-family-records/rtdb-inspection.d.ts +7 -0
- package/dist/bridge/tool-family-records/rtdb-inspection.d.ts.map +1 -0
- package/dist/bridge/tool-family-records/rtdb-inspection.js +6 -0
- package/dist/bridge/tool-family-records/rtdb-inspection.js.map +1 -0
- package/dist/bundler/externals.d.ts +37 -0
- package/dist/bundler/externals.d.ts.map +1 -0
- package/dist/bundler/externals.js +52 -0
- package/dist/bundler/externals.js.map +1 -0
- package/dist/bundler/index.d.ts +17 -0
- package/dist/bundler/index.d.ts.map +1 -0
- package/dist/bundler/index.js +17 -0
- package/dist/bundler/index.js.map +1 -0
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +48 -42
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/inlined-sdk-scanner.d.ts +6 -0
- package/dist/cli/inlined-sdk-scanner.d.ts.map +1 -0
- package/dist/cli/inlined-sdk-scanner.js +82 -0
- package/dist/cli/inlined-sdk-scanner.js.map +1 -0
- package/dist/cli/mcp-proxy.js +3 -3
- package/dist/cli/mcp-proxy.js.map +1 -1
- package/dist/cli/parse-args.d.ts +1 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +51 -15
- package/dist/cli/parse-args.js.map +1 -1
- package/dist/cli/pyric-config.d.ts +24 -0
- package/dist/cli/pyric-config.d.ts.map +1 -0
- package/dist/cli/pyric-config.js +28 -0
- package/dist/cli/pyric-config.js.map +1 -0
- package/dist/cli/sandbox-interlock.d.ts +97 -0
- package/dist/cli/sandbox-interlock.d.ts.map +1 -0
- package/dist/cli/sandbox-interlock.js +112 -0
- package/dist/cli/sandbox-interlock.js.map +1 -0
- package/dist/cli/{dev-runner.d.ts → sandbox-runner.d.ts} +53 -48
- package/dist/cli/sandbox-runner.d.ts.map +1 -0
- package/dist/cli/{dev-runner.js → sandbox-runner.js} +105 -67
- package/dist/cli/sandbox-runner.js.map +1 -0
- package/dist/cli/serve.d.ts +12 -14
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +155 -116
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/snapshot.js +5 -5
- package/dist/cli/snapshot.js.map +1 -1
- package/dist/cli/unsupported-runtime.d.ts +27 -0
- package/dist/cli/unsupported-runtime.d.ts.map +1 -0
- package/dist/cli/unsupported-runtime.js +63 -0
- package/dist/cli/unsupported-runtime.js.map +1 -0
- package/dist/cli/verify.js +1 -1
- package/dist/cli/verify.js.map +1 -1
- package/dist/conformance/.generated/can-i-use-browser.d.ts +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 +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 +37 -0
- package/dist/functions-rtdb/child.d.ts.map +1 -1
- package/dist/functions-rtdb/child.js +90 -21
- package/dist/functions-rtdb/child.js.map +1 -1
- package/dist/functions-rtdb/development-runtime.d.ts +3 -0
- package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
- package/dist/functions-rtdb/development-runtime.js +2 -1
- package/dist/functions-rtdb/development-runtime.js.map +1 -1
- package/dist/functions-rtdb/project.js +8 -8
- package/dist/functions-rtdb/project.js.map +1 -1
- package/dist/google-endpoints.d.ts +67 -0
- package/dist/google-endpoints.d.ts.map +1 -0
- package/dist/google-endpoints.js +119 -0
- package/dist/google-endpoints.js.map +1 -0
- package/dist/next/guard.js +1 -1
- package/dist/next/guard.js.map +1 -1
- package/dist/next/runtime-env.d.ts.map +1 -1
- package/dist/next/runtime-env.js +5 -0
- package/dist/next/runtime-env.js.map +1 -1
- package/dist/next/with-pyric.d.ts +1 -1
- package/dist/next/with-pyric.js +1 -1
- package/dist/register/beacon.d.ts +69 -0
- package/dist/register/beacon.d.ts.map +1 -0
- package/dist/register/beacon.js +199 -0
- package/dist/register/beacon.js.map +1 -0
- package/dist/register/index.d.ts.map +1 -1
- package/dist/register/index.js +65 -6
- package/dist/register/index.js.map +1 -1
- package/dist/register/net-guard.d.ts +110 -0
- package/dist/register/net-guard.d.ts.map +1 -0
- package/dist/register/net-guard.js +462 -0
- package/dist/register/net-guard.js.map +1 -0
- package/dist/remote/index.d.ts +1 -1
- package/dist/remote/index.js +9 -9
- package/dist/remote/index.js.map +1 -1
- package/dist/serve/ai-diagnostics-relay.d.ts +63 -0
- package/dist/serve/ai-diagnostics-relay.d.ts.map +1 -0
- package/dist/serve/ai-diagnostics-relay.js +125 -0
- package/dist/serve/ai-diagnostics-relay.js.map +1 -0
- package/dist/serve/ai-proxy.d.ts +92 -0
- package/dist/serve/ai-proxy.d.ts.map +1 -0
- package/dist/serve/ai-proxy.js +269 -0
- package/dist/serve/ai-proxy.js.map +1 -0
- package/dist/serve/ai-status.d.ts +44 -0
- package/dist/serve/ai-status.d.ts.map +1 -0
- package/dist/serve/ai-status.js +77 -0
- package/dist/serve/ai-status.js.map +1 -0
- package/dist/serve/ai-terminal-blocks.d.ts +97 -0
- package/dist/serve/ai-terminal-blocks.d.ts.map +1 -0
- package/dist/serve/ai-terminal-blocks.js +128 -0
- package/dist/serve/ai-terminal-blocks.js.map +1 -0
- package/dist/serve/ai-terminal-text.d.ts +36 -0
- package/dist/serve/ai-terminal-text.d.ts.map +1 -0
- package/dist/serve/ai-terminal-text.js +48 -0
- package/dist/serve/ai-terminal-text.js.map +1 -0
- package/dist/serve/beacon-route.d.ts +53 -0
- package/dist/serve/beacon-route.d.ts.map +1 -0
- package/dist/serve/beacon-route.js +101 -0
- package/dist/serve/beacon-route.js.map +1 -0
- package/dist/serve/bundler.js +10 -10
- package/dist/serve/bundler.js.map +1 -1
- package/dist/serve/entries/active-auth-registry.d.ts +16 -0
- package/dist/serve/entries/active-auth-registry.d.ts.map +1 -0
- package/dist/serve/entries/active-auth-registry.js +48 -0
- package/dist/serve/entries/active-auth-registry.js.map +1 -0
- package/dist/serve/entries/active-auth.d.ts +18 -0
- package/dist/serve/entries/active-auth.d.ts.map +1 -0
- package/dist/serve/entries/active-auth.js +84 -0
- package/dist/serve/entries/active-auth.js.map +1 -0
- package/dist/serve/entries/ai.d.ts.map +1 -1
- package/dist/serve/entries/ai.js +27 -1
- package/dist/serve/entries/ai.js.map +1 -1
- package/dist/serve/entries/auth-helper-core.d.ts +1 -0
- package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
- package/dist/serve/entries/auth-helper-core.js +4 -0
- package/dist/serve/entries/auth-helper-core.js.map +1 -1
- package/dist/serve/entries/auth-helper-dom.d.ts.map +1 -1
- package/dist/serve/entries/auth-helper-dom.js +29 -3
- package/dist/serve/entries/auth-helper-dom.js.map +1 -1
- package/dist/serve/entries/auth-helper-runtime.js +1 -1
- package/dist/serve/entries/auth-helper-runtime.js.map +1 -1
- package/dist/serve/entries/auth.d.ts.map +1 -1
- package/dist/serve/entries/auth.js +8 -0
- package/dist/serve/entries/auth.js.map +1 -1
- package/dist/serve/entries/bridge-url.d.ts +1 -1
- package/dist/serve/entries/bridge-url.js +1 -1
- package/dist/serve/entries/firestore.js +3 -3
- 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 +70 -4
- package/dist/serve/entries/init.js.map +1 -1
- package/dist/serve/entries/keepalive.js +1 -1
- package/dist/serve/entries/keepalive.js.map +1 -1
- package/dist/serve/entries/runtime.d.ts.map +1 -1
- package/dist/serve/entries/runtime.js +30 -14
- package/dist/serve/entries/runtime.js.map +1 -1
- package/dist/serve/entries/storage.js +1 -1
- package/dist/serve/entries/storage.js.map +1 -1
- package/dist/serve/entries/worker-runtime.js +1 -1
- package/dist/serve/entries/worker-runtime.js.map +1 -1
- package/dist/serve/init-payload.d.ts +4 -0
- package/dist/serve/init-payload.d.ts.map +1 -1
- package/dist/serve/namespace.d.ts +20 -5
- package/dist/serve/namespace.d.ts.map +1 -1
- package/dist/serve/namespace.js +93 -129
- package/dist/serve/namespace.js.map +1 -1
- package/dist/serve/rules.d.ts.map +1 -1
- package/dist/serve/rules.js +44 -21
- package/dist/serve/rules.js.map +1 -1
- package/dist/serve/runtime/chip-config.d.ts.map +1 -1
- package/dist/serve/runtime/chip-config.js +16 -2
- package/dist/serve/runtime/chip-config.js.map +1 -1
- package/dist/serve/runtime/chip-dialog.d.ts +18 -0
- package/dist/serve/runtime/chip-dialog.d.ts.map +1 -0
- package/dist/serve/runtime/chip-dialog.js +315 -0
- package/dist/serve/runtime/chip-dialog.js.map +1 -0
- package/dist/serve/runtime/chip-install.d.ts +2 -0
- package/dist/serve/runtime/chip-install.d.ts.map +1 -1
- package/dist/serve/runtime/chip-install.js +9 -4
- package/dist/serve/runtime/chip-install.js.map +1 -1
- package/dist/serve/runtime/chip-user-search.d.ts +16 -0
- package/dist/serve/runtime/chip-user-search.d.ts.map +1 -0
- package/dist/serve/runtime/chip-user-search.js +354 -0
- package/dist/serve/runtime/chip-user-search.js.map +1 -0
- package/dist/serve/runtime/chip.d.ts +10 -0
- package/dist/serve/runtime/chip.d.ts.map +1 -1
- package/dist/serve/runtime/chip.js +149 -15
- package/dist/serve/runtime/chip.js.map +1 -1
- package/dist/serve/runtime/identity.d.ts +17 -0
- package/dist/serve/runtime/identity.d.ts.map +1 -0
- package/dist/serve/runtime/identity.js +10 -0
- package/dist/serve/runtime/identity.js.map +1 -0
- package/dist/serve/runtime/manifest.d.ts +1 -1
- package/dist/serve/runtime/manifest.d.ts.map +1 -1
- package/dist/serve/runtime/manifest.js +1 -1
- package/dist/serve/runtime/manifest.js.map +1 -1
- package/dist/serve/runtime/status.d.ts.map +1 -1
- package/dist/serve/runtime/status.js +23 -0
- package/dist/serve/runtime/status.js.map +1 -1
- package/dist/serve/sandbox-session.d.ts +8 -0
- package/dist/serve/sandbox-session.d.ts.map +1 -1
- package/dist/serve/sandbox-session.js +12 -4
- package/dist/serve/sandbox-session.js.map +1 -1
- package/dist/serve/server.d.ts +7 -0
- package/dist/serve/server.d.ts.map +1 -1
- package/dist/serve/server.js +15 -1
- package/dist/serve/server.js.map +1 -1
- package/dist/serve/site-ui/404.html +1 -1
- package/dist/serve/site-ui/_astro/{RulesCodeEditor.Bl-XMkhD.js → RulesCodeEditor.DsTAsKIa.js} +1 -1
- package/dist/serve/site-ui/_astro/_slug_.Da5VLhW1.css +1 -0
- package/dist/serve/site-ui/_astro/_studio_.BnfYCKoI.css +1 -0
- package/dist/serve/site-ui/_astro/app.BOr2kwae.js +115 -0
- package/dist/serve/site-ui/_astro/app.DhAcImFD.js +1 -0
- package/dist/serve/site-ui/_astro/app.pMSnN6Qw.css +1 -0
- package/dist/serve/site-ui/_astro/{chess-showcase.Dh5D8kqe.js → chess-showcase.Bn_pP6UJ.js} +2 -2
- package/dist/serve/site-ui/_astro/{example-runtime.CuyAjjiG.js → example-runtime.CXopTGv7.js} +1 -1
- package/dist/serve/site-ui/_astro/index.Tb-31efc.css +1 -0
- package/dist/serve/site-ui/_astro/index.UkCBr-_0.css +1 -0
- package/dist/serve/site-ui/_astro/sandbox-controls.rOuZTOUG.js +510 -0
- package/dist/serve/site-ui/_astro/{seed.CSUkloMi.js → seed.03a08f9t.js} +2 -2
- package/dist/serve/site-ui/_astro/writes.BsPBG3dp.js +653 -0
- package/dist/serve/site-ui/auth/index.html +5 -3
- package/dist/serve/site-ui/david-east.jpg +0 -0
- package/dist/serve/site-ui/docs/_rhythm/index.html +6 -3
- package/dist/serve/site-ui/docs/_rhythm.md +1 -1
- package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +18 -15
- package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +16 -16
- package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +6 -5
- package/dist/serve/site-ui/docs/agent/watch-and-review.md +1 -5
- package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +8 -5
- package/dist/serve/site-ui/docs/agent/work-with-an-agent.md +4 -4
- package/dist/serve/site-ui/docs/ai-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/api-reference/index.html +13 -2
- package/dist/serve/site-ui/docs/api-reference.md +8 -0
- package/dist/serve/site-ui/docs/app-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/auth-compat/index.html +7 -4
- package/dist/serve/site-ui/docs/auth-compat.md +2 -2
- package/dist/serve/site-ui/docs/build/ai-logic/index.html +10 -2
- package/dist/serve/site-ui/docs/build/ai-logic.md +6 -0
- package/dist/serve/site-ui/docs/build/authentication/index.html +7 -4
- package/dist/serve/site-ui/docs/build/authentication.md +2 -2
- package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +5 -2
- package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +5 -2
- package/dist/serve/site-ui/docs/build/cloud-storage/index.html +6 -3
- package/dist/serve/site-ui/docs/build/cloud-storage.md +1 -1
- package/dist/serve/site-ui/docs/build/realtime-database/index.html +9 -6
- package/dist/serve/site-ui/docs/build/realtime-database.md +4 -4
- package/dist/serve/site-ui/docs/conformance-scores/index.html +10 -3
- package/dist/serve/site-ui/docs/conformance-scores.md +5 -1
- package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/create-pyric-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/database-compat/index.html +48 -45
- package/dist/serve/site-ui/docs/database-compat.md +43 -43
- package/dist/serve/site-ui/docs/examples/chess/index.html +5 -2
- package/dist/serve/site-ui/docs/examples/index.html +5 -2
- package/dist/serve/site-ui/docs/firestore-compat/index.html +8 -5
- package/dist/serve/site-ui/docs/firestore-compat.md +3 -3
- package/dist/serve/site-ui/docs/firestore-flutter-compat/index.html +319 -0
- package/dist/serve/site-ui/docs/firestore-flutter-compat.md +344 -0
- package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/get-started/backend-bundlers/index.html +105 -0
- package/dist/serve/site-ui/docs/get-started/backend-bundlers.md +165 -0
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +9 -6
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works.md +5 -5
- package/dist/serve/site-ui/docs/get-started/nextjs/index.html +9 -6
- package/dist/serve/site-ui/docs/get-started/nextjs.md +4 -4
- package/dist/serve/site-ui/docs/get-started/start-building/index.html +14 -9
- package/dist/serve/site-ui/docs/get-started/start-building.md +16 -10
- package/dist/serve/site-ui/docs/get-started/vite/index.html +6 -3
- package/dist/serve/site-ui/docs/get-started/vite.md +1 -1
- package/dist/serve/site-ui/docs/index.json +3128 -1613
- package/dist/serve/site-ui/docs/messaging-compat/index.html +5 -2
- package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +5 -2
- package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +6 -4
- package/dist/serve/site-ui/docs/observe/see-whats-happening.md +2 -4
- package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +9 -6
- package/dist/serve/site-ui/docs/observe/shape-your-data.md +4 -4
- package/dist/serve/site-ui/docs/overview/index.html +16 -10
- package/dist/serve/site-ui/docs/overview.md +19 -11
- package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +8 -5
- package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +3 -3
- package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +501 -0
- package/dist/serve/site-ui/docs/pyric-admin-reference-api.md +587 -0
- package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-analytics-reference-api/index.html +124 -0
- package/dist/serve/site-ui/docs/pyric-analytics-reference-api.md +287 -0
- package/dist/serve/site-ui/docs/pyric-app-check-reference-api/index.html +87 -0
- package/dist/serve/site-ui/docs/pyric-app-check-reference-api.md +199 -0
- package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +10 -3
- package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +2 -1
- package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api/index.html +56 -0
- package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api.md +72 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +6 -2
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api.md +1 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +6 -2
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api.md +1 -0
- package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +39 -11
- package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +17 -9
- package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +137 -94
- package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +61 -1
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api.md +2 -2
- package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +167 -96
- package/dist/serve/site-ui/docs/pyric-database-reference-api.md +108 -2
- package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api/index.html +559 -0
- package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api.md +1240 -0
- package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +44 -12
- package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +18 -8
- package/dist/serve/site-ui/docs/pyric-functions-reference-api/index.html +67 -0
- package/dist/serve/site-ui/docs/pyric-functions-reference-api.md +149 -0
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +10 -4
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api.md +5 -2
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +10 -4
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api.md +5 -2
- package/dist/serve/site-ui/docs/pyric-performance-reference-api/index.html +35 -0
- package/dist/serve/site-ui/docs/pyric-performance-reference-api.md +69 -0
- package/dist/serve/site-ui/docs/pyric-remote-config-reference-api/index.html +132 -0
- package/dist/serve/site-ui/docs/pyric-remote-config-reference-api.md +307 -0
- package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +56 -18
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +48 -9
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api.md +2 -2
- package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +243 -50
- package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +148 -31
- package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +26 -5
- package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +24 -2
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +30 -97
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api.md +20 -51
- package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +6 -3
- package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +128 -27
- package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api.md +58 -5
- package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +8 -6
- package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +3 -4
- package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +5 -2
- package/dist/serve/site-ui/docs/reference/cli/index.html +156 -0
- package/dist/serve/site-ui/docs/reference/cli.md +120 -0
- package/dist/serve/site-ui/docs/rules-compat/index.html +14 -3
- package/dist/serve/site-ui/docs/rules-compat.md +9 -1
- package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +6 -3
- package/dist/serve/site-ui/docs/secure/read-a-denial.md +1 -1
- package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +5 -2
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +5 -2
- package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +7 -4
- package/dist/serve/site-ui/docs/ship/ship-to-production.md +2 -2
- package/dist/serve/site-ui/docs/ship/test-in-node/index.html +9 -6
- package/dist/serve/site-ui/docs/ship/test-in-node.md +4 -4
- package/dist/serve/site-ui/docs/storage-compat/index.html +17 -14
- package/dist/serve/site-ui/docs/storage-compat.md +12 -12
- package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +5 -2
- package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +5 -2
- package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +5 -2
- package/dist/serve/site-ui/docs/tutorial/index.html +10 -7
- package/dist/serve/site-ui/docs/tutorial.md +4 -4
- package/dist/serve/site-ui/examples/chess/index.html +4 -2
- package/dist/serve/site-ui/firestore/index.html +5 -3
- package/dist/serve/site-ui/hero-charcoal.jpg +0 -0
- package/dist/serve/site-ui/index.html +9 -7
- package/dist/serve/site-ui/llms.txt +13 -3
- package/dist/serve/site-ui/pyric-campfire-full.png +0 -0
- package/dist/serve/site-ui/pyric-campfire.png +0 -0
- package/dist/serve/site-ui/rtdb/index.html +5 -3
- package/dist/serve/site-ui/settings/index.html +5 -3
- package/dist/serve/site-ui/storage/index.html +5 -3
- package/dist/serve/site-ui/studio/index.html +13 -0
- package/dist/serve/site-ui/studio-routes.json +1 -1
- package/dist/serve/site-ui/traffic/index.html +5 -3
- package/dist/serve/studio/disk-workspace.d.ts.map +1 -1
- package/dist/serve/studio/disk-workspace.js +64 -2
- package/dist/serve/studio/disk-workspace.js.map +1 -1
- package/dist/serve/studio/routes.d.ts +9 -0
- package/dist/serve/studio/routes.d.ts.map +1 -1
- package/dist/serve/studio/routes.js +47 -7
- package/dist/serve/studio/routes.js.map +1 -1
- package/dist/serve/vite-ai-config.d.ts.map +1 -1
- package/dist/serve/vite-ai-config.js +38 -8
- package/dist/serve/vite-ai-config.js.map +1 -1
- package/dist/serve/vite-module-swap.d.ts.map +1 -1
- package/dist/serve/vite-module-swap.js +0 -28
- package/dist/serve/vite-module-swap.js.map +1 -1
- package/dist/serve/vite-plugin.d.ts +7 -7
- package/dist/serve/vite-plugin.js +1 -1
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-sandbox-generation.d.ts +1 -1
- package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
- package/dist/serve/vite-sandbox-generation.js +13 -1
- package/dist/serve/vite-sandbox-generation.js.map +1 -1
- package/dist/serve/worker/client/auth.js +1 -2
- package/dist/serve/worker/client/auth.js.map +1 -1
- package/dist/serve/worker/client/core.d.ts +21 -1
- package/dist/serve/worker/client/core.d.ts.map +1 -1
- package/dist/serve/worker/client/core.js +79 -3
- package/dist/serve/worker/client/core.js.map +1 -1
- package/dist/serve/worker/client/disconnect.js +1 -1
- package/dist/serve/worker/client/disconnect.js.map +1 -1
- package/dist/serve/worker/client/presence.d.ts.map +1 -1
- package/dist/serve/worker/client/presence.js +18 -5
- package/dist/serve/worker/client/presence.js.map +1 -1
- package/dist/serve/worker/client.d.ts +1 -1
- package/dist/serve/worker/client.d.ts.map +1 -1
- package/dist/serve/worker/client.js +1 -1
- package/dist/serve/worker/client.js.map +1 -1
- package/dist/serve/worker/context-resolver.d.ts +30 -0
- package/dist/serve/worker/context-resolver.d.ts.map +1 -0
- package/dist/serve/worker/context-resolver.js +44 -0
- package/dist/serve/worker/context-resolver.js.map +1 -0
- package/dist/serve/worker/entry.js +23 -19
- package/dist/serve/worker/entry.js.map +1 -1
- package/dist/serve/worker/host/core.d.ts +1 -0
- package/dist/serve/worker/host/core.d.ts.map +1 -1
- package/dist/serve/worker/host/core.js +12 -6
- package/dist/serve/worker/host/core.js.map +1 -1
- package/dist/serve/worker/host/storage.js +2 -2
- package/dist/serve/worker/host-ai.d.ts.map +1 -1
- package/dist/serve/worker/host-ai.js +15 -0
- package/dist/serve/worker/host-ai.js.map +1 -1
- package/dist/serve/worker/host-auth.js +1 -2
- package/dist/serve/worker/host-auth.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 +2 -2
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/port-lifecycle.d.ts +18 -0
- package/dist/serve/worker/port-lifecycle.d.ts.map +1 -0
- package/dist/serve/worker/port-lifecycle.js +28 -0
- package/dist/serve/worker/port-lifecycle.js.map +1 -0
- package/dist/serve/worker/protocol.d.ts +4 -0
- package/dist/serve/worker/protocol.d.ts.map +1 -1
- package/dist/serve/worker/protocol.js.map +1 -1
- package/dist/serve/worker/serve-init.d.ts.map +1 -1
- package/dist/serve/worker/serve-init.js +15 -3
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/dist/verify/fixture.d.ts +1 -1
- package/package.json +17 -6
- package/src/assurance/.generated/conformance-verdicts.ts +68 -1
- package/src/bridge/client/dispatch.ts +52 -56
- package/src/bridge/client/tool-family-factories.ts +34 -0
- package/src/bridge/server/mcp-contract.ts +15 -59
- package/src/bridge/server/peer.ts +24 -1
- package/src/bridge/server/tool-family-factories.ts +40 -0
- package/src/bridge/server/tool-metadata.ts +29 -61
- package/src/bridge/tool-families.generated.ts +17 -0
- package/src/bridge/tool-families.ts +87 -0
- package/src/bridge/tool-family-records/conformance.ts +6 -0
- package/src/bridge/tool-family-records/firestore-data.ts +15 -0
- package/src/bridge/tool-family-records/firestore-inspect.ts +6 -0
- package/src/bridge/tool-family-records/firestore-rules.ts +15 -0
- package/src/bridge/tool-family-records/firestore-simulator.ts +16 -0
- package/src/bridge/tool-family-records/rtdb-inspection.ts +6 -0
- package/src/bundler/externals.ts +55 -0
- package/src/bundler/index.ts +21 -0
- package/src/cli/cli.test.ts +2 -46
- package/src/cli/index.ts +48 -42
- package/src/cli/inlined-sdk-scanner.ts +77 -0
- package/src/cli/mcp-proxy.ts +4 -4
- package/src/cli/parse-args.ts +61 -15
- package/src/cli/pyric-config.ts +45 -0
- package/src/cli/sandbox-interlock.ts +167 -0
- package/src/cli/{dev-runner.ts → sandbox-runner.ts} +142 -86
- package/src/cli/serve.ts +182 -115
- package/src/cli/snapshot.ts +5 -5
- package/src/cli/unsupported-runtime.ts +68 -0
- package/src/cli/verify.ts +1 -1
- package/src/conformance/.generated/can-i-use-browser.ts +2 -2
- package/src/conformance/.generated/can-i-use.ts +2 -2
- package/src/conformance/.generated/conformance-docs.ts +1 -1
- package/src/functions-rtdb/child.ts +115 -21
- package/src/functions-rtdb/development-runtime.ts +5 -1
- package/src/functions-rtdb/project.ts +8 -8
- package/src/google-endpoints.ts +155 -0
- package/src/next/guard.ts +1 -1
- package/src/next/runtime-env.ts +5 -0
- package/src/next/with-pyric.ts +1 -1
- package/src/register/beacon.ts +232 -0
- package/src/register/index.ts +68 -6
- package/src/register/net-guard.ts +567 -0
- package/src/remote/index.ts +9 -9
- package/src/serve/ai-diagnostics-relay.ts +243 -0
- package/src/serve/ai-proxy.ts +327 -0
- package/src/serve/ai-status.ts +109 -0
- package/src/serve/ai-terminal-blocks.ts +210 -0
- package/src/serve/ai-terminal-text.ts +52 -0
- package/src/serve/beacon-route.ts +141 -0
- package/src/serve/bundler.ts +10 -10
- package/src/serve/entries/active-auth-registry.ts +56 -0
- package/src/serve/entries/active-auth.ts +100 -0
- package/src/serve/entries/ai.ts +27 -1
- package/src/serve/entries/auth-helper-core.ts +5 -0
- package/src/serve/entries/auth-helper-dom.ts +27 -3
- package/src/serve/entries/auth-helper-runtime.ts +1 -1
- package/src/serve/entries/auth.ts +8 -0
- package/src/serve/entries/bridge-url.ts +1 -1
- package/src/serve/entries/firestore.ts +3 -3
- package/src/serve/entries/init.ts +78 -3
- package/src/serve/entries/keepalive.ts +1 -1
- package/src/serve/entries/runtime.ts +29 -14
- package/src/serve/entries/storage.ts +1 -1
- package/src/serve/entries/worker-runtime.ts +1 -1
- package/src/serve/init-payload.ts +4 -0
- package/src/serve/namespace.ts +117 -145
- package/src/serve/rules.ts +47 -22
- package/src/serve/runtime/chip-config.ts +16 -2
- package/src/serve/runtime/chip-dialog.ts +366 -0
- package/src/serve/runtime/chip-install.ts +10 -4
- package/src/serve/runtime/chip-user-search.ts +391 -0
- package/src/serve/runtime/chip.ts +177 -15
- package/src/serve/runtime/identity.ts +26 -0
- package/src/serve/runtime/manifest.ts +1 -1
- package/src/serve/runtime/status.ts +24 -0
- package/src/serve/sandbox-session.ts +19 -4
- package/src/serve/server.ts +18 -1
- package/src/serve/studio/disk-workspace.ts +76 -2
- package/src/serve/studio/routes.ts +63 -7
- package/src/serve/vite-ai-config.ts +37 -7
- package/src/serve/vite-module-swap.ts +0 -28
- package/src/serve/vite-plugin.ts +8 -8
- package/src/serve/vite-sandbox-generation.ts +16 -1
- package/src/serve/worker/client/auth.ts +1 -1
- package/src/serve/worker/client/core.ts +80 -3
- package/src/serve/worker/client/disconnect.ts +1 -1
- package/src/serve/worker/client/presence.ts +25 -5
- package/src/serve/worker/client.ts +1 -1
- package/src/serve/worker/context-resolver.ts +60 -0
- package/src/serve/worker/entry.ts +22 -18
- package/src/serve/worker/host/core.ts +9 -7
- package/src/serve/worker/host/storage.ts +2 -2
- package/src/serve/worker/host-ai.ts +15 -0
- package/src/serve/worker/host-auth.ts +1 -1
- package/src/serve/worker/index.ts +4 -1
- package/src/serve/worker/port-lifecycle.ts +45 -0
- package/src/serve/worker/protocol.ts +2 -1
- package/src/serve/worker/serve-init.ts +14 -3
- package/src/verify/fixture.ts +1 -1
- package/README.md.orig +0 -145
- package/dist/cli/dev-runner.d.ts.map +0 -1
- package/dist/cli/dev-runner.js.map +0 -1
- package/dist/serve/site-ui/_astro/_slug_.CXh9yTP1.css +0 -1
- package/dist/serve/site-ui/_astro/_slug_.CupVK4TM.css +0 -1
- package/dist/serve/site-ui/_astro/_studio_.CfxiQWkk.css +0 -1
- package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +0 -1
- package/dist/serve/site-ui/_astro/app.Ce3MTLQm.js +0 -1
- package/dist/serve/site-ui/_astro/app.taqzyjD0.js +0 -11
- package/dist/serve/site-ui/_astro/sandbox-controls.BP4M5f1M.js +0 -1169
- package/dist/serve/site-ui/_astro/writes.C57paAj2.js +0 -99
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +0 -582
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +0 -448
package/src/cli/serve.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `pyric
|
|
2
|
+
* `pyric sandbox` is the local server with the Pyric sandbox standing in for
|
|
3
3
|
* Firebase. Feels like `firebase serve` (banner, labeled lines, port 3473,
|
|
4
4
|
* SIGINT shutdown) with the sandbox-flavored extras firebase can't do: the
|
|
5
5
|
* served page runs an in-browser backend, your `firestore.rules` deploy into
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* rules load (fail fast on broken rules) → SDK bundle (cached per pyric
|
|
11
11
|
* version) → static server with the `/__pyric/` namespace + HTML injection.
|
|
12
12
|
*/
|
|
13
|
+
import { randomBytes } from 'node:crypto';
|
|
13
14
|
import { join, relative, resolve } from 'node:path';
|
|
14
|
-
import { existsSync,
|
|
15
|
+
import { existsSync, watch as watchFile } from 'node:fs';
|
|
15
16
|
import type { ParsedArgs } from './parse-args.js';
|
|
16
17
|
import { readFirebaseJson, readFirebaseRc, type FirebaseJson } from './firebase-json.js';
|
|
17
18
|
import { bundleSdk, bundleWorker, defaultSdkEntries, resolveSiteUiDir } from '../serve/bundler.js';
|
|
@@ -22,23 +23,30 @@ import {
|
|
|
22
23
|
embeddedWorkerVersion,
|
|
23
24
|
} from '../serve/standalone-assets.js';
|
|
24
25
|
import { hasSandboxBuildMarker } from '../serve/sandbox-marker.js';
|
|
26
|
+
import { formatBeaconReceipt } from '../serve/beacon-route.js';
|
|
25
27
|
import type { InitPayload } from '../serve/namespace.js';
|
|
28
|
+
import { formatAiStatusLine } from '../serve/ai-status.js';
|
|
26
29
|
import { injectServeTags } from '../serve/html-injection.js';
|
|
27
30
|
import { formatActivityWarning } from '../serve/activity-warning.js';
|
|
28
31
|
import { consoleServeLogger, startStaticServer, stderrServeLogger, type ServeHandle } from '../serve/server.js';
|
|
29
32
|
import { createBridgeMount } from '../serve/bridge-mount.js';
|
|
30
33
|
import { openBrowser, shouldAutoOpen } from '../serve/open-browser.js';
|
|
34
|
+
import { readPyricConfig, type PyricConfig } from './pyric-config.js';
|
|
31
35
|
import {
|
|
32
36
|
buildChildEnv,
|
|
33
|
-
detectPackageManager,
|
|
34
37
|
formatStartupEnvExport,
|
|
35
|
-
readDevScript,
|
|
36
38
|
registerModuleUrl,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
resolveSandboxChild,
|
|
40
|
+
spawnSandboxChild,
|
|
39
41
|
waitForSandboxPeer,
|
|
40
|
-
type
|
|
41
|
-
} from './
|
|
42
|
+
type SandboxChildHandle,
|
|
43
|
+
} from './sandbox-runner.js';
|
|
44
|
+
import {
|
|
45
|
+
reportLaunchChecks,
|
|
46
|
+
startBeaconWatchdog,
|
|
47
|
+
type BeaconWatchdog,
|
|
48
|
+
} from './sandbox-interlock.js';
|
|
49
|
+
import { scanForInlinedFirebase } from './inlined-sdk-scanner.js';
|
|
42
50
|
import {
|
|
43
51
|
createFunctionsDevelopmentRuntime,
|
|
44
52
|
createHttpFunctionsPeerReadiness,
|
|
@@ -60,7 +68,7 @@ interface HostingConfig {
|
|
|
60
68
|
rewrites?: Array<{ source?: string; destination?: string }>;
|
|
61
69
|
}
|
|
62
70
|
|
|
63
|
-
/** Extract the single hosting config `pyric
|
|
71
|
+
/** Extract the single hosting config `pyric sandbox` supports. Arrays
|
|
64
72
|
* (multi-site) take the first entry with a warning — multi-site is out of
|
|
65
73
|
* scope (plan section 6). */
|
|
66
74
|
export function extractHosting(config: FirebaseJson | null): HostingConfig | null {
|
|
@@ -84,11 +92,17 @@ export interface ServeRuntime {
|
|
|
84
92
|
payload: () => InitPayload;
|
|
85
93
|
/** HTTP MCP endpoint when `--bridge` is on; null otherwise. */
|
|
86
94
|
mcpUrl: string | null;
|
|
87
|
-
/** The Studio
|
|
95
|
+
/** The Studio hub URL (`/__pyric/ui/studio`) when `--ui` is on and the build is
|
|
88
96
|
* present; null otherwise. */
|
|
89
97
|
uiUrl: string | null;
|
|
90
98
|
/** Persistence summary (null when `--persist` is off). */
|
|
91
99
|
persist: { restoredDocs: number; restoredUsers: number } | null;
|
|
100
|
+
/** Handshake beacons posted to `/__pyric/beacon` so far, the interlock
|
|
101
|
+
* watchdog's only input. */
|
|
102
|
+
beaconCount: () => number;
|
|
103
|
+
/** The per-launch secret a beacon must present, placed in every child's
|
|
104
|
+
* `PYRIC_BEACON_TOKEN`. */
|
|
105
|
+
beaconToken: string;
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
/** The `--json` stdout contract — one line, keep stable; agents parse this.
|
|
@@ -147,17 +161,25 @@ export async function startServe(opts: {
|
|
|
147
161
|
* (the served project's file tree) + `/__pyric/projects` (single-project
|
|
148
162
|
* store over `cwd`). The Studio app's `local` mode talks to these. */
|
|
149
163
|
ui?: boolean;
|
|
164
|
+
/** Explicit opt-in to permissive mode (default-allow RTDB rules when unconfigured). */
|
|
165
|
+
permissive?: boolean;
|
|
150
166
|
logger?: Parameters<typeof startStaticServer>[0]['logger'];
|
|
151
167
|
}): Promise<ServeRuntime> {
|
|
152
168
|
const logger = opts.logger ?? consoleServeLogger();
|
|
153
169
|
|
|
170
|
+
// Handshake beacons from pyric-launched children, plus the per-launch secret
|
|
171
|
+
// that authorizes one. Both live here because the route does.
|
|
172
|
+
let beaconsSeen = 0;
|
|
173
|
+
const beaconCount = (): number => beaconsSeen;
|
|
174
|
+
const beaconToken = randomBytes(24).toString('base64url');
|
|
175
|
+
|
|
154
176
|
// --fresh only means anything against the state.json file `--persist`
|
|
155
177
|
// maintains — without `--persist` there is no file to discard, so
|
|
156
178
|
// `--fresh` alone was a silent no-op (nothing happened, nothing said so).
|
|
157
179
|
// Fail fast instead of pretending to reset something.
|
|
158
180
|
if (opts.fresh && !opts.persist) {
|
|
159
181
|
throw new Error(
|
|
160
|
-
'pyric
|
|
182
|
+
'pyric sandbox: --fresh requires --persist (it discards .pyric/state/state.json). ' +
|
|
161
183
|
'Browser-stored data is cleared from Studio → Settings → Reset, or DevTools → Clear site data.',
|
|
162
184
|
);
|
|
163
185
|
}
|
|
@@ -172,9 +194,29 @@ export async function startServe(opts: {
|
|
|
172
194
|
logger.note(' ⚠ no firebase.json found — serving the current directory without hosting config');
|
|
173
195
|
}
|
|
174
196
|
|
|
197
|
+
const pyricConfig = await readPyricConfig(opts.cwd);
|
|
198
|
+
if (pyricConfig.rules) {
|
|
199
|
+
if (!config) config = {};
|
|
200
|
+
if (typeof pyricConfig.rules === 'string') {
|
|
201
|
+
config.firestore = { ...config.firestore, rules: pyricConfig.rules };
|
|
202
|
+
} else {
|
|
203
|
+
if (pyricConfig.rules.firestore) {
|
|
204
|
+
config.firestore = { ...config.firestore, rules: pyricConfig.rules.firestore };
|
|
205
|
+
}
|
|
206
|
+
if (pyricConfig.rules.database) {
|
|
207
|
+
config.database = { ...config.database, rules: pyricConfig.rules.database };
|
|
208
|
+
}
|
|
209
|
+
if (pyricConfig.rules.storage) {
|
|
210
|
+
const baseStorage =
|
|
211
|
+
typeof config.storage === 'object' && !Array.isArray(config.storage) ? config.storage : {};
|
|
212
|
+
config.storage = { ...baseStorage, rules: pyricConfig.rules.storage };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
175
217
|
const hosting = extractHosting(config);
|
|
176
218
|
if (Array.isArray(config?.hosting) && (config.hosting as unknown[]).length > 1) {
|
|
177
|
-
logger.note(' ⚠ multiple hosting sites configured
|
|
219
|
+
logger.note(' ⚠ multiple hosting sites configured. pyric sandbox serves the first entry only');
|
|
178
220
|
}
|
|
179
221
|
const publicDir = resolve(opts.cwd, hosting?.public ?? '.');
|
|
180
222
|
if (!existsSync(publicDir)) {
|
|
@@ -184,31 +226,31 @@ export async function startServe(opts: {
|
|
|
184
226
|
const looksLikeBuildOutput = /(^|[\\/])(dist|build|out)$/.test(publicDir);
|
|
185
227
|
const hint = looksLikeBuildOutput
|
|
186
228
|
? `\n No build yet? Run \`bun run dev\` for the live sandbox dev server, ` +
|
|
187
|
-
`or \`bun run build\` then \`pyric
|
|
229
|
+
`or \`bun run build\` then \`pyric sandbox\` to preview the production build.`
|
|
188
230
|
: '';
|
|
189
|
-
throw new Error(`pyric
|
|
231
|
+
throw new Error(`pyric sandbox: hosting.public directory does not exist: ${publicDir}${hint}`);
|
|
190
232
|
}
|
|
191
233
|
|
|
192
234
|
// The import map can only remap BARE `firebase/*` specifiers. A plain bundler
|
|
193
235
|
// build (`vite build`) inlines the real SDK into the app chunk, leaving
|
|
194
|
-
// nothing to intercept
|
|
236
|
+
// nothing to intercept: the page would then talk to REAL Firebase endpoints
|
|
195
237
|
// with the sandbox's fake credentials while the injected banner claims
|
|
196
|
-
// otherwise. That hole is structural, so `pyric
|
|
238
|
+
// otherwise. That hole is structural, so `pyric sandbox` refuses such a dist
|
|
197
239
|
// rather than serving it. A pyric SANDBOX build (`vite build --mode
|
|
198
240
|
// development`) carries the marker and bundles pyric's in-page adapters, so it
|
|
199
|
-
// is trusted and the scan is skipped (marker present
|
|
241
|
+
// is trusted and the scan is skipped (marker present, no real SDK to find).
|
|
200
242
|
if (!hasSandboxBuildMarker(publicDir)) {
|
|
201
243
|
const inlined = scanForInlinedFirebase(publicDir);
|
|
202
244
|
if (inlined.length > 0) {
|
|
203
245
|
throw new Error(
|
|
204
|
-
`pyric
|
|
246
|
+
`pyric sandbox: ${inlined[0]} bundles the real Firebase SDK, so this dist cannot be ` +
|
|
205
247
|
`sandboxed — its firebase/* calls would reach LIVE Google endpoints, not the ` +
|
|
206
248
|
`pyric sandbox. Two ways forward:\n` +
|
|
207
|
-
` (a)
|
|
249
|
+
` (a) \`pyric sandbox -- <command>\` runs the child server with the @pyric/cli/vite ` +
|
|
208
250
|
`plugin swaps firebase/* live) — use \`bun run dev\`;\n` +
|
|
209
251
|
` (b) rebuild as a self-contained sandbox bundle and serve THAT: ` +
|
|
210
252
|
`\`vite build --mode development\` (or pyric({ swapInBuild: true })) then ` +
|
|
211
|
-
`\`pyric
|
|
253
|
+
`\`pyric sandbox\`.\n` +
|
|
212
254
|
`A plain \`vite build\` is your production build — deploy it, don't sandbox it.`,
|
|
213
255
|
);
|
|
214
256
|
}
|
|
@@ -285,15 +327,21 @@ export async function startServe(opts: {
|
|
|
285
327
|
studio: opts.ui ? { siteUiDir } : false,
|
|
286
328
|
bridgeUrl: () => mount && origin.port > 0 ? mount.wsUrl(origin) : null,
|
|
287
329
|
activity: (incident) => logger.note(formatActivityWarning(incident)),
|
|
330
|
+
beaconToken,
|
|
331
|
+
beacon: (report) => {
|
|
332
|
+
beaconsSeen += 1;
|
|
333
|
+
logger.note(formatBeaconReceipt(report));
|
|
334
|
+
},
|
|
335
|
+
permissive: opts.permissive,
|
|
288
336
|
logger,
|
|
289
337
|
});
|
|
290
338
|
} catch (error) {
|
|
291
339
|
bundle.dispose?.();
|
|
292
340
|
if (error instanceof SandboxSeedError) {
|
|
293
341
|
if (error.kind === 'read') {
|
|
294
|
-
throw new Error(`pyric
|
|
342
|
+
throw new Error(`pyric sandbox: failed to read --seed ${error.path}: ${error.detail}`);
|
|
295
343
|
}
|
|
296
|
-
throw new Error(`pyric
|
|
344
|
+
throw new Error(`pyric sandbox: --seed must be a JSON object of "collection/doc" to fields, ${error.detail}`);
|
|
297
345
|
}
|
|
298
346
|
throw error;
|
|
299
347
|
}
|
|
@@ -376,7 +424,7 @@ export async function startServe(opts: {
|
|
|
376
424
|
};
|
|
377
425
|
if (bundle.dispose) handle.server.once('close', bundle.dispose);
|
|
378
426
|
handle.server.once('close', () => void closeOwnedResources());
|
|
379
|
-
const uiUrl = siteUiDir ? `${handle.url}/__pyric/ui
|
|
427
|
+
const uiUrl = siteUiDir ? `${handle.url}/__pyric/ui/studio` : null;
|
|
380
428
|
const docsUrl = siteUiDir ? `${handle.url}/__pyric/ui/docs/` : null;
|
|
381
429
|
|
|
382
430
|
// Hot-reload: the static adapter observes the filesystem; the session owns
|
|
@@ -472,7 +520,7 @@ export async function startServe(opts: {
|
|
|
472
520
|
session.payload().storageRules
|
|
473
521
|
? `✔ rules ${session.summary.rules.storage.sourcePath} → deployed to the storage sandbox (hash ${session.summary.rules.storage.hash}; ` +
|
|
474
522
|
`edits require a restart — storage rules do not hot-reload)`
|
|
475
|
-
: `• rules no storage.rules — storage sandbox
|
|
523
|
+
: `• rules no storage.rules — storage sandbox denies client operations by default`,
|
|
476
524
|
);
|
|
477
525
|
if (uiUrl) {
|
|
478
526
|
logger.info(`✔ studio Pyric Studio: ${uiUrl}`);
|
|
@@ -483,6 +531,13 @@ export async function startServe(opts: {
|
|
|
483
531
|
if (mount) {
|
|
484
532
|
logger.info(`✔ bridge MCP endpoint: ${mount.mcpUrl(origin)} (sandbox peers over ws at /__pyric/sandbox)`);
|
|
485
533
|
}
|
|
534
|
+
// AI is a mounted service like the bridge: `/__pyric/ai-proxy` answers from
|
|
535
|
+
// the first request on, whether or not anything is configured. `pyric
|
|
536
|
+
// sandbox` has no AI flag, so the ENGINE is always the page's own `getAI()`
|
|
537
|
+
// choice (resolved lazily in the browser, since nothing here instantiates a
|
|
538
|
+
// broker to find out); what this server does decide is where the proxy
|
|
539
|
+
// forwards, and that is what the line reports.
|
|
540
|
+
logger.info(formatAiStatusLine({}));
|
|
486
541
|
let persistSummary: ServeRuntime['persist'] = null;
|
|
487
542
|
const persistence = session.summary.persistence;
|
|
488
543
|
if (persistence) {
|
|
@@ -531,7 +586,8 @@ export async function startServe(opts: {
|
|
|
531
586
|
logger.note('');
|
|
532
587
|
logger.note(' ⚠ the pyric sandbox runs IN the served page — keep the browser tab open.');
|
|
533
588
|
logger.note(' Firestore/auth data and persistence stop when no page is open.');
|
|
534
|
-
|
|
589
|
+
const mcpUrl = mount ? mount.mcpUrl(origin) : null;
|
|
590
|
+
return { handle, publicDir, payload, uiUrl, mcpUrl, persist: persistSummary, beaconCount, beaconToken };
|
|
535
591
|
}
|
|
536
592
|
|
|
537
593
|
/**
|
|
@@ -547,7 +603,7 @@ export function bridgeEnabledFromFlags(flags: { get(key: string): unknown }): bo
|
|
|
547
603
|
* A dev child also implies the bridge: the runner injects
|
|
548
604
|
* `PYRIC_SANDBOX=remote:<url>` into the child, whose remote client dials the
|
|
549
605
|
* `/__pyric/sandbox` WS — without the bridge mount that upgrade 404s and
|
|
550
|
-
*
|
|
606
|
+
* `pyric sandbox -- <cmd>` breaks its own
|
|
551
607
|
* child. Pure + exported for unit coverage.
|
|
552
608
|
*/
|
|
553
609
|
export function bridgeEnabledFor(
|
|
@@ -560,7 +616,7 @@ export function bridgeEnabledFor(
|
|
|
560
616
|
|
|
561
617
|
/**
|
|
562
618
|
* Process-level last line of defense for the dev server: a single bad
|
|
563
|
-
* request/WS interaction must never take `pyric
|
|
619
|
+
* request/WS interaction must never take `pyric sandbox` down. Node kills the
|
|
564
620
|
* process on an unhandled rejection (default `--unhandled-rejections=throw`
|
|
565
621
|
* since v15) and on any uncaught exception — and the serve process hosts
|
|
566
622
|
* long-lived, browser-driven machinery (WS peers, SSE streams, file watchers,
|
|
@@ -578,13 +634,13 @@ export function installServeProcessGuard(
|
|
|
578
634
|
reason instanceof Error ? (reason.stack ?? reason.message) : String(reason);
|
|
579
635
|
const onRejection = (reason: unknown): void => {
|
|
580
636
|
log(
|
|
581
|
-
` ✖ pyric
|
|
637
|
+
` ✖ pyric sandbox: unhandled rejection. The server was kept alive. Please report this:\n` +
|
|
582
638
|
` ${describe(reason).split('\n').join('\n ')}`,
|
|
583
639
|
);
|
|
584
640
|
};
|
|
585
641
|
const onException = (err: unknown): void => {
|
|
586
642
|
log(
|
|
587
|
-
` ✖ pyric
|
|
643
|
+
` ✖ pyric sandbox: uncaught exception. The server was kept alive. Please report this:\n` +
|
|
588
644
|
` ${describe(err).split('\n').join('\n ')}`,
|
|
589
645
|
);
|
|
590
646
|
};
|
|
@@ -596,10 +652,49 @@ export function installServeProcessGuard(
|
|
|
596
652
|
};
|
|
597
653
|
}
|
|
598
654
|
|
|
655
|
+
function resolveServePort(flagPort: unknown, configPort?: number): number {
|
|
656
|
+
if (typeof flagPort === 'string') return Number(flagPort);
|
|
657
|
+
if (typeof flagPort === 'number') return flagPort;
|
|
658
|
+
if (typeof configPort === 'number') return configPort;
|
|
659
|
+
return 3473;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function resolveProjectIdentifier(
|
|
663
|
+
flagProject?: unknown,
|
|
664
|
+
envProject?: string,
|
|
665
|
+
configProject?: string,
|
|
666
|
+
rcDefault?: string,
|
|
667
|
+
): string {
|
|
668
|
+
if (typeof flagProject === 'string' && flagProject.length > 0) return flagProject;
|
|
669
|
+
if (typeof envProject === 'string' && envProject.length > 0) return envProject;
|
|
670
|
+
if (typeof configProject === 'string' && configProject.length > 0) return configProject;
|
|
671
|
+
if (typeof rcDefault === 'string' && rcDefault.length > 0) return rcDefault;
|
|
672
|
+
return 'demo-project';
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function resolveExplicitCommand(parsed: ParsedArgs): string[] | null {
|
|
676
|
+
if (parsed.passthrough && parsed.passthrough.length > 0) {
|
|
677
|
+
return parsed.passthrough;
|
|
678
|
+
}
|
|
679
|
+
if (parsed.positional.length > 0) {
|
|
680
|
+
return parsed.positional;
|
|
681
|
+
}
|
|
682
|
+
return null;
|
|
683
|
+
}
|
|
684
|
+
|
|
599
685
|
/** CLI entry. Resolves on SIGINT/SIGTERM after a clean stop. */
|
|
600
686
|
export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
687
|
+
const cwd = process.cwd();
|
|
688
|
+
let pyricConfig: PyricConfig = {};
|
|
689
|
+
try {
|
|
690
|
+
pyricConfig = await readPyricConfig(cwd);
|
|
691
|
+
} catch (error) {
|
|
692
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
693
|
+
return 2;
|
|
694
|
+
}
|
|
695
|
+
|
|
601
696
|
const flagPort = parsed.flags.get('port');
|
|
602
|
-
const port =
|
|
697
|
+
const port = resolveServePort(flagPort, pyricConfig.port);
|
|
603
698
|
if (!Number.isFinite(port) || port < 0 || port > 65535) {
|
|
604
699
|
process.stderr.write(`pyric: invalid --port '${flagPort}'.\n`);
|
|
605
700
|
return 1;
|
|
@@ -610,7 +705,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
610
705
|
const only = parsed.flags.get('only');
|
|
611
706
|
if (typeof only === 'string' && only !== 'hosting') {
|
|
612
707
|
process.stderr.write(
|
|
613
|
-
`pyric: --only '${only}' is not supported
|
|
708
|
+
`pyric: --only '${only}' is not supported. pyric sandbox serves hosting with the in-page sandbox standing in for Firestore and Auth.\n`,
|
|
614
709
|
);
|
|
615
710
|
return 1;
|
|
616
711
|
}
|
|
@@ -623,7 +718,6 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
623
718
|
// Resolve the child plan BEFORE the server starts: a planned child implies
|
|
624
719
|
// the bridge (see bridgeEnabledFor) — the child's injected PYRIC_SANDBOX
|
|
625
720
|
// is useless without the /__pyric/sandbox WS mount.
|
|
626
|
-
const cwd = process.cwd();
|
|
627
721
|
let functionsProject: FunctionsRtdbProject | null;
|
|
628
722
|
let functionsProjectId: string | null = null;
|
|
629
723
|
try {
|
|
@@ -631,22 +725,25 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
631
725
|
if (functionsProject) {
|
|
632
726
|
const flagProject = parsed.flags.get('project');
|
|
633
727
|
const rc = await readFirebaseRc(cwd);
|
|
634
|
-
functionsProjectId =
|
|
635
|
-
|
|
636
|
-
process.env.PYRIC_PROJECT
|
|
637
|
-
|
|
638
|
-
|
|
728
|
+
functionsProjectId = resolveProjectIdentifier(
|
|
729
|
+
flagProject,
|
|
730
|
+
process.env.PYRIC_PROJECT,
|
|
731
|
+
pyricConfig.project,
|
|
732
|
+
rc?.projects?.default,
|
|
733
|
+
);
|
|
639
734
|
}
|
|
640
735
|
} catch (error) {
|
|
641
736
|
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
642
737
|
return 2;
|
|
643
738
|
}
|
|
644
|
-
|
|
645
|
-
|
|
739
|
+
|
|
740
|
+
const explicitCommand = resolveExplicitCommand(parsed);
|
|
741
|
+
|
|
742
|
+
const plan = resolveSandboxChild({
|
|
743
|
+
explicitCommand,
|
|
744
|
+
configCommand: pyricConfig.command,
|
|
646
745
|
noRun: Boolean(parsed.flags.get('no-run')),
|
|
647
746
|
json,
|
|
648
|
-
devScript: readDevScript(cwd),
|
|
649
|
-
packageManager: detectPackageManager(cwd),
|
|
650
747
|
});
|
|
651
748
|
const bridgeOn = bridgeEnabledFor(parsed.flags, plan, functionsProject);
|
|
652
749
|
|
|
@@ -663,6 +760,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
663
760
|
watch: parsed.flags.get('no-watch') ? false : undefined,
|
|
664
761
|
persist: Boolean(parsed.flags.get('persist')),
|
|
665
762
|
fresh: Boolean(parsed.flags.get('fresh')),
|
|
763
|
+
permissive: Boolean(parsed.flags.get('permissive')),
|
|
666
764
|
// --ui mounts the Pyric Studio storage routes (workspace + projects).
|
|
667
765
|
ui: uiOn,
|
|
668
766
|
// --no-capture disables the default-on session capture. The pattern
|
|
@@ -675,7 +773,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
675
773
|
project:
|
|
676
774
|
typeof parsed.flags.get('project') === 'string'
|
|
677
775
|
? (parsed.flags.get('project') as string)
|
|
678
|
-
: process.env.PYRIC_PROJECT ?? functionsProjectId ?? undefined,
|
|
776
|
+
: process.env.PYRIC_PROJECT ?? pyricConfig.project ?? functionsProjectId ?? undefined,
|
|
679
777
|
});
|
|
680
778
|
} catch (e) {
|
|
681
779
|
process.stderr.write(`${e instanceof Error ? e.message : String(e)}\n`);
|
|
@@ -691,7 +789,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
691
789
|
// (the banner went to stderr). Readiness probe: GET /__pyric/init.json.
|
|
692
790
|
if (json) process.stdout.write(serveJsonLine(runtime) + '\n');
|
|
693
791
|
|
|
694
|
-
//
|
|
792
|
+
// A host-only sandbox mounts no MCP bridge unless one is needed.
|
|
695
793
|
// so a `pyric mcp-proxy` in an editor cannot attach. Nudge toward --bridge.
|
|
696
794
|
if (!bridgeOn && !json) {
|
|
697
795
|
process.stderr.write(
|
|
@@ -714,7 +812,8 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
714
812
|
void openBrowser(targetUrl);
|
|
715
813
|
}
|
|
716
814
|
|
|
717
|
-
let devChild:
|
|
815
|
+
let devChild: SandboxChildHandle | null = null;
|
|
816
|
+
let beaconWatchdog: BeaconWatchdog | null = null;
|
|
718
817
|
let functionsRuntime: FunctionsDevelopmentRuntime | null = null;
|
|
719
818
|
let resolveFunctionsExit!: (code: number) => void;
|
|
720
819
|
const functionsExited = new Promise<number>((resolve) => { resolveFunctionsExit = resolve; });
|
|
@@ -737,6 +836,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
737
836
|
]);
|
|
738
837
|
const stopAfterSignal = async (): Promise<number> => {
|
|
739
838
|
(json ? process.stderr : process.stdout).write('\nShutting down...\n');
|
|
839
|
+
beaconWatchdog?.stop();
|
|
740
840
|
if (devChild && devChild.child.exitCode === null) devChild.signal(await signal);
|
|
741
841
|
await functionsRuntime?.close().catch(() => undefined);
|
|
742
842
|
await runtime.handle.stop().catch(() => undefined);
|
|
@@ -781,6 +881,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
781
881
|
baseEnv: process.env,
|
|
782
882
|
serveUrl: runtime.handle.url,
|
|
783
883
|
registerUrl: registerModuleUrl(),
|
|
884
|
+
beaconToken: runtime.beaconToken,
|
|
784
885
|
instance: `${functionsProjectId}-default-rtdb`,
|
|
785
886
|
location: process.env.PYRIC_FUNCTIONS_RTDB_REGION ?? 'us-central1',
|
|
786
887
|
projectId: functionsProjectId ?? 'demo-project',
|
|
@@ -793,7 +894,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
793
894
|
if (result.kind === 'no-peer') {
|
|
794
895
|
process.stderr.write(
|
|
795
896
|
` ⚠ functions not started — no browser tab connected after 30s. ` +
|
|
796
|
-
`Open ${runtime.handle.url} and restart pyric
|
|
897
|
+
`Open ${runtime.handle.url} and restart pyric sandbox.\n`,
|
|
797
898
|
);
|
|
798
899
|
} else if (result.kind === 'failed') {
|
|
799
900
|
process.stderr.write(`${result.error.message}\n`);
|
|
@@ -810,16 +911,15 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
810
911
|
for (const unsupported of ready.unsupportedTriggers) {
|
|
811
912
|
process.stderr.write(
|
|
812
913
|
` ⚠ functions export ${unsupported.exportName} uses unsupported trigger ` +
|
|
813
|
-
`${unsupported.eventType}; it will not run in pyric
|
|
914
|
+
`${unsupported.eventType}; it will not run in pyric sandbox.\n`,
|
|
814
915
|
);
|
|
815
916
|
}
|
|
816
917
|
}
|
|
817
918
|
}
|
|
818
919
|
|
|
819
|
-
//
|
|
820
|
-
//
|
|
821
|
-
//
|
|
822
|
-
// host-only; --json defaults to host-only (explicit `--` still wins).
|
|
920
|
+
// Run the explicit or configured command with the sandbox environment.
|
|
921
|
+
// `--no-run` forces host-only. `--json` skips the configured command, but an
|
|
922
|
+
// explicit command still runs.
|
|
823
923
|
// (`plan` was resolved above so it could imply the bridge mount.)
|
|
824
924
|
if (plan) {
|
|
825
925
|
const info = json ? process.stderr : process.stdout;
|
|
@@ -838,23 +938,46 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
838
938
|
` ⚠ no browser tab connected after 30s — starting your command anyway; sandbox ops will fail until ${runtime.handle.url} is open.\n`,
|
|
839
939
|
);
|
|
840
940
|
}
|
|
941
|
+
} else if (!json) {
|
|
942
|
+
info.write(
|
|
943
|
+
` ⓘ Auto-open is disabled (--no-open/CI). The pyric sandbox is browser-resident: ` +
|
|
944
|
+
`open ${runtime.handle.url} to connect if your command performs Firebase operations.\n`,
|
|
945
|
+
);
|
|
841
946
|
}
|
|
842
947
|
info.write(
|
|
843
948
|
`✔ run \`${plan.label}\` — firebase-admin/firebase imports are routed to the sandbox at ${runtime.handle.url}\n`,
|
|
844
949
|
);
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
950
|
+
const childEnv = buildChildEnv(process.env, {
|
|
951
|
+
serveUrl: runtime.handle.url,
|
|
952
|
+
registerUrl: registerModuleUrl(),
|
|
953
|
+
beaconToken: runtime.beaconToken,
|
|
954
|
+
});
|
|
955
|
+
// What we are handing the child, stated before it starts: the interlock
|
|
956
|
+
// line and the unsupported-runtime check.
|
|
957
|
+
const interlock = reportLaunchChecks({
|
|
958
|
+
childEnv,
|
|
959
|
+
registerUrl: registerModuleUrl(),
|
|
960
|
+
argv: plan.argv,
|
|
961
|
+
write: (line) => info.write(line),
|
|
962
|
+
});
|
|
963
|
+
|
|
964
|
+
devChild = spawnSandboxChild(plan, { cwd, json, env: childEnv });
|
|
965
|
+
// A child still alive well after launch that never posted a beacon is very
|
|
966
|
+
// likely not intercepted. `startBeaconWatchdog` says why this only warns.
|
|
967
|
+
const beaconsAtSpawn = runtime.beaconCount();
|
|
968
|
+
beaconWatchdog = startBeaconWatchdog({
|
|
969
|
+
label: plan.label,
|
|
970
|
+
beacon: interlock.beacon,
|
|
971
|
+
sawBeacon: () => runtime.beaconCount() > beaconsAtSpawn,
|
|
972
|
+
isAlive: () => devChild !== null && devChild.child.exitCode === null,
|
|
973
|
+
warn: (line) => void process.stderr.write(`${line}\n`),
|
|
852
974
|
});
|
|
853
975
|
} else if (!json) {
|
|
854
976
|
process.stdout.write(
|
|
855
977
|
formatStartupEnvExport({
|
|
856
978
|
serveUrl: runtime.handle.url,
|
|
857
979
|
registerUrl: registerModuleUrl(),
|
|
980
|
+
beaconToken: runtime.beaconToken,
|
|
858
981
|
}),
|
|
859
982
|
);
|
|
860
983
|
}
|
|
@@ -866,6 +989,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
866
989
|
if (settled) return;
|
|
867
990
|
settled = true;
|
|
868
991
|
void (async () => {
|
|
992
|
+
beaconWatchdog?.stop();
|
|
869
993
|
await functionsRuntime?.close().catch(() => undefined);
|
|
870
994
|
if (devChild && devChild.child.exitCode === null) {
|
|
871
995
|
devChild.signal('SIGTERM');
|
|
@@ -895,7 +1019,7 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
895
1019
|
if (functionsRuntime) {
|
|
896
1020
|
void functionsExited.then((code) => {
|
|
897
1021
|
if (!settled && !shuttingDown) {
|
|
898
|
-
process.stderr.write(`pyric
|
|
1022
|
+
process.stderr.write(`pyric sandbox: Functions child exited unexpectedly (code ${code}).\n`);
|
|
899
1023
|
finish(code === 0 ? 1 : code);
|
|
900
1024
|
}
|
|
901
1025
|
});
|
|
@@ -903,60 +1027,3 @@ export async function runServe(parsed: ParsedArgs): Promise<number> {
|
|
|
903
1027
|
void signal.then(shutdown);
|
|
904
1028
|
});
|
|
905
1029
|
}
|
|
906
|
-
|
|
907
|
-
/**
|
|
908
|
-
* Detect a bundler build that INLINED the real firebase SDK into its served
|
|
909
|
-
* assets (`vite build` output). The served import map remaps only bare
|
|
910
|
-
* `firebase/*` specifiers, so such a build cannot be sandboxed — its calls
|
|
911
|
-
* reach real Google endpoints. Fingerprints are real-SDK-only endpoint hosts
|
|
912
|
-
* that never appear in a sandbox-clean app (whose calls all route to
|
|
913
|
-
* `/__pyric/*`). Bounded: depth ≤ 4, ≤ 200 script files, first hit per file.
|
|
914
|
-
* Returns publicDir-relative paths of offending assets.
|
|
915
|
-
*/
|
|
916
|
-
export function scanForInlinedFirebase(dir: string): string[] {
|
|
917
|
-
const FINGERPRINTS = [
|
|
918
|
-
'identitytoolkit.googleapis.com',
|
|
919
|
-
'firestore.googleapis.com',
|
|
920
|
-
'securetoken.googleapis.com',
|
|
921
|
-
'firebasedatabase.app',
|
|
922
|
-
];
|
|
923
|
-
const hits: string[] = [];
|
|
924
|
-
let scanned = 0;
|
|
925
|
-
const walk = (d: string, rel: string, depth: number): void => {
|
|
926
|
-
if (depth > 4 || scanned >= 200) return;
|
|
927
|
-
let names: string[];
|
|
928
|
-
try {
|
|
929
|
-
names = readdirSync(d);
|
|
930
|
-
} catch {
|
|
931
|
-
return;
|
|
932
|
-
}
|
|
933
|
-
for (const name of names) {
|
|
934
|
-
if (scanned >= 200) return;
|
|
935
|
-
const p = join(d, name);
|
|
936
|
-
const r = rel ? `${rel}/${name}` : name;
|
|
937
|
-
let st;
|
|
938
|
-
try {
|
|
939
|
-
st = statSync(p);
|
|
940
|
-
} catch {
|
|
941
|
-
continue;
|
|
942
|
-
}
|
|
943
|
-
if (st.isDirectory()) {
|
|
944
|
-
// The pyric namespace itself never lands in hosting.public, but a
|
|
945
|
-
// node_modules inside a served dir would be a scan-cost trap.
|
|
946
|
-
// Dot-directories (.next, .git, .pyric) are internal caches and must be ignored.
|
|
947
|
-
if (name === 'node_modules' || name.startsWith('.')) continue;
|
|
948
|
-
walk(p, r, depth + 1);
|
|
949
|
-
} else if (/\.(js|mjs)$/.test(name)) {
|
|
950
|
-
scanned++;
|
|
951
|
-
try {
|
|
952
|
-
const text = readFileSync(p, 'utf8');
|
|
953
|
-
if (FINGERPRINTS.some((f) => text.includes(f))) hits.push(r);
|
|
954
|
-
} catch {
|
|
955
|
-
// unreadable asset: skip
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
};
|
|
960
|
-
walk(dir, '', 0);
|
|
961
|
-
return hits;
|
|
962
|
-
}
|
package/src/cli/snapshot.ts
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
* pyric snapshot [--out FILE] [--port N] [--force] [--json]
|
|
7
7
|
*
|
|
8
8
|
* Source preference:
|
|
9
|
-
* 1.
|
|
9
|
+
* 1. Live state from a running `pyric sandbox --persist`
|
|
10
10
|
* (`GET /__pyric/state` — `--port`, else the 3473+ scan window),
|
|
11
11
|
* 2. else the on-disk `.pyric/state/state.json`,
|
|
12
12
|
* 3. else exit 2 with a clear message.
|
|
13
13
|
*
|
|
14
14
|
* The output is a `PyricStateFile` envelope — directly re-servable:
|
|
15
|
-
* `pyric
|
|
15
|
+
* `pyric sandbox --seed <out>` (the state-file shape is detected by its
|
|
16
16
|
* `version` key and seeds docs + users).
|
|
17
17
|
*/
|
|
18
18
|
import { existsSync, writeFileSync } from 'node:fs';
|
|
@@ -44,7 +44,7 @@ async function fetchLive(port: number): Promise<LiveState | null> {
|
|
|
44
44
|
if (!body || typeof body !== 'object' || !('version' in body)) return null;
|
|
45
45
|
return { envelope: body, projectDir: res.headers.get('x-pyric-project-dir') };
|
|
46
46
|
} catch {
|
|
47
|
-
return null; //
|
|
47
|
+
return null; // No Pyric sandbox is listening. Fall through.
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -110,7 +110,7 @@ export async function runSnapshot(parsed: ParsedArgs, deps: SnapshotDeps = {}):
|
|
|
110
110
|
}
|
|
111
111
|
if (!envelope) {
|
|
112
112
|
err.write(
|
|
113
|
-
'pyric snapshot: no state found
|
|
113
|
+
'pyric snapshot: no state found. No `pyric sandbox --persist` is running here and ' +
|
|
114
114
|
'no .pyric/state/state.json exists. Run with --persist (and use the app) first.\n',
|
|
115
115
|
);
|
|
116
116
|
return 2;
|
|
@@ -158,7 +158,7 @@ export async function runSnapshot(parsed: ParsedArgs, deps: SnapshotDeps = {}):
|
|
|
158
158
|
if (redactedCount > 0) {
|
|
159
159
|
report.write(` ⓘ redacted ${redactedCount} password(s) — re-run with --include-passwords to keep them\n`);
|
|
160
160
|
}
|
|
161
|
-
report.write(` Re-serve it: pyric
|
|
161
|
+
report.write(` Re-serve it: pyric sandbox --seed ${typeof outFlag === 'string' ? outFlag : 'pyric-state.json'}\n`);
|
|
162
162
|
if (json) out.write(JSON.stringify({ out: outPath, docs, users, source, redactedPasswords: redactedCount }) + '\n');
|
|
163
163
|
return 0;
|
|
164
164
|
}
|