@pyric/cli 0.1.0-alpha.14 → 0.1.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assurance/.generated/conformance-verdicts.d.ts +120 -75
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +120 -75
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/cli/serve.d.ts +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +207 -284
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/service-command-records/database-rules-generate.d.ts +4 -0
- package/dist/cli/service-command-records/database-rules-generate.d.ts.map +1 -0
- package/dist/cli/service-command-records/database-rules-generate.js +3 -0
- package/dist/cli/service-command-records/database-rules-generate.js.map +1 -0
- package/dist/cli/service-command-records/database-rules-lint.d.ts +4 -0
- package/dist/cli/service-command-records/database-rules-lint.d.ts.map +1 -0
- package/dist/cli/service-command-records/database-rules-lint.js +3 -0
- package/dist/cli/service-command-records/database-rules-lint.js.map +1 -0
- package/dist/cli/service-command-records/database-rules-simulate.d.ts +4 -0
- package/dist/cli/service-command-records/database-rules-simulate.d.ts.map +1 -0
- package/dist/cli/service-command-records/database-rules-simulate.js +3 -0
- package/dist/cli/service-command-records/database-rules-simulate.js.map +1 -0
- package/dist/cli/service-command-records/database-rules-validate.d.ts +4 -0
- package/dist/cli/service-command-records/database-rules-validate.d.ts.map +1 -0
- package/dist/cli/service-command-records/database-rules-validate.js +3 -0
- package/dist/cli/service-command-records/database-rules-validate.js.map +1 -0
- package/dist/cli/service-command-records/firestore-indexes-generate.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-indexes-generate.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-indexes-generate.js +3 -0
- package/dist/cli/service-command-records/firestore-indexes-generate.js.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-lint.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-rules-lint.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-lint.js +3 -0
- package/dist/cli/service-command-records/firestore-rules-lint.js.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-resolve.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-rules-resolve.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-resolve.js +3 -0
- package/dist/cli/service-command-records/firestore-rules-resolve.js.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-simulate.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-rules-simulate.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-simulate.js +3 -0
- package/dist/cli/service-command-records/firestore-rules-simulate.js.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-validate.d.ts +4 -0
- package/dist/cli/service-command-records/firestore-rules-validate.d.ts.map +1 -0
- package/dist/cli/service-command-records/firestore-rules-validate.js +3 -0
- package/dist/cli/service-command-records/firestore-rules-validate.js.map +1 -0
- package/dist/cli/service-command-records/storage-rules-lint.d.ts +4 -0
- package/dist/cli/service-command-records/storage-rules-lint.d.ts.map +1 -0
- package/dist/cli/service-command-records/storage-rules-lint.js +3 -0
- package/dist/cli/service-command-records/storage-rules-lint.js.map +1 -0
- package/dist/cli/service-command-records/storage-rules-simulate.d.ts +4 -0
- package/dist/cli/service-command-records/storage-rules-simulate.d.ts.map +1 -0
- package/dist/cli/service-command-records/storage-rules-simulate.js +3 -0
- package/dist/cli/service-command-records/storage-rules-simulate.js.map +1 -0
- package/dist/cli/service-commands.d.ts +7 -0
- package/dist/cli/service-commands.d.ts.map +1 -1
- package/dist/cli/service-commands.generated.d.ts +35 -0
- package/dist/cli/service-commands.generated.d.ts.map +1 -0
- package/dist/cli/service-commands.generated.js +25 -0
- package/dist/cli/service-commands.generated.js.map +1 -0
- package/dist/cli/service-commands.js +23 -40
- package/dist/cli/service-commands.js.map +1 -1
- package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use-browser.js +1 -1
- package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
- package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use.js +1 -1
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
- package/dist/conformance/.generated/conformance-docs.js +1 -1
- package/dist/conformance/.generated/conformance-docs.js.map +1 -1
- package/dist/functions-rtdb/development-runtime.d.ts +63 -0
- package/dist/functions-rtdb/development-runtime.d.ts.map +1 -0
- package/dist/functions-rtdb/development-runtime.js +244 -0
- package/dist/functions-rtdb/development-runtime.js.map +1 -0
- package/dist/serve/bridge-mount.d.ts +32 -2
- package/dist/serve/bridge-mount.d.ts.map +1 -1
- package/dist/serve/bridge-mount.js +232 -18
- package/dist/serve/bridge-mount.js.map +1 -1
- package/dist/serve/bundler.d.ts +2 -18
- package/dist/serve/bundler.d.ts.map +1 -1
- package/dist/serve/bundler.js +7 -35
- package/dist/serve/bundler.js.map +1 -1
- package/dist/serve/entries/app-client.d.ts.map +1 -1
- package/dist/serve/entries/app-client.js +5 -5
- package/dist/serve/entries/app-client.js.map +1 -1
- package/dist/serve/entries/auth-helper-core.d.ts +23 -6
- package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
- package/dist/serve/entries/auth-helper-core.js +55 -24
- package/dist/serve/entries/auth-helper-core.js.map +1 -1
- package/dist/serve/entries/database.d.ts +28 -0
- package/dist/serve/entries/database.d.ts.map +1 -1
- package/dist/serve/entries/database.js +95 -26
- package/dist/serve/entries/database.js.map +1 -1
- package/dist/serve/entries/init.d.ts.map +1 -1
- package/dist/serve/entries/init.js +21 -12
- package/dist/serve/entries/init.js.map +1 -1
- package/dist/serve/html-injection.d.ts +5 -0
- package/dist/serve/html-injection.d.ts.map +1 -0
- package/dist/serve/html-injection.js +59 -0
- package/dist/serve/html-injection.js.map +1 -0
- package/dist/serve/namespace.d.ts +6 -22
- package/dist/serve/namespace.d.ts.map +1 -1
- package/dist/serve/namespace.js +23 -145
- package/dist/serve/namespace.js.map +1 -1
- package/dist/serve/runtime/worker-replacement.d.ts +1 -2
- package/dist/serve/runtime/worker-replacement.d.ts.map +1 -1
- package/dist/serve/sandbox-session.d.ts +78 -0
- package/dist/serve/sandbox-session.d.ts.map +1 -0
- package/dist/serve/sandbox-session.js +171 -0
- package/dist/serve/sandbox-session.js.map +1 -0
- package/dist/serve/server.d.ts +5 -2
- package/dist/serve/server.d.ts.map +1 -1
- package/dist/serve/server.js +21 -5
- package/dist/serve/server.js.map +1 -1
- package/dist/serve/site-tree.d.ts +8 -0
- package/dist/serve/site-tree.d.ts.map +1 -0
- package/dist/serve/site-tree.js +113 -0
- package/dist/serve/site-tree.js.map +1 -0
- package/dist/serve/site-ui/_astro/RulesCodeEditor.CzwHdCi9.js +23 -0
- package/dist/serve/site-ui/_astro/_example_.jevZ7OdV.css +1 -0
- package/dist/serve/site-ui/_astro/_slug_.BoKXYrnu.css +1 -0
- package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +1 -0
- package/dist/serve/site-ui/_astro/app.BnMC0ywl.js +109 -0
- package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +1 -0
- package/dist/serve/site-ui/_astro/app.DVXXR-WI.js +1 -0
- package/dist/serve/site-ui/_astro/chess-showcase.DzPO6kz0.js +1 -0
- package/dist/serve/site-ui/_astro/chess-source-explorer.C5k9c5yK.js +1 -0
- package/dist/serve/site-ui/_astro/chess-v2.CFHmd3UL.js +354 -0
- package/dist/serve/site-ui/_astro/client.D2ORs4B-.js +25 -0
- package/dist/serve/site-ui/_astro/example-runtime.CM0H02rx.js +291 -0
- package/dist/serve/site-ui/_astro/index.B4Kh80he.js +1 -0
- package/dist/serve/site-ui/_astro/index.DBy5LfQW.js +9 -0
- package/dist/serve/site-ui/_astro/index.DNyk7q8W.js +9 -0
- package/dist/serve/site-ui/_astro/jsx-runtime.D_zvdyIk.js +9 -0
- package/dist/serve/site-ui/_astro/reads.D1exkX1-.js +1 -0
- package/dist/serve/site-ui/_astro/sandbox-controls.BqMePr5V.js +1153 -0
- package/dist/serve/site-ui/_astro/seed.BCn5DhHS.js +20 -0
- package/dist/serve/site-ui/auth/index.html +11 -0
- package/dist/serve/site-ui/docs/_rhythm/index.html +100 -0
- package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +43 -0
- package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +26 -0
- package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +70 -0
- package/dist/serve/{docs-ui → site-ui}/docs/ai-compat/index.html +3 -3
- package/dist/serve/site-ui/docs/api-reference/index.html +68 -0
- package/dist/serve/{docs-ui → site-ui}/docs/app-compat/index.html +3 -3
- package/dist/serve/{docs-ui → site-ui}/docs/auth-compat/index.html +3 -3
- package/dist/serve/site-ui/docs/build/ai-logic/index.html +64 -0
- package/dist/serve/site-ui/docs/build/authentication/index.html +66 -0
- package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +84 -0
- package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +71 -0
- package/dist/serve/site-ui/docs/build/cloud-storage/index.html +66 -0
- package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-storage.md +2 -2
- package/dist/serve/site-ui/docs/build/realtime-database/index.html +67 -0
- package/dist/serve/site-ui/docs/conformance-scores/index.html +50 -0
- package/dist/serve/{docs-ui → site-ui}/docs/conformance-scores.md +3 -3
- package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +531 -0
- package/dist/serve/{docs-ui → site-ui}/docs/database-compat/index.html +211 -168
- package/dist/serve/{docs-ui → site-ui}/docs/database-compat.md +208 -170
- package/dist/serve/site-ui/docs/examples/chess/index.html +384 -0
- package/dist/serve/site-ui/docs/examples/chess.md +57 -0
- package/dist/serve/site-ui/docs/examples/index.html +3 -0
- package/dist/serve/site-ui/docs/examples.md +4 -0
- package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat/index.html +55 -91
- package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat.md +52 -88
- package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +73 -0
- package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +29 -0
- package/dist/serve/site-ui/docs/get-started/start-building/index.html +33 -0
- package/dist/serve/{docs-ui → site-ui}/docs/index.json +595 -26
- package/dist/serve/site-ui/docs/messaging-compat/index.html +324 -0
- package/dist/serve/{docs-ui → site-ui}/docs/messaging-compat.md +71 -1
- package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +28 -0
- package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +74 -0
- package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +45 -0
- package/dist/serve/site-ui/docs/overview/index.html +17 -0
- package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +186 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api/index.html +318 -202
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api.md +154 -27
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api/index.html +5 -5
- package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +318 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api/index.html +5 -5
- package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +160 -0
- package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +425 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api/index.html +5 -5
- package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +60 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +507 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +258 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +51 -0
- package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +308 -0
- package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +68 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +11 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api/index.html +1186 -1384
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api.md +817 -1291
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +126 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-vite-reference-api.md +1 -1
- package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +2641 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-database-reference-api.md +1055 -158
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api/index.html +311 -249
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api.md +72 -54
- package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +509 -0
- package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +182 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api/index.html +7 -26
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api.md +13 -23
- package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +121 -0
- package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +203 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api/index.html +26 -5
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api.md +22 -22
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api/index.html +5 -15
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api.md +0 -13
- package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +639 -0
- package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +100 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +24 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +136 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api/index.html +7 -7
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api.md +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +16 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api/index.html +4 -4
- package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +176 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api/index.html +10 -11
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api.md +7 -8
- package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +188 -0
- package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/rules-compat/index.html +87 -57
- package/dist/serve/{docs-ui → site-ui}/docs/rules-compat.md +84 -54
- package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +51 -0
- package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +106 -0
- package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +41 -0
- package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +67 -0
- package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +159 -0
- package/dist/serve/{docs-ui → site-ui}/docs/secure/rules-standard-library.md +2 -2
- package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +47 -0
- package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +95 -0
- package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +82 -0
- package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +37 -0
- package/dist/serve/site-ui/docs/ship/test-in-node/index.html +75 -0
- package/dist/serve/{docs-ui → site-ui}/docs/storage-compat/index.html +8 -8
- package/dist/serve/{docs-ui → site-ui}/docs/storage-compat.md +5 -5
- package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +132 -0
- package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +861 -0
- package/dist/serve/site-ui/docs/trust/rules-standard-library.md +344 -0
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +582 -0
- package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +448 -0
- package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +14 -0
- package/dist/serve/{docs-ui → site-ui}/docs/tutorial/index.html +4 -4
- package/dist/serve/{docs-ui → site-ui}/docs/tutorial.md +1 -1
- package/dist/serve/site-ui/examples/chess/index.html +2 -0
- package/dist/serve/site-ui/examples/firestore-first-write/index.html +2 -0
- package/dist/serve/site-ui/firestore/index.html +11 -0
- package/dist/serve/site-ui/index.html +11 -0
- package/dist/serve/{docs-ui → site-ui}/llms.txt +6 -2
- package/dist/serve/site-ui/rtdb/index.html +11 -0
- package/dist/serve/site-ui/settings/index.html +11 -0
- package/dist/serve/site-ui/storage/index.html +11 -0
- package/dist/serve/site-ui/studio-routes.json +1 -0
- package/dist/serve/site-ui/traffic/index.html +11 -0
- package/dist/serve/standalone-assets.d.ts +4 -10
- package/dist/serve/standalone-assets.d.ts.map +1 -1
- package/dist/serve/standalone-assets.js +8 -21
- package/dist/serve/standalone-assets.js.map +1 -1
- package/dist/serve/vite-functions-development.d.ts +29 -0
- package/dist/serve/vite-functions-development.d.ts.map +1 -0
- package/dist/serve/vite-functions-development.js +150 -0
- package/dist/serve/vite-functions-development.js.map +1 -0
- package/dist/serve/vite-generation-bridge.d.ts +17 -0
- package/dist/serve/vite-generation-bridge.d.ts.map +1 -0
- package/dist/serve/vite-generation-bridge.js +47 -0
- package/dist/serve/vite-generation-bridge.js.map +1 -0
- package/dist/serve/vite-generation-functions.d.ts +35 -0
- package/dist/serve/vite-generation-functions.d.ts.map +1 -0
- package/dist/serve/vite-generation-functions.js +46 -0
- package/dist/serve/vite-generation-functions.js.map +1 -0
- package/dist/serve/vite-generation-middleware.d.ts +10 -0
- package/dist/serve/vite-generation-middleware.d.ts.map +1 -0
- package/dist/serve/vite-generation-middleware.js +40 -0
- package/dist/serve/vite-generation-middleware.js.map +1 -0
- package/dist/serve/vite-generation-rules-watch.d.ts +8 -0
- package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -0
- package/dist/serve/vite-generation-rules-watch.js +33 -0
- package/dist/serve/vite-generation-rules-watch.js.map +1 -0
- package/dist/serve/vite-module-swap.d.ts +16 -0
- package/dist/serve/vite-module-swap.d.ts.map +1 -0
- package/dist/serve/vite-module-swap.js +96 -0
- package/dist/serve/vite-module-swap.js.map +1 -0
- package/dist/serve/vite-page-runtime.d.ts +29 -0
- package/dist/serve/vite-page-runtime.d.ts.map +1 -0
- package/dist/serve/vite-page-runtime.js +71 -0
- package/dist/serve/vite-page-runtime.js.map +1 -0
- package/dist/serve/vite-plugin.d.ts +44 -4
- package/dist/serve/vite-plugin.d.ts.map +1 -1
- package/dist/serve/vite-plugin.js +62 -864
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-sandbox-generation.d.ts +57 -0
- package/dist/serve/vite-sandbox-generation.d.ts.map +1 -0
- package/dist/serve/vite-sandbox-generation.js +178 -0
- package/dist/serve/vite-sandbox-generation.js.map +1 -0
- package/dist/serve/worker/client/disconnect.d.ts.map +1 -1
- package/dist/serve/worker/client/disconnect.js +2 -0
- package/dist/serve/worker/client/disconnect.js.map +1 -1
- package/dist/serve/worker/client/handles.d.ts +5 -0
- package/dist/serve/worker/client/handles.d.ts.map +1 -1
- package/dist/serve/worker/client/handles.js.map +1 -1
- package/dist/serve/worker/client/pagehide.d.ts +13 -0
- package/dist/serve/worker/client/pagehide.d.ts.map +1 -0
- package/dist/serve/worker/client/pagehide.js +19 -0
- package/dist/serve/worker/client/pagehide.js.map +1 -0
- package/dist/serve/worker/client/rtdb-admin.d.ts +8 -0
- package/dist/serve/worker/client/rtdb-admin.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-admin.js +39 -0
- package/dist/serve/worker/client/rtdb-admin.js.map +1 -0
- package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts +15 -0
- package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-connection-lifecycle.js +45 -0
- package/dist/serve/worker/client/rtdb-connection-lifecycle.js.map +1 -0
- package/dist/serve/worker/client/rtdb-controls.d.ts +6 -0
- package/dist/serve/worker/client/rtdb-controls.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-controls.js +8 -0
- package/dist/serve/worker/client/rtdb-controls.js.map +1 -0
- package/dist/serve/worker/client/rtdb-listeners.d.ts +24 -0
- package/dist/serve/worker/client/rtdb-listeners.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-listeners.js +262 -0
- package/dist/serve/worker/client/rtdb-listeners.js.map +1 -0
- package/dist/serve/worker/client/rtdb-reads.d.ts +4 -0
- package/dist/serve/worker/client/rtdb-reads.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-reads.js +11 -0
- package/dist/serve/worker/client/rtdb-reads.js.map +1 -0
- package/dist/serve/worker/client/rtdb-references.d.ts +19 -0
- package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-references.js +63 -0
- package/dist/serve/worker/client/rtdb-references.js.map +1 -0
- package/dist/serve/worker/client/rtdb-snapshots.d.ts +20 -0
- package/dist/serve/worker/client/rtdb-snapshots.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-snapshots.js +64 -0
- package/dist/serve/worker/client/rtdb-snapshots.js.map +1 -0
- package/dist/serve/worker/client/rtdb-transactions.d.ts +14 -0
- package/dist/serve/worker/client/rtdb-transactions.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-transactions.js +34 -0
- package/dist/serve/worker/client/rtdb-transactions.js.map +1 -0
- package/dist/serve/worker/client/rtdb-writes.d.ts +8 -0
- package/dist/serve/worker/client/rtdb-writes.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb-writes.js +65 -0
- package/dist/serve/worker/client/rtdb-writes.js.map +1 -0
- package/dist/serve/worker/client.d.ts +0 -2
- package/dist/serve/worker/client.d.ts.map +1 -1
- package/dist/serve/worker/client.js +0 -2
- package/dist/serve/worker/client.js.map +1 -1
- package/dist/serve/worker/entry.js +2 -2
- package/dist/serve/worker/entry.js.map +1 -1
- package/dist/serve/worker/host/dispatch.d.ts +2 -0
- package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
- package/dist/serve/worker/host/dispatch.js +24 -2
- package/dist/serve/worker/host/dispatch.js.map +1 -1
- package/dist/serve/worker/host/rtdb.d.ts +6 -2
- package/dist/serve/worker/host/rtdb.d.ts.map +1 -1
- package/dist/serve/worker/host/rtdb.js +224 -2
- package/dist/serve/worker/host/rtdb.js.map +1 -1
- package/dist/serve/worker/host/studio.d.ts.map +1 -1
- package/dist/serve/worker/host/studio.js +2 -0
- package/dist/serve/worker/host/studio.js.map +1 -1
- package/dist/serve/worker/host/subscriptions.d.ts.map +1 -1
- package/dist/serve/worker/host/subscriptions.js +3 -3
- package/dist/serve/worker/host/subscriptions.js.map +1 -1
- package/dist/serve/worker/host.d.ts +1 -1
- package/dist/serve/worker/host.d.ts.map +1 -1
- package/dist/serve/worker/host.js +1 -1
- package/dist/serve/worker/host.js.map +1 -1
- package/dist/serve/worker/index.d.ts +16 -1
- package/dist/serve/worker/index.d.ts.map +1 -1
- package/dist/serve/worker/index.js +17 -4
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/protocol.d.ts +57 -0
- package/dist/serve/worker/protocol.d.ts.map +1 -1
- package/dist/serve/worker/protocol.js.map +1 -1
- package/dist/serve/worker/rtdb-value-equality.d.ts +3 -0
- package/dist/serve/worker/rtdb-value-equality.d.ts.map +1 -0
- package/dist/serve/worker/rtdb-value-equality.js +18 -0
- package/dist/serve/worker/rtdb-value-equality.js.map +1 -0
- package/dist/serve/worker/serve-init.js +2 -2
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/dist/serve/worker/service-worker-relay.js +2 -2
- package/dist/serve/worker/service-worker-relay.js.map +1 -1
- package/package.json +7 -5
- package/src/assurance/.generated/conformance-verdicts.ts +120 -75
- package/src/cli/serve.ts +215 -307
- package/src/cli/service-command-records/database-rules-generate.ts +3 -0
- package/src/cli/service-command-records/database-rules-lint.ts +3 -0
- package/src/cli/service-command-records/database-rules-simulate.ts +3 -0
- package/src/cli/service-command-records/database-rules-validate.ts +3 -0
- package/src/cli/service-command-records/firestore-indexes-generate.ts +3 -0
- package/src/cli/service-command-records/firestore-rules-lint.ts +3 -0
- package/src/cli/service-command-records/firestore-rules-resolve.ts +3 -0
- package/src/cli/service-command-records/firestore-rules-simulate.ts +3 -0
- package/src/cli/service-command-records/firestore-rules-validate.ts +3 -0
- package/src/cli/service-command-records/storage-rules-lint.ts +3 -0
- package/src/cli/service-command-records/storage-rules-simulate.ts +3 -0
- package/src/cli/service-commands.generated.ts +27 -0
- package/src/cli/service-commands.test.ts +43 -0
- package/src/cli/service-commands.ts +36 -51
- package/src/conformance/.generated/can-i-use-browser.ts +1 -1
- package/src/conformance/.generated/can-i-use.ts +1 -1
- package/src/conformance/.generated/conformance-docs.ts +1 -1
- package/src/functions-rtdb/development-runtime.ts +299 -0
- package/src/serve/bridge-mount.ts +253 -19
- package/src/serve/bundler.ts +8 -34
- package/src/serve/entries/app-client.ts +5 -4
- package/src/serve/entries/auth-helper-core.ts +83 -30
- package/src/serve/entries/database.ts +180 -57
- package/src/serve/entries/init.ts +30 -20
- package/src/serve/html-injection.ts +65 -0
- package/src/serve/namespace.ts +26 -169
- package/src/serve/runtime/worker-replacement.ts +1 -1
- package/src/serve/sandbox-session.ts +233 -0
- package/src/serve/server.ts +20 -5
- package/src/serve/site-tree.ts +146 -0
- package/src/serve/standalone-assets.ts +9 -26
- package/src/serve/vite-functions-development.ts +201 -0
- package/src/serve/vite-generation-bridge.ts +66 -0
- package/src/serve/vite-generation-functions.ts +78 -0
- package/src/serve/vite-generation-middleware.ts +56 -0
- package/src/serve/vite-generation-rules-watch.ts +37 -0
- package/src/serve/vite-module-swap.ts +119 -0
- package/src/serve/vite-page-runtime.ts +100 -0
- package/src/serve/vite-plugin.ts +78 -883
- package/src/serve/vite-sandbox-generation.ts +255 -0
- package/src/serve/worker/client/disconnect.ts +3 -1
- package/src/serve/worker/client/handles.ts +5 -0
- package/src/serve/worker/client/pagehide.ts +31 -0
- package/src/serve/worker/client/rtdb-admin.ts +74 -0
- package/src/serve/worker/client/rtdb-connection-lifecycle.ts +52 -0
- package/src/serve/worker/client/rtdb-controls.ts +8 -0
- package/src/serve/worker/client/rtdb-listeners.ts +337 -0
- package/src/serve/worker/client/rtdb-reads.ts +12 -0
- package/src/serve/worker/client/rtdb-references.ts +85 -0
- package/src/serve/worker/client/rtdb-snapshots.ts +118 -0
- package/src/serve/worker/client/rtdb-transactions.ts +51 -0
- package/src/serve/worker/client/rtdb-writes.ts +74 -0
- package/src/serve/worker/client.ts +0 -2
- package/src/serve/worker/entry.ts +2 -2
- package/src/serve/worker/host/dispatch.ts +22 -2
- package/src/serve/worker/host/rtdb.ts +243 -2
- package/src/serve/worker/host/studio.ts +2 -0
- package/src/serve/worker/host/subscriptions.ts +8 -4
- package/src/serve/worker/host.ts +1 -1
- package/src/serve/worker/index.ts +58 -10
- package/src/serve/worker/protocol.ts +23 -2
- package/src/serve/worker/rtdb-value-equality.ts +17 -0
- package/src/serve/worker/serve-init.ts +2 -2
- package/src/serve/worker/service-worker-relay.ts +2 -2
- package/dist/serve/docs-ui/_astro/_slug_.DUci-duz.css +0 -1
- package/dist/serve/docs-ui/docs/_rhythm/index.html +0 -100
- package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +0 -43
- package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +0 -26
- package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +0 -70
- package/dist/serve/docs-ui/docs/api-reference/index.html +0 -68
- package/dist/serve/docs-ui/docs/build/ai-logic/index.html +0 -64
- package/dist/serve/docs-ui/docs/build/authentication/index.html +0 -66
- package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +0 -70
- package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +0 -71
- package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +0 -66
- package/dist/serve/docs-ui/docs/build/realtime-database/index.html +0 -67
- package/dist/serve/docs-ui/docs/conformance-scores/index.html +0 -50
- package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +0 -531
- package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +0 -73
- package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +0 -29
- package/dist/serve/docs-ui/docs/get-started/start-building/index.html +0 -33
- package/dist/serve/docs-ui/docs/messaging-compat/index.html +0 -265
- package/dist/serve/docs-ui/docs/observe/resolve-runtime-status/index.html +0 -28
- package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +0 -74
- package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +0 -45
- package/dist/serve/docs-ui/docs/overview/index.html +0 -17
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +0 -186
- package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +0 -318
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +0 -160
- package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +0 -425
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +0 -60
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +0 -507
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +0 -258
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +0 -51
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +0 -308
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +0 -68
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +0 -11
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +0 -126
- package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +0 -1852
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +0 -509
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +0 -182
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +0 -121
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +0 -203
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +0 -639
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +0 -100
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +0 -24
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +0 -136
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +0 -16
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +0 -176
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +0 -188
- package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +0 -51
- package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +0 -106
- package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +0 -41
- package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +0 -67
- package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +0 -159
- package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +0 -47
- package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +0 -95
- package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +0 -82
- package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +0 -37
- package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +0 -75
- package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +0 -132
- package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +0 -14
- package/dist/serve/docs-ui/index.html +0 -1
- package/dist/serve/studio-ui/assets/RulesCodeEditor-BDlH-5lp.js +0 -23
- package/dist/serve/studio-ui/assets/index-Bf9SSE8L.js +0 -1218
- package/dist/serve/studio-ui/assets/index-BlSGru_r.css +0 -1
- package/dist/serve/studio-ui/assets/seed-D_UjxfOU.js +0 -20
- package/dist/serve/studio-ui/index.html +0 -32
- package/dist/serve/worker/client/rtdb.d.ts +0 -36
- package/dist/serve/worker/client/rtdb.d.ts.map +0 -1
- package/dist/serve/worker/client/rtdb.js +0 -241
- package/dist/serve/worker/client/rtdb.js.map +0 -1
- package/src/serve/worker/client/rtdb.ts +0 -311
- /package/dist/serve/{docs-ui → site-ui}/404.html +0 -0
- /package/dist/serve/{docs-ui → site-ui}/_astro/_slug_.CXh9yTP1.css +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/_rhythm.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/agent/set-up-your-agent.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/agent/watch-and-review.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/agent/work-with-an-agent.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/ai-compat.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/api-reference.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/app-compat.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/auth-compat.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/ai-logic.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/authentication.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-firestore.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-messaging.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/build/realtime-database.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/create-pyric-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/functions-rtdb-compat.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/get-started/how-the-swap-works.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/get-started/start-building.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/index.html +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/observe/resolve-runtime-status.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/observe/see-whats-happening.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/observe/shape-your-data.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/overview.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-app-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-storage-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-scripting-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-app-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-browser-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-browser-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-docs-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-credentials-node-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-register-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-sw-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-database-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-firestore-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-agents-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-hooks-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/audit-your-rules.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/firestore-rules-limits.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/read-a-denial.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/rtdb-rules-in-typescript.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/secure-it-with-rules.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/simulate-and-lint.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/secure/write-a-rules-test-suite.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/ship/ship-to-production.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/ship/test-in-node.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/trust/how-we-know-it-matches-firebase.md +0 -0
- /package/dist/serve/{docs-ui → site-ui}/docs/trust/versioning-and-compatibility.md +0 -0
- /package/dist/serve/{studio-ui → site-ui}/pyric-logo.svg +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import type { ChildProcess } from 'node:child_process';
|
|
2
|
+
import {
|
|
3
|
+
spawnFunctionsRtdbChild,
|
|
4
|
+
type FunctionsRtdbChildEvent,
|
|
5
|
+
type FunctionsRtdbChildHandle,
|
|
6
|
+
type FunctionsRtdbChildReady,
|
|
7
|
+
type SpawnFunctionsRtdbChildOptions,
|
|
8
|
+
} from './child.js';
|
|
9
|
+
import { buildChildEnv, createLinePrefixer } from '../cli/dev-runner.js';
|
|
10
|
+
|
|
11
|
+
const INITIAL_PEER_TIMEOUT_MS = 30_000;
|
|
12
|
+
const RELOAD_PEER_TIMEOUT_MS = 5_000;
|
|
13
|
+
const PEER_POLL_INTERVAL_MS = 250;
|
|
14
|
+
|
|
15
|
+
export interface FunctionsPeerReadiness {
|
|
16
|
+
wait(options: { timeoutMs: number; signal: AbortSignal }): Promise<boolean>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type FunctionsDevelopmentResult =
|
|
20
|
+
| { kind: 'ready'; ready: FunctionsRtdbChildReady }
|
|
21
|
+
| { kind: 'no-peer' }
|
|
22
|
+
| { kind: 'failed'; error: Error };
|
|
23
|
+
|
|
24
|
+
export type FunctionsDevelopmentEvent =
|
|
25
|
+
| { type: 'child-event'; event: FunctionsRtdbChildEvent }
|
|
26
|
+
| { type: 'output'; stream: 'stdout' | 'stderr'; line: string }
|
|
27
|
+
| { type: 'unexpected-exit'; code: number };
|
|
28
|
+
|
|
29
|
+
export interface FunctionsDevelopmentRuntime {
|
|
30
|
+
start(): Promise<FunctionsDevelopmentResult>;
|
|
31
|
+
reload(): Promise<FunctionsDevelopmentResult>;
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface FunctionsDevelopmentRuntimeOptions {
|
|
36
|
+
sourceDir: string;
|
|
37
|
+
entry: string;
|
|
38
|
+
baseEnv: NodeJS.ProcessEnv;
|
|
39
|
+
serveUrl: string;
|
|
40
|
+
registerUrl: string;
|
|
41
|
+
instance: string;
|
|
42
|
+
location: string;
|
|
43
|
+
childModuleUrl?: string | URL;
|
|
44
|
+
readiness: FunctionsPeerReadiness;
|
|
45
|
+
onEvent?(event: FunctionsDevelopmentEvent): void;
|
|
46
|
+
/** Internal test seam; production adapters use the real isolated child. */
|
|
47
|
+
spawn?(options: SpawnFunctionsRtdbChildOptions): FunctionsRtdbChildHandle;
|
|
48
|
+
initialPeerTimeoutMs?: number;
|
|
49
|
+
reloadPeerTimeoutMs?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function abortableDelay(ms: number, signal: AbortSignal): Promise<void> {
|
|
53
|
+
if (signal.aborted) return Promise.resolve();
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
const timer = setTimeout(done, ms);
|
|
56
|
+
function done(): void {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
signal.removeEventListener('abort', done);
|
|
59
|
+
resolve();
|
|
60
|
+
}
|
|
61
|
+
signal.addEventListener('abort', done, { once: true });
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function settleBeforeAbort<T>(operation: Promise<T>, signal: AbortSignal): Promise<T> {
|
|
66
|
+
if (signal.aborted) return Promise.reject(signal.reason);
|
|
67
|
+
return new Promise<T>((resolve, reject) => {
|
|
68
|
+
const onAbort = (): void => {
|
|
69
|
+
cleanup();
|
|
70
|
+
reject(signal.reason);
|
|
71
|
+
};
|
|
72
|
+
const cleanup = (): void => signal.removeEventListener('abort', onAbort);
|
|
73
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
74
|
+
operation.then(
|
|
75
|
+
(value) => { cleanup(); resolve(value); },
|
|
76
|
+
(error) => { cleanup(); reject(error); },
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function createInProcessFunctionsPeerReadiness(
|
|
82
|
+
connected: () => boolean,
|
|
83
|
+
options: { intervalMs?: number; now?: () => number; sleep?: typeof abortableDelay } = {},
|
|
84
|
+
): FunctionsPeerReadiness {
|
|
85
|
+
const intervalMs = options.intervalMs ?? PEER_POLL_INTERVAL_MS;
|
|
86
|
+
const now = options.now ?? Date.now;
|
|
87
|
+
const sleep = options.sleep ?? abortableDelay;
|
|
88
|
+
return {
|
|
89
|
+
async wait({ timeoutMs, signal }) {
|
|
90
|
+
const deadline = now() + timeoutMs;
|
|
91
|
+
while (!signal.aborted) {
|
|
92
|
+
if (connected()) return true;
|
|
93
|
+
if (now() >= deadline) return false;
|
|
94
|
+
await sleep(intervalMs, signal);
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function createHttpFunctionsPeerReadiness(
|
|
102
|
+
serveUrl: string,
|
|
103
|
+
options: {
|
|
104
|
+
intervalMs?: number;
|
|
105
|
+
fetchImpl?: typeof fetch;
|
|
106
|
+
now?: () => number;
|
|
107
|
+
sleep?: typeof abortableDelay;
|
|
108
|
+
} = {},
|
|
109
|
+
): FunctionsPeerReadiness {
|
|
110
|
+
const baseUrl = serveUrl.replace(/\/$/, '');
|
|
111
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
112
|
+
const intervalMs = options.intervalMs ?? PEER_POLL_INTERVAL_MS;
|
|
113
|
+
const now = options.now ?? Date.now;
|
|
114
|
+
const sleep = options.sleep ?? abortableDelay;
|
|
115
|
+
return {
|
|
116
|
+
async wait({ timeoutMs, signal }) {
|
|
117
|
+
const deadline = now() + timeoutMs;
|
|
118
|
+
const deadlineAbort = new AbortController();
|
|
119
|
+
const deadlineTimer = setTimeout(() => deadlineAbort.abort(), timeoutMs);
|
|
120
|
+
deadlineTimer.unref();
|
|
121
|
+
const waitSignal = AbortSignal.any([signal, deadlineAbort.signal]);
|
|
122
|
+
try {
|
|
123
|
+
while (!waitSignal.aborted) {
|
|
124
|
+
try {
|
|
125
|
+
const response = await settleBeforeAbort(
|
|
126
|
+
fetchImpl(`${baseUrl}/__pyric/health`, { signal: waitSignal }),
|
|
127
|
+
waitSignal,
|
|
128
|
+
);
|
|
129
|
+
if (response.ok) {
|
|
130
|
+
const health = await settleBeforeAbort(
|
|
131
|
+
response.json() as Promise<{ sandboxConnected?: boolean }>,
|
|
132
|
+
waitSignal,
|
|
133
|
+
);
|
|
134
|
+
if (health.sandboxConnected === true) return true;
|
|
135
|
+
}
|
|
136
|
+
} catch {
|
|
137
|
+
if (waitSignal.aborted) return false;
|
|
138
|
+
}
|
|
139
|
+
if (now() >= deadline) return false;
|
|
140
|
+
await sleep(intervalMs, waitSignal);
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
} finally {
|
|
144
|
+
clearTimeout(deadlineTimer);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function asError(error: unknown): Error {
|
|
151
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function attachOutput(
|
|
155
|
+
child: ChildProcess,
|
|
156
|
+
emit: (event: FunctionsDevelopmentEvent) => void,
|
|
157
|
+
): void {
|
|
158
|
+
const attach = (stream: 'stdout' | 'stderr'): void => {
|
|
159
|
+
const readable = child[stream];
|
|
160
|
+
if (!readable) return;
|
|
161
|
+
const lines = createLinePrefixer('[functions] ', (line) => emit({ type: 'output', stream, line }));
|
|
162
|
+
readable.setEncoding('utf8');
|
|
163
|
+
readable.on('data', (chunk: string) => lines.push(chunk));
|
|
164
|
+
readable.once('end', () => lines.flush());
|
|
165
|
+
};
|
|
166
|
+
attach('stdout');
|
|
167
|
+
attach('stderr');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function createFunctionsDevelopmentRuntime(
|
|
171
|
+
options: FunctionsDevelopmentRuntimeOptions,
|
|
172
|
+
): FunctionsDevelopmentRuntime {
|
|
173
|
+
const spawn = options.spawn ?? spawnFunctionsRtdbChild;
|
|
174
|
+
const emit = (event: FunctionsDevelopmentEvent): void => options.onEvent?.(event);
|
|
175
|
+
const expectedStops = new WeakSet<FunctionsRtdbChildHandle>();
|
|
176
|
+
let activeChild: FunctionsRtdbChildHandle | null = null;
|
|
177
|
+
let activeWait: AbortController | null = null;
|
|
178
|
+
let closed = false;
|
|
179
|
+
let startPromise: Promise<FunctionsDevelopmentResult> | null = null;
|
|
180
|
+
let reloadPromise: Promise<FunctionsDevelopmentResult> | null = null;
|
|
181
|
+
let reloadQueued = false;
|
|
182
|
+
let closePromise: Promise<void> | null = null;
|
|
183
|
+
|
|
184
|
+
const stopChild = async (child: FunctionsRtdbChildHandle | null): Promise<void> => {
|
|
185
|
+
if (!child) return;
|
|
186
|
+
expectedStops.add(child);
|
|
187
|
+
if (activeChild === child) activeChild = null;
|
|
188
|
+
await child.stop().catch(() => undefined);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const launch = async (mode: 'initial' | 'reload'): Promise<FunctionsDevelopmentResult> => {
|
|
192
|
+
const controller = new AbortController();
|
|
193
|
+
activeWait = controller;
|
|
194
|
+
let connected: boolean;
|
|
195
|
+
try {
|
|
196
|
+
connected = await options.readiness.wait({
|
|
197
|
+
timeoutMs: mode === 'initial'
|
|
198
|
+
? options.initialPeerTimeoutMs ?? INITIAL_PEER_TIMEOUT_MS
|
|
199
|
+
: options.reloadPeerTimeoutMs ?? RELOAD_PEER_TIMEOUT_MS,
|
|
200
|
+
signal: controller.signal,
|
|
201
|
+
});
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (controller.signal.aborted || closed) return { kind: 'no-peer' };
|
|
204
|
+
return { kind: 'failed', error: asError(error) };
|
|
205
|
+
} finally {
|
|
206
|
+
if (activeWait === controller) activeWait = null;
|
|
207
|
+
}
|
|
208
|
+
if (!connected || closed) return { kind: 'no-peer' };
|
|
209
|
+
|
|
210
|
+
let handle: FunctionsRtdbChildHandle;
|
|
211
|
+
try {
|
|
212
|
+
handle = spawn({
|
|
213
|
+
cwd: options.sourceDir,
|
|
214
|
+
entry: options.entry,
|
|
215
|
+
env: buildChildEnv(options.baseEnv, {
|
|
216
|
+
serveUrl: options.serveUrl,
|
|
217
|
+
registerUrl: options.registerUrl,
|
|
218
|
+
}),
|
|
219
|
+
instance: options.instance,
|
|
220
|
+
location: options.location,
|
|
221
|
+
...(options.childModuleUrl === undefined ? {} : { childModuleUrl: options.childModuleUrl }),
|
|
222
|
+
onEvent: (event) => emit({ type: 'child-event', event }),
|
|
223
|
+
});
|
|
224
|
+
} catch (error) {
|
|
225
|
+
return { kind: 'failed', error: asError(error) };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
activeChild = handle;
|
|
229
|
+
attachOutput(handle.child, emit);
|
|
230
|
+
let readyReached = false;
|
|
231
|
+
let exitBeforeReady: number | null = null;
|
|
232
|
+
const reportUnexpectedExit = (code: number): void => {
|
|
233
|
+
if (activeChild === handle && !closed && !expectedStops.has(handle)) {
|
|
234
|
+
activeChild = null;
|
|
235
|
+
emit({ type: 'unexpected-exit', code });
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
void handle.exited.then((code) => {
|
|
239
|
+
if (!readyReached) exitBeforeReady = code;
|
|
240
|
+
else reportUnexpectedExit(code);
|
|
241
|
+
});
|
|
242
|
+
try {
|
|
243
|
+
const ready = await handle.ready;
|
|
244
|
+
readyReached = true;
|
|
245
|
+
if (exitBeforeReady !== null) reportUnexpectedExit(exitBeforeReady);
|
|
246
|
+
if (closed) {
|
|
247
|
+
await stopChild(handle);
|
|
248
|
+
return { kind: 'no-peer' };
|
|
249
|
+
}
|
|
250
|
+
return { kind: 'ready', ready };
|
|
251
|
+
} catch (error) {
|
|
252
|
+
await stopChild(handle);
|
|
253
|
+
return { kind: 'failed', error: asError(error) };
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const runtime: FunctionsDevelopmentRuntime = {
|
|
258
|
+
start() {
|
|
259
|
+
startPromise ??= launch('initial');
|
|
260
|
+
return startPromise;
|
|
261
|
+
},
|
|
262
|
+
reload() {
|
|
263
|
+
if (closed) return Promise.resolve({ kind: 'failed', error: new Error('Functions runtime is closed') });
|
|
264
|
+
reloadQueued = true;
|
|
265
|
+
if (!reloadPromise) {
|
|
266
|
+
reloadPromise = (async (): Promise<FunctionsDevelopmentResult> => {
|
|
267
|
+
let result: FunctionsDevelopmentResult = { kind: 'no-peer' };
|
|
268
|
+
if (startPromise) await startPromise;
|
|
269
|
+
do {
|
|
270
|
+
reloadQueued = false;
|
|
271
|
+
await stopChild(activeChild);
|
|
272
|
+
if (closed) return { kind: 'no-peer' };
|
|
273
|
+
result = await launch('reload');
|
|
274
|
+
} while (reloadQueued && !closed);
|
|
275
|
+
return result;
|
|
276
|
+
})().finally(() => { reloadPromise = null; });
|
|
277
|
+
}
|
|
278
|
+
return reloadPromise as Promise<FunctionsDevelopmentResult>;
|
|
279
|
+
},
|
|
280
|
+
close() {
|
|
281
|
+
if (closePromise) return closePromise;
|
|
282
|
+
closePromise = (async () => {
|
|
283
|
+
closed = true;
|
|
284
|
+
reloadQueued = false;
|
|
285
|
+
activeWait?.abort();
|
|
286
|
+
await stopChild(activeChild);
|
|
287
|
+
await Promise.allSettled([
|
|
288
|
+
...(startPromise ? [startPromise] : []),
|
|
289
|
+
...(reloadPromise ? [reloadPromise] : []),
|
|
290
|
+
]);
|
|
291
|
+
// A transition that crossed the closed check in the same turn may have
|
|
292
|
+
// installed a child after the first capture. The stop is idempotent.
|
|
293
|
+
await stopChild(activeChild);
|
|
294
|
+
})();
|
|
295
|
+
return closePromise;
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
return runtime;
|
|
299
|
+
}
|
|
@@ -16,7 +16,10 @@
|
|
|
16
16
|
* WS /__pyric/sandbox the in-page sandbox peer (server `upgrade`)
|
|
17
17
|
*/
|
|
18
18
|
import { randomUUID } from 'node:crypto';
|
|
19
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
19
20
|
import type { IncomingMessage, Server, ServerResponse } from 'node:http';
|
|
21
|
+
import { dirname, join } from 'node:path';
|
|
22
|
+
import type { Duplex } from 'node:stream';
|
|
20
23
|
import { WebSocketServer, type WebSocket } from 'ws';
|
|
21
24
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
22
25
|
import { createBridge, type BridgeToolEvent } from '../bridge/server/bridge.js';
|
|
@@ -48,10 +51,14 @@ export interface BridgeMount {
|
|
|
48
51
|
* The pointer writer records this so the proxy can verify it reached this
|
|
49
52
|
* exact server across a cross-family port collision. */
|
|
50
53
|
readonly instanceId: string;
|
|
54
|
+
/** Canonical project identity used by health, audit, URLs, and discovery. */
|
|
55
|
+
readonly project: string;
|
|
51
56
|
/** Namespace-handler tier: returns true when the request was handled. */
|
|
52
57
|
handler(req: IncomingMessage, res: ServerResponse, url: URL): Promise<boolean>;
|
|
53
|
-
/** Attach
|
|
54
|
-
|
|
58
|
+
/** Attach all bridge-owned host resources and return their explicit owner. */
|
|
59
|
+
attachHost(options: BridgeHostOptions): BridgeHostAttachment;
|
|
60
|
+
/** Close every attachment, peer, and MCP session. Idempotent. */
|
|
61
|
+
close(): Promise<void>;
|
|
55
62
|
/** Whether a sandbox peer (a browser tab / SharedWorker relay) is currently
|
|
56
63
|
* connected. In-process callers (the Vite plugin's Functions start) poll
|
|
57
64
|
* this instead of self-fetching `/__pyric/health`, which avoids a loopback
|
|
@@ -63,6 +70,29 @@ export interface BridgeMount {
|
|
|
63
70
|
mcpUrl(origin: { host: string; port: number }): string;
|
|
64
71
|
}
|
|
65
72
|
|
|
73
|
+
export interface BridgeHostOptions {
|
|
74
|
+
/** Every server accepting upgrades (static serve may bind both IP families). */
|
|
75
|
+
servers: Server[];
|
|
76
|
+
/** Server whose listen/close lifecycle owns discovery publication. */
|
|
77
|
+
lifecycleServer?: Server;
|
|
78
|
+
projectDir: string;
|
|
79
|
+
/** Returns null until a stable, externally reachable origin is known. */
|
|
80
|
+
origin(): { host: string; port: number } | null;
|
|
81
|
+
/** Defaults true. A host with a broader ordered shutdown can opt out and
|
|
82
|
+
* explicitly close the returned attachment from its own close listener. */
|
|
83
|
+
closeOnServerClose?: boolean;
|
|
84
|
+
/** Vite cannot dual-bind, so its adapter enables the cross-family probe. */
|
|
85
|
+
collision?: {
|
|
86
|
+
warn(message: string, options?: { timestamp?: boolean }): void;
|
|
87
|
+
/** Internal deterministic test seam. */
|
|
88
|
+
fetchImpl?: typeof fetch;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface BridgeHostAttachment {
|
|
93
|
+
close(): Promise<void>;
|
|
94
|
+
}
|
|
95
|
+
|
|
66
96
|
export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
|
|
67
97
|
const project = opts.project ?? 'sandbox';
|
|
68
98
|
const auditWriter = opts.disableAuditLog ? null : createAuditWriter(project);
|
|
@@ -87,19 +117,30 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
|
|
|
87
117
|
close: () => Promise<void>;
|
|
88
118
|
idle: ReturnType<typeof setTimeout> | null;
|
|
89
119
|
sessionId: string | null;
|
|
120
|
+
closing: Promise<void> | null;
|
|
90
121
|
};
|
|
91
122
|
const sessions = new Map<string, Session>();
|
|
123
|
+
const pendingSessions = new Set<Session>();
|
|
124
|
+
const attachments = new Set<BridgeHostAttachment>();
|
|
125
|
+
let closed = false;
|
|
126
|
+
let closePromise: Promise<void> | null = null;
|
|
92
127
|
|
|
93
128
|
const bumpIdle = (s: Session): void => {
|
|
94
129
|
if (s.idle) clearTimeout(s.idle);
|
|
95
130
|
s.idle = setTimeout(() => {
|
|
96
131
|
if (s.sessionId) sessions.delete(s.sessionId);
|
|
132
|
+
pendingSessions.delete(s);
|
|
97
133
|
void s.close();
|
|
98
134
|
}, SESSION_IDLE_MS);
|
|
99
135
|
};
|
|
100
136
|
|
|
101
137
|
const newSession = async (): Promise<Session> => {
|
|
102
|
-
if (
|
|
138
|
+
if (closed) {
|
|
139
|
+
const error = new Error('pyric bridge: mount is closed');
|
|
140
|
+
(error as { statusCode?: number }).statusCode = 503;
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
if (sessions.size + pendingSessions.size >= MAX_SESSIONS) {
|
|
103
144
|
const e = new Error(`pyric bridge: at session cap (${MAX_SESSIONS})`);
|
|
104
145
|
(e as { statusCode?: number }).statusCode = 503;
|
|
105
146
|
throw e;
|
|
@@ -109,34 +150,77 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
|
|
|
109
150
|
close: async () => {},
|
|
110
151
|
idle: null,
|
|
111
152
|
sessionId: null,
|
|
153
|
+
closing: null,
|
|
112
154
|
};
|
|
113
155
|
session.transport = new StreamableHTTPServerTransport({
|
|
114
156
|
sessionIdGenerator: () => randomUUID(),
|
|
115
157
|
onsessioninitialized: (id) => {
|
|
158
|
+
if (closed) {
|
|
159
|
+
pendingSessions.delete(session);
|
|
160
|
+
void session.close();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
116
163
|
session.sessionId = id;
|
|
117
164
|
sessions.set(id, session);
|
|
165
|
+
pendingSessions.delete(session);
|
|
118
166
|
bumpIdle(session);
|
|
119
167
|
},
|
|
120
168
|
});
|
|
121
169
|
session.transport.onclose = () => {
|
|
122
170
|
if (session.sessionId) sessions.delete(session.sessionId);
|
|
171
|
+
pendingSessions.delete(session);
|
|
123
172
|
};
|
|
124
173
|
const surface = getDefaultMcpToolSurface();
|
|
125
174
|
const server = buildMcpServer(bridge, {
|
|
126
175
|
forwarded: surface.forwarded,
|
|
127
176
|
inProcess: surface.inProcess,
|
|
128
177
|
});
|
|
129
|
-
session.close =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
178
|
+
session.close = () => {
|
|
179
|
+
session.closing ??= (async () => {
|
|
180
|
+
if (session.idle) clearTimeout(session.idle);
|
|
181
|
+
session.idle = null;
|
|
182
|
+
await server.close().catch(() => {});
|
|
183
|
+
await session.transport.close().catch(() => {});
|
|
184
|
+
})();
|
|
185
|
+
return session.closing;
|
|
133
186
|
};
|
|
134
|
-
|
|
187
|
+
pendingSessions.add(session);
|
|
188
|
+
try {
|
|
189
|
+
await server.connect(session.transport);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
pendingSessions.delete(session);
|
|
192
|
+
await session.close();
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
135
195
|
return session;
|
|
136
196
|
};
|
|
137
197
|
|
|
138
|
-
|
|
198
|
+
const closeSession = async (session: Session): Promise<void> => {
|
|
199
|
+
if (session.sessionId) sessions.delete(session.sessionId);
|
|
200
|
+
pendingSessions.delete(session);
|
|
201
|
+
await session.close();
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const removeOwnedPointer = (pointer: string): void => {
|
|
205
|
+
try {
|
|
206
|
+
if (!existsSync(pointer)) return;
|
|
207
|
+
const current = JSON.parse(readFileSync(pointer, 'utf8')) as { instanceId?: string };
|
|
208
|
+
if (current.instanceId === bridge.instanceId) rmSync(pointer);
|
|
209
|
+
} catch {
|
|
210
|
+
// Best effort. A malformed or concurrently replaced pointer is not ours.
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const mount: BridgeMount = {
|
|
215
|
+
project,
|
|
216
|
+
instanceId: bridge.instanceId,
|
|
217
|
+
|
|
139
218
|
async handler(req, res, url) {
|
|
219
|
+
if (closed && (url.pathname === HEALTH_PATH || url.pathname === MCP_PATH)) {
|
|
220
|
+
res.writeHead(503, { 'content-type': 'application/json' });
|
|
221
|
+
res.end(JSON.stringify({ error: 'pyric bridge: mount is closed' }));
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
140
224
|
if (url.pathname === HEALTH_PATH) {
|
|
141
225
|
res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify(bridge.health()));
|
|
142
226
|
return true;
|
|
@@ -144,20 +228,38 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
|
|
|
144
228
|
if (url.pathname === MCP_PATH) {
|
|
145
229
|
try {
|
|
146
230
|
const sessionId = (req.headers['mcp-session-id'] ?? req.headers['Mcp-Session-Id']) as string | undefined;
|
|
147
|
-
let session
|
|
148
|
-
|
|
149
|
-
|
|
231
|
+
let session: Session;
|
|
232
|
+
let created = false;
|
|
233
|
+
if (sessionId) {
|
|
234
|
+
const existing = sessions.get(sessionId);
|
|
235
|
+
if (!existing) {
|
|
236
|
+
res.writeHead(404, { 'content-type': 'application/json' });
|
|
237
|
+
res.end(JSON.stringify({ error: 'pyric bridge: MCP session not found' }));
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
session = existing;
|
|
241
|
+
bumpIdle(session);
|
|
242
|
+
} else {
|
|
243
|
+
session = await newSession();
|
|
244
|
+
created = true;
|
|
245
|
+
}
|
|
150
246
|
|
|
151
247
|
if (req.method === 'DELETE' && sessionId) {
|
|
152
|
-
await session
|
|
153
|
-
sessions.delete(sessionId);
|
|
248
|
+
await closeSession(session);
|
|
154
249
|
res.writeHead(204).end();
|
|
155
250
|
return true;
|
|
156
251
|
}
|
|
157
252
|
// The transport reads the raw request stream itself. Do NOT pre-parse
|
|
158
253
|
// the body (the old `collectBody` path); a double read hangs the
|
|
159
254
|
// initialize POST.
|
|
160
|
-
|
|
255
|
+
try {
|
|
256
|
+
await session.transport.handleRequest(req, res);
|
|
257
|
+
} finally {
|
|
258
|
+
// A request without a session id is allowed to allocate only while
|
|
259
|
+
// it attempts initialization. Invalid/non-initialize traffic must
|
|
260
|
+
// not strand an uninitialized transport against the session cap.
|
|
261
|
+
if (created && session.sessionId === null) await closeSession(session);
|
|
262
|
+
}
|
|
161
263
|
} catch (err) {
|
|
162
264
|
const statusCode = (err as { statusCode?: number })?.statusCode ?? 500;
|
|
163
265
|
if (!res.headersSent) {
|
|
@@ -169,10 +271,25 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
|
|
|
169
271
|
}
|
|
170
272
|
return false;
|
|
171
273
|
},
|
|
172
|
-
|
|
274
|
+
attachHost({
|
|
275
|
+
servers,
|
|
276
|
+
lifecycleServer = servers[0],
|
|
277
|
+
projectDir,
|
|
278
|
+
origin,
|
|
279
|
+
collision,
|
|
280
|
+
closeOnServerClose = true,
|
|
281
|
+
}) {
|
|
282
|
+
if (closed) throw new Error('pyric bridge: cannot attach a closed mount');
|
|
173
283
|
const wss = new WebSocketServer({ noServer: true });
|
|
174
284
|
const guard = opts.upgradeGuard;
|
|
175
|
-
|
|
285
|
+
const pointer = join(projectDir, '.pyric', 'serve.json');
|
|
286
|
+
const upgradedSockets = new Set<Duplex>();
|
|
287
|
+
const collisionAbort = new AbortController();
|
|
288
|
+
let collisionProbe: Promise<void> | null = null;
|
|
289
|
+
let attachmentClosed = false;
|
|
290
|
+
let attachmentClosePromise: Promise<void> | null = null;
|
|
291
|
+
|
|
292
|
+
const onUpgrade = (req: IncomingMessage, socket: Duplex, head: Buffer): void => {
|
|
176
293
|
if ((req.url ?? '') !== WS_PATH) return;
|
|
177
294
|
// DNS-rebinding + cross-origin hijack guard. The static/dev server runs
|
|
178
295
|
// isAllowedHost on the `request` event only; `upgrade` is a separate
|
|
@@ -187,14 +304,131 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
|
|
|
187
304
|
return;
|
|
188
305
|
}
|
|
189
306
|
}
|
|
307
|
+
upgradedSockets.add(socket);
|
|
308
|
+
socket.once('close', () => upgradedSockets.delete(socket));
|
|
190
309
|
wss.handleUpgrade(req, socket as never, head, (ws: WebSocket) => {
|
|
191
310
|
attachPeer(bridge, ws);
|
|
192
311
|
});
|
|
193
|
-
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const publish = (): void => {
|
|
315
|
+
const currentOrigin = origin();
|
|
316
|
+
if (!currentOrigin?.port || attachmentClosed) return;
|
|
317
|
+
try {
|
|
318
|
+
mkdirSync(dirname(pointer), { recursive: true });
|
|
319
|
+
writeFileSync(pointer, JSON.stringify({
|
|
320
|
+
url: `http://${currentOrigin.host}:${currentOrigin.port}`,
|
|
321
|
+
mcpUrl: mount.mcpUrl(currentOrigin),
|
|
322
|
+
port: currentOrigin.port,
|
|
323
|
+
pid: process.pid,
|
|
324
|
+
instanceId: bridge.instanceId,
|
|
325
|
+
project,
|
|
326
|
+
}, null, 2) + '\n');
|
|
327
|
+
} catch {
|
|
328
|
+
// Discovery falls back to a port scan.
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const probeCollision = async (): Promise<void> => {
|
|
333
|
+
const currentOrigin = origin();
|
|
334
|
+
if (!collision || !currentOrigin?.port || attachmentClosed) return;
|
|
335
|
+
for (const probe of [`http://127.0.0.1:${currentOrigin.port}`, `http://[::1]:${currentOrigin.port}`]) {
|
|
336
|
+
try {
|
|
337
|
+
const response = await (collision.fetchImpl ?? fetch)(`${probe}${HEALTH_PATH}`, {
|
|
338
|
+
signal: AbortSignal.any([collisionAbort.signal, AbortSignal.timeout(1000)]),
|
|
339
|
+
});
|
|
340
|
+
if (attachmentClosed) return;
|
|
341
|
+
if (response.status !== 200) continue;
|
|
342
|
+
const body = (await response.json()) as { mode?: string; instanceId?: string };
|
|
343
|
+
if (attachmentClosed) return;
|
|
344
|
+
if (body.mode === 'sandbox' && body.instanceId && body.instanceId !== bridge.instanceId) {
|
|
345
|
+
collision.warn(
|
|
346
|
+
`\n⚠ pyric: another sandbox already serves port ${currentOrigin.port} on a different loopback ` +
|
|
347
|
+
`family (${probe}). Two dev servers are colliding across IPv4/IPv6 — your MCP ` +
|
|
348
|
+
`agent and browser can land on DIFFERENT sandboxes (writes seem to vanish). ` +
|
|
349
|
+
`Stop the other server, or give this app a unique \`server.port\` so the two ` +
|
|
350
|
+
`don't share one (pinning server.host to a family the squatter holds would ` +
|
|
351
|
+
`just EADDRINUSE).\n`,
|
|
352
|
+
{ timestamp: true },
|
|
353
|
+
);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
} catch {
|
|
357
|
+
if (attachmentClosed) return;
|
|
358
|
+
// The other loopback family is silent.
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const announce = (): void => {
|
|
364
|
+
publish();
|
|
365
|
+
if (!collisionProbe) {
|
|
366
|
+
const current = probeCollision();
|
|
367
|
+
collisionProbe = current;
|
|
368
|
+
void current.finally(() => {
|
|
369
|
+
if (collisionProbe === current) collisionProbe = null;
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
const attachment: BridgeHostAttachment = {
|
|
374
|
+
close(): Promise<void> {
|
|
375
|
+
if (attachmentClosePromise) return attachmentClosePromise;
|
|
376
|
+
attachmentClosePromise = (async () => {
|
|
377
|
+
attachmentClosed = true;
|
|
378
|
+
collisionAbort.abort();
|
|
379
|
+
for (const server of servers) server.removeListener('upgrade', onUpgrade as never);
|
|
380
|
+
lifecycleServer?.removeListener('listening', announce);
|
|
381
|
+
lifecycleServer?.removeListener('close', onClose);
|
|
382
|
+
await collisionProbe;
|
|
383
|
+
removeOwnedPointer(pointer);
|
|
384
|
+
for (const client of wss.clients) client.terminate();
|
|
385
|
+
for (const socket of upgradedSockets) socket.destroy();
|
|
386
|
+
upgradedSockets.clear();
|
|
387
|
+
await new Promise<void>((resolve) => {
|
|
388
|
+
let settled = false;
|
|
389
|
+
const done = (): void => {
|
|
390
|
+
if (settled) return;
|
|
391
|
+
settled = true;
|
|
392
|
+
clearTimeout(fallback);
|
|
393
|
+
resolve();
|
|
394
|
+
};
|
|
395
|
+
// `noServer` owns no listener socket. Once upgrades are detached
|
|
396
|
+
// and clients are terminated, a missing ws `close` callback must
|
|
397
|
+
// not deadlock the host's ordered shutdown.
|
|
398
|
+
const fallback = setTimeout(done, 500);
|
|
399
|
+
fallback.unref();
|
|
400
|
+
try {
|
|
401
|
+
wss.close(done);
|
|
402
|
+
} catch {
|
|
403
|
+
done();
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
attachments.delete(attachment);
|
|
407
|
+
})();
|
|
408
|
+
return attachmentClosePromise;
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
const onClose = (): void => { void attachment.close(); };
|
|
412
|
+
|
|
413
|
+
for (const server of servers) server.on('upgrade', onUpgrade as never);
|
|
414
|
+
if (closeOnServerClose) lifecycleServer?.once('close', onClose);
|
|
415
|
+
if ((lifecycleServer as unknown as { listening?: boolean } | undefined)?.listening) announce();
|
|
416
|
+
else lifecycleServer?.once('listening', announce);
|
|
417
|
+
attachments.add(attachment);
|
|
418
|
+
return attachment;
|
|
194
419
|
},
|
|
195
420
|
sandboxConnected: () => bridge.health().sandboxConnected === true,
|
|
196
|
-
instanceId: bridge.instanceId,
|
|
197
421
|
wsUrl: ({ host, port }) => `ws://${host}:${port}${WS_PATH}`,
|
|
198
422
|
mcpUrl: ({ host, port }) => `http://${host}:${port}${MCP_PATH}`,
|
|
423
|
+
close(): Promise<void> {
|
|
424
|
+
if (closePromise) return closePromise;
|
|
425
|
+
closePromise = (async () => {
|
|
426
|
+
closed = true;
|
|
427
|
+
await Promise.all([...attachments].map((attachment) => attachment.close()));
|
|
428
|
+
await Promise.all([...new Set([...sessions.values(), ...pendingSessions])].map(closeSession));
|
|
429
|
+
})();
|
|
430
|
+
return closePromise;
|
|
431
|
+
},
|
|
199
432
|
};
|
|
433
|
+
return mount;
|
|
200
434
|
}
|