@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
package/src/serve/namespace.ts
CHANGED
|
@@ -10,18 +10,18 @@
|
|
|
10
10
|
* Bridge routes (`/__pyric/mcp`, `/__pyric/sandbox`) mount here in P2.
|
|
11
11
|
*/
|
|
12
12
|
import { randomBytes } from 'node:crypto';
|
|
13
|
-
import { existsSync
|
|
14
|
-
import { basename,
|
|
13
|
+
import { existsSync } from 'node:fs';
|
|
14
|
+
import { basename, join } from 'node:path';
|
|
15
15
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
16
16
|
import type { ActivityIncident } from 'pyric/firestore/internal';
|
|
17
17
|
import { collectBody } from '../bridge/server/peer.js';
|
|
18
18
|
import { StateFileError, type StateSection, type StateStore } from './state-store.js';
|
|
19
19
|
import { createWriterLock, type WriterLock } from './writer-lock.js';
|
|
20
20
|
import { createStudioRoutes, type StudioRouteOptions } from './studio/index.js';
|
|
21
|
-
import {
|
|
22
|
-
import { SANDBOX_BUILD_MARKER } from './sandbox-marker.js';
|
|
21
|
+
import { pipeFileToResponse, type ServeLogger } from './server.js';
|
|
23
22
|
import type { InitPayload } from './init-payload.js';
|
|
24
23
|
import { handleActivity } from './activity-route.js';
|
|
24
|
+
import { createSiteTreeHandler } from './site-tree.js';
|
|
25
25
|
export type { InitPayload } from './init-payload.js';
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -34,12 +34,19 @@ export interface ServeEventHub {
|
|
|
34
34
|
handle(req: IncomingMessage, res: ServerResponse): void;
|
|
35
35
|
broadcast(event: string, data: unknown): void;
|
|
36
36
|
clientCount(): number;
|
|
37
|
+
/** End all open streams. Idempotent; used by host-neutral session cleanup. */
|
|
38
|
+
close(): void;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export function createEventHub(): ServeEventHub {
|
|
40
42
|
const clients = new Set<ServerResponse>();
|
|
43
|
+
let closed = false;
|
|
41
44
|
return {
|
|
42
45
|
handle(req, res) {
|
|
46
|
+
if (closed) {
|
|
47
|
+
res.writeHead(503, { 'content-type': 'text/plain' }).end('sandbox session closed');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
43
50
|
res.writeHead(200, {
|
|
44
51
|
'content-type': 'text/event-stream',
|
|
45
52
|
'cache-control': 'no-store',
|
|
@@ -53,6 +60,7 @@ export function createEventHub(): ServeEventHub {
|
|
|
53
60
|
res.on('error', () => clients.delete(res));
|
|
54
61
|
},
|
|
55
62
|
broadcast(event, data) {
|
|
63
|
+
if (closed) return;
|
|
56
64
|
const frame = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
|
|
57
65
|
for (const res of clients) {
|
|
58
66
|
try {
|
|
@@ -63,6 +71,12 @@ export function createEventHub(): ServeEventHub {
|
|
|
63
71
|
}
|
|
64
72
|
},
|
|
65
73
|
clientCount: () => clients.size,
|
|
74
|
+
close() {
|
|
75
|
+
if (closed) return;
|
|
76
|
+
closed = true;
|
|
77
|
+
for (const res of clients) res.end();
|
|
78
|
+
clients.clear();
|
|
79
|
+
},
|
|
66
80
|
};
|
|
67
81
|
}
|
|
68
82
|
|
|
@@ -85,22 +99,14 @@ export interface NamespaceOptions {
|
|
|
85
99
|
* current fixture JSON (200) or 404 when nothing is captured yet, so the
|
|
86
100
|
* served worker can re-hydrate its event history on boot after a death. */
|
|
87
101
|
capture?: { write(json: string): void; read(): string | null };
|
|
102
|
+
/** Unified Astro documentation + Studio tree, built for `/__pyric/ui/`. */
|
|
103
|
+
siteUiDir?: string;
|
|
104
|
+
/** Served SharedWorker epoch stamped only into Studio entry documents. */
|
|
105
|
+
workerVersion?: string;
|
|
88
106
|
/** `--ui` (Pyric Studio): mounts `/__pyric/workspace` + `/__pyric/projects`
|
|
89
107
|
* (disk-backed `WorkspaceStore`/`ProjectStore`, plus the SSE watch stream)
|
|
90
108
|
* that `@pyric/studio`'s `local` mode talks to. */
|
|
91
109
|
studio?: StudioRouteOptions;
|
|
92
|
-
/** `--ui` (Pyric Studio): the dir of the built Studio app, served under
|
|
93
|
-
* `/__pyric/ui/`. Resolved by file path in the CLI (@pyric/cli never
|
|
94
|
-
* imports `@pyric/studio`). Absent when `--ui` is off or the build is
|
|
95
|
-
* missing. */
|
|
96
|
-
studioUiDir?: string;
|
|
97
|
-
/** `--ui` (Pyric Studio): the built docs site (site-docs), served so the
|
|
98
|
-
* Studio Docs tab has local docs without the hosted site. Built with base
|
|
99
|
-
* `/__pyric/ui/`, so its output straddles two subtrees under the mount:
|
|
100
|
-
* the pages/twins/index.json live under `/__pyric/ui/docs/`, but the shared
|
|
101
|
-
* assets live at `/__pyric/ui/_astro/` (Astro's asset dir, at the base
|
|
102
|
-
* root — NOT under `docs/`). Both are served from this one dir. */
|
|
103
|
-
docsUiDir?: string;
|
|
104
110
|
/** The OpenAI-compatible upstream `/__pyric/ai-proxy` forwards to
|
|
105
111
|
* (pyric/ai — cdd-deltas #98.2). Falls back to the
|
|
106
112
|
* `PYRIC_AI_PROXY_UPSTREAM` env var, then `http://localhost:11434/v1`
|
|
@@ -467,6 +473,9 @@ async function handleDenials(
|
|
|
467
473
|
export function createPyricNamespace(opts: NamespaceOptions) {
|
|
468
474
|
const writerLock = createWriterLock();
|
|
469
475
|
const studioRoutes = opts.studio ? createStudioRoutes(opts.studio) : null;
|
|
476
|
+
const siteTree = opts.siteUiDir
|
|
477
|
+
? createSiteTreeHandler(opts.siteUiDir, opts.workerVersion)
|
|
478
|
+
: null;
|
|
470
479
|
const denialThrottle = createDenialThrottle();
|
|
471
480
|
// Issued once per server boot. The outer static/Vite host guard protects
|
|
472
481
|
// init.json before this capability is disclosed to the served runtime.
|
|
@@ -517,159 +526,7 @@ export function createPyricNamespace(opts: NamespaceOptions) {
|
|
|
517
526
|
pipeFileToResponse(file, res);
|
|
518
527
|
return true;
|
|
519
528
|
}
|
|
520
|
-
|
|
521
|
-
// `/__pyric/ui/` studio handler below: that handler's SPA fallback answers
|
|
522
|
-
// every miss with Studio's index.html, which would swallow docs pages and
|
|
523
|
-
// (worse) return HTML for a missing docs asset. Built with base
|
|
524
|
-
// `/__pyric/ui/`, the docs output lives in TWO subtrees under the mount —
|
|
525
|
-
// pages/twins/index.json under `/__pyric/ui/docs/`, and shared assets at
|
|
526
|
-
// `/__pyric/ui/_astro/` (Astro's asset dir sits at the base root, not under
|
|
527
|
-
// `docs/`). We claim both; `_astro` is Astro-specific and never collides
|
|
528
|
-
// with Studio (Vite emits `/__pyric/ui/assets/`). No SPA fallback here — a
|
|
529
|
-
// genuinely missing docs page 404s (a broken doc link must fail loudly, not
|
|
530
|
-
// masquerade as another page). Directory-format pages (`<slug>/index.html`)
|
|
531
|
-
// and `bunx serve`-style extensionless→trailing-slash redirects are handled
|
|
532
|
-
// by resolveStaticFile + the directory redirect below.
|
|
533
|
-
if (
|
|
534
|
-
opts.docsUiDir &&
|
|
535
|
-
(url.pathname === '/__pyric/ui/docs' ||
|
|
536
|
-
url.pathname.startsWith('/__pyric/ui/docs/') ||
|
|
537
|
-
url.pathname.startsWith('/__pyric/ui/_astro/'))
|
|
538
|
-
) {
|
|
539
|
-
const rel = url.pathname.slice('/__pyric/ui'.length) || '/';
|
|
540
|
-
// `bunx serve` parity: an extensionless path that names a real directory
|
|
541
|
-
// (e.g. `/__pyric/ui/docs` or `/__pyric/ui/docs/<slug>`) redirects to the
|
|
542
|
-
// trailing-slash form so the directory's index.html loads with correct
|
|
543
|
-
// relative-URL resolution.
|
|
544
|
-
if (!rel.endsWith('/') && !extname(rel)) {
|
|
545
|
-
const dir = join(opts.docsUiDir, decodeURIComponent(rel));
|
|
546
|
-
if (existsSync(dir) && statSync(dir).isDirectory()) {
|
|
547
|
-
res.writeHead(301, { location: `${url.pathname}/` }).end();
|
|
548
|
-
return true;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
const file = resolveStaticFile(opts.docsUiDir, rel);
|
|
552
|
-
if (!file) {
|
|
553
|
-
res.writeHead(404).end('not found');
|
|
554
|
-
return true;
|
|
555
|
-
}
|
|
556
|
-
res.writeHead(200, { 'content-type': contentTypeFor(file), 'cache-control': 'no-store' });
|
|
557
|
-
pipeFileToResponse(file, res);
|
|
558
|
-
return true;
|
|
559
|
-
}
|
|
560
|
-
if (
|
|
561
|
-
opts.studioUiDir &&
|
|
562
|
-
(url.pathname === '/__pyric/ui' || url.pathname.startsWith('/__pyric/ui/'))
|
|
563
|
-
) {
|
|
564
|
-
// The built Pyric Studio app. Served verbatim (NOT through
|
|
565
|
-
// injectServeTags: that import-map/init injection is for sandbox pages,
|
|
566
|
-
// not Studio). Studio uses History-API routing under this mount, so any
|
|
567
|
-
// path that doesn't resolve to a real file falls back to index.html —
|
|
568
|
-
// INCLUDING paths with dots (deep links like /storage/uploads/logo.png).
|
|
569
|
-
// Only misses under Vite's content-hashed asset dir stay hard 404s, so a
|
|
570
|
-
// broken script/style URL fails loudly instead of returning HTML.
|
|
571
|
-
if (url.pathname === '/__pyric/ui') {
|
|
572
|
-
res.writeHead(301, { location: '/__pyric/ui/' }).end();
|
|
573
|
-
return true;
|
|
574
|
-
}
|
|
575
|
-
const rel = url.pathname.slice('/__pyric/ui'.length) || '/';
|
|
576
|
-
let file = resolveStaticFile(opts.studioUiDir, rel);
|
|
577
|
-
if (!file && !rel.startsWith('/assets/')) {
|
|
578
|
-
file = resolveStaticFile(opts.studioUiDir, '/index.html');
|
|
579
|
-
}
|
|
580
|
-
if (!file) {
|
|
581
|
-
res.writeHead(404).end('not found');
|
|
582
|
-
return true;
|
|
583
|
-
}
|
|
584
|
-
res.writeHead(200, { 'content-type': contentTypeFor(file), 'cache-control': 'no-store' });
|
|
585
|
-
pipeFileToResponse(file, res);
|
|
586
|
-
return true;
|
|
587
|
-
}
|
|
529
|
+
if (siteTree?.(req, res, url)) return true;
|
|
588
530
|
return false; // unknown /__pyric/* → caller 404s
|
|
589
531
|
};
|
|
590
532
|
}
|
|
591
|
-
|
|
592
|
-
// ─── HTML injection ───────────────────────────────────────────────────
|
|
593
|
-
|
|
594
|
-
/** The import-map targets. Spec → served URL. */
|
|
595
|
-
export function sdkImportMap(): Record<string, string> {
|
|
596
|
-
return {
|
|
597
|
-
'firebase/ai': '/__pyric/sdk/ai.js',
|
|
598
|
-
'firebase/app': '/__pyric/sdk/app.js',
|
|
599
|
-
'firebase/auth': '/__pyric/sdk/auth.js',
|
|
600
|
-
'firebase/database': '/__pyric/sdk/database.js',
|
|
601
|
-
'firebase/firestore': '/__pyric/sdk/firestore.js',
|
|
602
|
-
'firebase/messaging': '/__pyric/sdk/messaging.js',
|
|
603
|
-
'firebase/messaging/sw': '/__pyric/sdk/messaging-sw.js',
|
|
604
|
-
'firebase/storage': '/__pyric/sdk/storage.js',
|
|
605
|
-
};
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
/**
|
|
609
|
-
* Inject the import map + init script into an HTML document. The import map
|
|
610
|
-
* MUST precede any module script that imports a mapped specifier, so both
|
|
611
|
-
* tags go at the very start of `<head>` (fallbacks: after `<html>`, else
|
|
612
|
-
* prepended). Idempotent — a page already carrying the marker is untouched
|
|
613
|
-
* (matters when transformHtml runs over an SPA fallback repeatedly).
|
|
614
|
-
*/
|
|
615
|
-
export function injectServeTags(
|
|
616
|
-
html: string,
|
|
617
|
-
importMap: Record<string, string> = sdkImportMap(),
|
|
618
|
-
workerVersion?: string,
|
|
619
|
-
forceInPage = false,
|
|
620
|
-
): string {
|
|
621
|
-
const MARKER = 'data-pyric-serve';
|
|
622
|
-
if (html.includes(MARKER)) return html;
|
|
623
|
-
// A pyric SANDBOX BUILD (`vite build` under the pyricSandbox plugin's sandbox
|
|
624
|
-
// mode) already BUNDLES its own runtime + init chunk — injecting the import
|
|
625
|
-
// map + /__pyric/sdk/init.js on top would boot a SECOND runtime instance on
|
|
626
|
-
// the page (two banners, two bridge peer registrations, races between them).
|
|
627
|
-
// The bundle owns the sandbox for a marked page: it fetches
|
|
628
|
-
// /__pyric/init.json itself (worker path: the SharedWorker does; in-page
|
|
629
|
-
// path: the runtime does) and owns rules hot-reload the same way. The ONLY
|
|
630
|
-
// serve-time contribution left is the worker-version staleness stamp, which
|
|
631
|
-
// the bundled runtime reads from this meta to warn about a stale
|
|
632
|
-
// still-running SharedWorker.
|
|
633
|
-
if (html.includes(SANDBOX_BUILD_MARKER)) {
|
|
634
|
-
if (!workerVersion || html.includes('pyric-worker-v')) return html;
|
|
635
|
-
const meta = `<meta name="pyric-worker-v" content="${workerVersion}" ${MARKER}>`;
|
|
636
|
-
const headTag = html.match(/<head[^>]*>/i);
|
|
637
|
-
if (headTag && headTag.index !== undefined) {
|
|
638
|
-
const at = headTag.index + headTag[0].length;
|
|
639
|
-
return html.slice(0, at) + meta + html.slice(at);
|
|
640
|
-
}
|
|
641
|
-
return meta + html;
|
|
642
|
-
}
|
|
643
|
-
// Stamp the worker's content hash so the page can DETECT staleness: a live
|
|
644
|
-
// SharedWorker survives serve restarts + reloads and can't hot-update, so it
|
|
645
|
-
// keeps running old code until every tab of the origin closes. The worker
|
|
646
|
-
// name is intentionally STABLE (one backend shared by all tabs), so rather
|
|
647
|
-
// than split tabs across versions, `runtime.ts` compares this served hash to
|
|
648
|
-
// the running worker's baked hash and warns the user to close all tabs.
|
|
649
|
-
const versionMeta = workerVersion
|
|
650
|
-
? `<meta name="pyric-worker-v" content="${workerVersion}" ${MARKER}>`
|
|
651
|
-
: '';
|
|
652
|
-
// `--bridge`: the MCP bridge peers with the IN-PAGE sandbox, so force the page
|
|
653
|
-
// off the default SharedWorker path. Otherwise the agent drives an empty
|
|
654
|
-
// in-page sandbox while the app's data lives in the worker. Set before any app
|
|
655
|
-
// code runs; mirrors the Vite plugin's transformIndexHtml.
|
|
656
|
-
const forceTag = forceInPage
|
|
657
|
-
? `<script ${MARKER}>globalThis.__PYRIC_FORCE_INPAGE__=true;</script>`
|
|
658
|
-
: '';
|
|
659
|
-
const tags =
|
|
660
|
-
versionMeta +
|
|
661
|
-
forceTag +
|
|
662
|
-
`<script type="importmap" ${MARKER}>${JSON.stringify({ imports: importMap })}</script>` +
|
|
663
|
-
`<script type="module" src="/__pyric/sdk/init.js" ${MARKER}></script>`;
|
|
664
|
-
const head = html.match(/<head[^>]*>/i);
|
|
665
|
-
if (head && head.index !== undefined) {
|
|
666
|
-
const at = head.index + head[0].length;
|
|
667
|
-
return html.slice(0, at) + tags + html.slice(at);
|
|
668
|
-
}
|
|
669
|
-
const htmlTag = html.match(/<html[^>]*>/i);
|
|
670
|
-
if (htmlTag && htmlTag.index !== undefined) {
|
|
671
|
-
const at = htmlTag.index + htmlTag[0].length;
|
|
672
|
-
return html.slice(0, at) + tags + html.slice(at);
|
|
673
|
-
}
|
|
674
|
-
return tags + html;
|
|
675
|
-
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
|
+
import type { ActivityIncident } from 'pyric/firestore/internal';
|
|
6
|
+
import type { FirebaseJson } from '../cli/firebase-json.js';
|
|
7
|
+
import { createCaptureStore, type CaptureStore } from './capture-store.js';
|
|
8
|
+
import type { InitPayload } from './init-payload.js';
|
|
9
|
+
import {
|
|
10
|
+
loadProjectDatabaseRules,
|
|
11
|
+
loadProjectRules,
|
|
12
|
+
loadProjectStorageRules,
|
|
13
|
+
prepareRulesSource,
|
|
14
|
+
rulesHashOf,
|
|
15
|
+
} from './rules.js';
|
|
16
|
+
import { createEventHub, createPyricNamespace } from './namespace.js';
|
|
17
|
+
import { diskProjectStore, diskWorkspace } from './studio/index.js';
|
|
18
|
+
import type { ServeLogger } from './server.js';
|
|
19
|
+
import {
|
|
20
|
+
createStateStore,
|
|
21
|
+
firestoreDocCount,
|
|
22
|
+
STATE_FILE_VERSION,
|
|
23
|
+
type PyricStateFile,
|
|
24
|
+
type StateStore,
|
|
25
|
+
} from './state-store.js';
|
|
26
|
+
|
|
27
|
+
export interface SandboxSessionOptions {
|
|
28
|
+
projectDir: string;
|
|
29
|
+
firebaseConfig: FirebaseJson | null;
|
|
30
|
+
sdk: { dir: string; workerVersion?: string };
|
|
31
|
+
seedFile?: string;
|
|
32
|
+
capture?: boolean;
|
|
33
|
+
persistence?: { fresh?: boolean };
|
|
34
|
+
studio?: false | { siteUiDir?: string };
|
|
35
|
+
bridgeUrl?: () => string | null;
|
|
36
|
+
ai?: InitPayload['ai'];
|
|
37
|
+
aiProxyUpstream?: string;
|
|
38
|
+
logger?: ServeLogger;
|
|
39
|
+
activity?: (incident: ActivityIncident) => void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface SandboxSessionSummary {
|
|
43
|
+
rules: {
|
|
44
|
+
firestore: { sourcePath: string | null; hash: string | null };
|
|
45
|
+
database: { sourcePath: string | null; hash: string | null };
|
|
46
|
+
storage: { sourcePath: string | null; hash: string | null };
|
|
47
|
+
};
|
|
48
|
+
persistence: null | {
|
|
49
|
+
path: string;
|
|
50
|
+
backupPath: string;
|
|
51
|
+
restoredDocs: number;
|
|
52
|
+
restoredUsers: number;
|
|
53
|
+
restored: boolean;
|
|
54
|
+
};
|
|
55
|
+
capturePath: string | null;
|
|
56
|
+
seedLabel: string | null;
|
|
57
|
+
seedStaged: boolean;
|
|
58
|
+
studioMounted: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface SandboxSession {
|
|
62
|
+
readonly summary: SandboxSessionSummary;
|
|
63
|
+
payload(): InitPayload;
|
|
64
|
+
handle(req: IncomingMessage, res: ServerResponse, url: URL): boolean | Promise<boolean>;
|
|
65
|
+
reloadFirestoreRules(): Promise<RulesReloadResult>;
|
|
66
|
+
close(): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export class SandboxSeedError extends Error {
|
|
70
|
+
constructor(
|
|
71
|
+
readonly kind: 'read' | 'shape',
|
|
72
|
+
readonly path: string,
|
|
73
|
+
readonly detail: string,
|
|
74
|
+
) {
|
|
75
|
+
super(kind === 'read' ? `failed to read seed ${path}: ${detail}` : `seed must be a JSON object (${detail})`);
|
|
76
|
+
this.name = 'SandboxSeedError';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type RulesReloadResult =
|
|
81
|
+
| { kind: 'not-configured' }
|
|
82
|
+
| { kind: 'reloaded'; rulesHash: string; clients: number }
|
|
83
|
+
| { kind: 'rejected'; error: Error };
|
|
84
|
+
|
|
85
|
+
export async function createSandboxSession(
|
|
86
|
+
options: SandboxSessionOptions,
|
|
87
|
+
): Promise<SandboxSession> {
|
|
88
|
+
// Preserve the established fail-fast order: Firestore, then RTDB, then
|
|
89
|
+
// Storage. Callers historically surfaced the first error in this sequence.
|
|
90
|
+
const firestore = await loadProjectRules(options.projectDir, options.firebaseConfig);
|
|
91
|
+
const database = await loadProjectDatabaseRules(options.projectDir, options.firebaseConfig);
|
|
92
|
+
const storage = await loadProjectStorageRules(options.projectDir, options.firebaseConfig);
|
|
93
|
+
const live = {
|
|
94
|
+
rules: firestore.rules,
|
|
95
|
+
rulesHash: firestore.rulesHash,
|
|
96
|
+
};
|
|
97
|
+
const events = createEventHub();
|
|
98
|
+
const capture: CaptureStore | undefined = (options.capture ?? true)
|
|
99
|
+
? createCaptureStore(options.projectDir)
|
|
100
|
+
: undefined;
|
|
101
|
+
const state: StateStore | undefined = options.persistence
|
|
102
|
+
? createStateStore(options.projectDir)
|
|
103
|
+
: undefined;
|
|
104
|
+
if (state && options.persistence?.fresh) {
|
|
105
|
+
for (const file of [state.path, state.backupPath]) {
|
|
106
|
+
if (existsSync(file)) rmSync(file);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
let persisted = state?.load() ?? null;
|
|
110
|
+
let seed: Record<string, Record<string, unknown>> | null = null;
|
|
111
|
+
let seedState: unknown | null = null;
|
|
112
|
+
let seedUsers: Record<string, unknown>[] | null = null;
|
|
113
|
+
let seedLabel: string | null = null;
|
|
114
|
+
if (options.seedFile) {
|
|
115
|
+
const seedPath = resolve(options.projectDir, options.seedFile);
|
|
116
|
+
let parsed: unknown;
|
|
117
|
+
try {
|
|
118
|
+
parsed = JSON.parse(readFileSync(seedPath, 'utf8')) as unknown;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
throw new SandboxSeedError('read', seedPath, error instanceof Error ? error.message : String(error));
|
|
121
|
+
}
|
|
122
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
123
|
+
throw new SandboxSeedError('shape', seedPath, `got ${Array.isArray(parsed) ? 'array' : typeof parsed}`);
|
|
124
|
+
}
|
|
125
|
+
const record = parsed as Record<string, unknown>;
|
|
126
|
+
if (record.version === STATE_FILE_VERSION && ('firestore' in record || 'auth' in record)) {
|
|
127
|
+
const fixture = record as unknown as PyricStateFile;
|
|
128
|
+
const restoredDocs = firestoreDocCount(fixture.firestore);
|
|
129
|
+
const restoredUsers = fixture.auth?.users?.length ?? 0;
|
|
130
|
+
seedLabel = `${restoredDocs} doc(s) + ${restoredUsers} user(s) from state fixture`;
|
|
131
|
+
if (state && !state.exists()) {
|
|
132
|
+
if (fixture.firestore != null) state.writeSection('firestore', fixture.firestore);
|
|
133
|
+
if (fixture.auth != null) state.writeSection('auth', fixture.auth);
|
|
134
|
+
persisted = state.load();
|
|
135
|
+
} else if (!state) {
|
|
136
|
+
seedState = fixture.firestore ?? null;
|
|
137
|
+
seedUsers = (fixture.auth?.users as Record<string, unknown>[] | undefined) ?? null;
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
seed = record as Record<string, Record<string, unknown>>;
|
|
141
|
+
seedLabel = `${Object.keys(seed).length} document(s)`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const payload = (): InitPayload => ({
|
|
146
|
+
rules: live.rules,
|
|
147
|
+
rulesHash: live.rulesHash,
|
|
148
|
+
databaseRules: database.rules,
|
|
149
|
+
databaseRulesHash: database.rulesHash,
|
|
150
|
+
databaseUrl: database.databaseUrl,
|
|
151
|
+
storageRules: storage.rules,
|
|
152
|
+
storageRulesHash: storage.rulesHash,
|
|
153
|
+
projectKey: options.projectDir,
|
|
154
|
+
bridgeUrl: options.bridgeUrl?.() ?? null,
|
|
155
|
+
seed: state?.exists() ? null : seed,
|
|
156
|
+
seedState,
|
|
157
|
+
persist: Boolean(state),
|
|
158
|
+
capture: Boolean(capture),
|
|
159
|
+
authUsers: state
|
|
160
|
+
? ((state.readSection('auth') as { users?: Record<string, unknown>[] } | null)?.users ?? null)
|
|
161
|
+
: seedUsers,
|
|
162
|
+
messaging: true,
|
|
163
|
+
ai: options.ai ?? null,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const summary: SandboxSessionSummary = {
|
|
167
|
+
rules: {
|
|
168
|
+
firestore: { sourcePath: firestore.sourcePath, hash: firestore.rulesHash },
|
|
169
|
+
database: { sourcePath: database.sourcePath, hash: database.rulesHash },
|
|
170
|
+
storage: { sourcePath: storage.sourcePath, hash: storage.rulesHash },
|
|
171
|
+
},
|
|
172
|
+
persistence: state
|
|
173
|
+
? {
|
|
174
|
+
path: state.path,
|
|
175
|
+
backupPath: state.backupPath,
|
|
176
|
+
restoredDocs: firestoreDocCount(persisted?.firestore),
|
|
177
|
+
restoredUsers: persisted?.auth?.users?.length ?? 0,
|
|
178
|
+
restored: persisted !== null,
|
|
179
|
+
}
|
|
180
|
+
: null,
|
|
181
|
+
capturePath: capture?.path ?? null,
|
|
182
|
+
seedLabel,
|
|
183
|
+
seedStaged: Boolean((seed && !state?.exists()) || seedState || seedUsers),
|
|
184
|
+
studioMounted: Boolean(options.studio),
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const namespace = createPyricNamespace({
|
|
188
|
+
sdkDir: options.sdk.dir,
|
|
189
|
+
initPayload: payload,
|
|
190
|
+
events,
|
|
191
|
+
state,
|
|
192
|
+
capture,
|
|
193
|
+
studio: options.studio
|
|
194
|
+
? {
|
|
195
|
+
workspace: diskWorkspace(options.projectDir),
|
|
196
|
+
projects: diskProjectStore(join(options.projectDir, '.pyric', 'projects')),
|
|
197
|
+
}
|
|
198
|
+
: undefined,
|
|
199
|
+
siteUiDir: options.studio ? options.studio.siteUiDir : undefined,
|
|
200
|
+
workerVersion: options.sdk.workerVersion,
|
|
201
|
+
aiProxyUpstream: options.aiProxyUpstream,
|
|
202
|
+
activity: options.activity,
|
|
203
|
+
logger: options.logger,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const reloadFirestoreRules = async (): Promise<RulesReloadResult> => {
|
|
207
|
+
if (!firestore.sourcePath) return { kind: 'not-configured' };
|
|
208
|
+
try {
|
|
209
|
+
const raw = await readFile(firestore.sourcePath, 'utf8');
|
|
210
|
+
const rules = prepareRulesSource(raw, firestore.sourcePath);
|
|
211
|
+
const rulesHash = rulesHashOf(rules);
|
|
212
|
+
live.rules = rules;
|
|
213
|
+
live.rulesHash = rulesHash;
|
|
214
|
+
events.broadcast('rules-changed', { rules, rulesHash });
|
|
215
|
+
return { kind: 'reloaded', rulesHash, clients: events.clientCount() };
|
|
216
|
+
} catch (error) {
|
|
217
|
+
return { kind: 'rejected', error: error instanceof Error ? error : new Error(String(error)) };
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
let closePromise: Promise<void> | null = null;
|
|
221
|
+
const close = (): Promise<void> => {
|
|
222
|
+
closePromise ??= Promise.resolve().then(() => events.close());
|
|
223
|
+
return closePromise;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
summary,
|
|
228
|
+
payload,
|
|
229
|
+
handle: namespace,
|
|
230
|
+
reloadFirestoreRules,
|
|
231
|
+
close,
|
|
232
|
+
};
|
|
233
|
+
}
|
package/src/serve/server.ts
CHANGED
|
@@ -173,14 +173,29 @@ export function contentTypeFor(path: string): string {
|
|
|
173
173
|
return CONTENT_TYPES[extname(path).toLowerCase()] ?? 'application/octet-stream';
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
/**
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
/** Decode a URL pathname for static-file lookup. Malformed escapes are misses. */
|
|
177
|
+
export function decodeStaticPathname(pathname: string): string | null {
|
|
178
|
+
try {
|
|
179
|
+
return decodeURIComponent(pathname);
|
|
180
|
+
} catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** Resolve a request path inside `publicDir`, refusing malformed or escaping paths. */
|
|
186
|
+
export function resolveStaticPath(publicDir: string, pathname: string): string | null {
|
|
187
|
+
const decoded = decodeStaticPathname(pathname);
|
|
188
|
+
if (decoded === null) return null;
|
|
180
189
|
const root = resolve(publicDir);
|
|
181
190
|
const candidate = normalize(join(root, decoded));
|
|
182
191
|
if (candidate !== root && !candidate.startsWith(root + sep)) return null; // traversal
|
|
183
|
-
|
|
192
|
+
return candidate;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Resolve an existing static file inside `publicDir`. */
|
|
196
|
+
export function resolveStaticFile(publicDir: string, pathname: string): string | null {
|
|
197
|
+
let file = resolveStaticPath(publicDir, pathname);
|
|
198
|
+
if (file === null) return null;
|
|
184
199
|
if (existsSync(file) && statSync(file).isDirectory()) file = join(file, 'index.html');
|
|
185
200
|
if (!existsSync(file) || !statSync(file).isFile()) return null;
|
|
186
201
|
return file;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
+
import { extname, join } from 'node:path';
|
|
4
|
+
import {
|
|
5
|
+
contentTypeFor,
|
|
6
|
+
decodeStaticPathname,
|
|
7
|
+
pipeFileToResponse,
|
|
8
|
+
resolveStaticFile,
|
|
9
|
+
resolveStaticPath,
|
|
10
|
+
} from './server.js';
|
|
11
|
+
|
|
12
|
+
interface StudioRoutesManifest {
|
|
13
|
+
routes: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface RequestWithOriginalUrl extends IncomingMessage {
|
|
17
|
+
originalUrl?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const SITE_TREE_MOUNT_PATH = '/__pyric/ui';
|
|
21
|
+
const SITE_TREE_DESCENDANT_PREFIX = `${SITE_TREE_MOUNT_PATH}/`;
|
|
22
|
+
|
|
23
|
+
function studioRoutesFromSite(root: string): ReadonlySet<string> {
|
|
24
|
+
const manifestPath = join(root, 'studio-routes.json');
|
|
25
|
+
const parsed = JSON.parse(readFileSync(manifestPath, 'utf8')) as StudioRoutesManifest;
|
|
26
|
+
if (!Array.isArray(parsed.routes) || parsed.routes.some((route) => typeof route !== 'string')) {
|
|
27
|
+
throw new Error(`pyric: invalid Studio route manifest at ${manifestPath}`);
|
|
28
|
+
}
|
|
29
|
+
return new Set(parsed.routes);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function rawRequestPathname(request: RequestWithOriginalUrl, parsedUrl: URL): string {
|
|
33
|
+
let requestTarget = request.originalUrl;
|
|
34
|
+
|
|
35
|
+
if (requestTarget === undefined) {
|
|
36
|
+
requestTarget = request.url;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (requestTarget === undefined) {
|
|
40
|
+
return parsedUrl.pathname;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const queryStringStart = requestTarget.indexOf('?');
|
|
44
|
+
|
|
45
|
+
if (queryStringStart === -1) {
|
|
46
|
+
return requestTarget;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return requestTarget.slice(0, queryStringStart);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function isSiteTreePath(pathname: string): boolean {
|
|
53
|
+
if (pathname === SITE_TREE_MOUNT_PATH) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return pathname.startsWith(SITE_TREE_DESCENDANT_PREFIX);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function withWorkerVersion(html: string, workerVersion: string | undefined): string {
|
|
61
|
+
if (!workerVersion || html.includes('name="pyric-worker-v"')) return html;
|
|
62
|
+
if (!/^[a-f0-9]{16}$/.test(workerVersion)) {
|
|
63
|
+
throw new Error(`pyric: invalid SharedWorker epoch '${workerVersion}'`);
|
|
64
|
+
}
|
|
65
|
+
const meta = `<meta name="pyric-worker-v" content="${workerVersion}" data-pyric-serve>`;
|
|
66
|
+
const head = html.match(/<head[^>]*>/i);
|
|
67
|
+
if (!head || head.index === undefined) return meta + html;
|
|
68
|
+
const at = head.index + head[0].length;
|
|
69
|
+
return html.slice(0, at) + meta + html.slice(at);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Serve the one Astro tree with SPA fallback limited to generated Studio entries. */
|
|
73
|
+
export function createSiteTreeHandler(root: string, workerVersion?: string) {
|
|
74
|
+
const studioRoutes = studioRoutesFromSite(root);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
req: RequestWithOriginalUrl,
|
|
78
|
+
res: ServerResponse,
|
|
79
|
+
url: URL,
|
|
80
|
+
): boolean => {
|
|
81
|
+
// URL parsing normalizes encoded dot segments before `url.pathname`
|
|
82
|
+
// reaches us. Route and validate against the raw request target so an
|
|
83
|
+
// encoded traversal cannot cross from Studio into docs or static assets.
|
|
84
|
+
// Connect preserves that target in `originalUrl` after stripping a mount
|
|
85
|
+
// prefix from `url`.
|
|
86
|
+
const rawPathname = rawRequestPathname(req, url);
|
|
87
|
+
if (!isSiteTreePath(rawPathname)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
if (rawPathname === SITE_TREE_MOUNT_PATH) {
|
|
91
|
+
res.writeHead(301, { location: SITE_TREE_DESCENDANT_PREFIX }).end();
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let relativePath = rawPathname.slice(SITE_TREE_MOUNT_PATH.length);
|
|
96
|
+
|
|
97
|
+
if (relativePath === '') {
|
|
98
|
+
relativePath = '/';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const decodedRel = decodeStaticPathname(relativePath);
|
|
102
|
+
if (decodedRel === null || decodedRel.includes('\\')) {
|
|
103
|
+
res.writeHead(404).end('not found');
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
const decodedSegments = decodedRel.split('/').filter(Boolean);
|
|
107
|
+
if (decodedSegments.some((segment) => segment === '.' || segment === '..')) {
|
|
108
|
+
res.writeHead(404).end('not found');
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (!relativePath.endsWith('/') && !extname(relativePath)) {
|
|
112
|
+
const dir = resolveStaticPath(root, relativePath);
|
|
113
|
+
if (dir && existsSync(dir) && statSync(dir).isDirectory()) {
|
|
114
|
+
res.writeHead(301, { location: `${rawPathname}/` }).end();
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const first = decodedSegments[0];
|
|
120
|
+
const studioRequest = first === undefined || studioRoutes.has(first);
|
|
121
|
+
let file = resolveStaticFile(root, relativePath);
|
|
122
|
+
// Storage object names commonly contain extensions (logo.png), while the
|
|
123
|
+
// other Studio routes reserve extension-bearing misses for static assets.
|
|
124
|
+
const allowsDottedState = first === 'storage';
|
|
125
|
+
const hasDottedStateSegment = decodedSegments
|
|
126
|
+
.slice(1)
|
|
127
|
+
.some((segment) => segment.includes('.'));
|
|
128
|
+
if (!file && studioRequest && (allowsDottedState || !hasDottedStateSegment)) {
|
|
129
|
+
const entry = first === undefined ? '/index.html' : `/${first}/index.html`;
|
|
130
|
+
file = resolveStaticFile(root, entry);
|
|
131
|
+
}
|
|
132
|
+
if (!file) {
|
|
133
|
+
res.writeHead(404).end('not found');
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const contentType = contentTypeFor(file);
|
|
138
|
+
res.writeHead(200, { 'content-type': contentType, 'cache-control': 'no-store' });
|
|
139
|
+
if (studioRequest && contentType.includes('text/html')) {
|
|
140
|
+
res.end(withWorkerVersion(readFileSync(file, 'utf8'), workerVersion));
|
|
141
|
+
} else {
|
|
142
|
+
pipeFileToResponse(file, res);
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
};
|
|
146
|
+
}
|