@pyric/cli 0.1.0-alpha.11 → 0.1.0-alpha.13
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/cli/serve.js +4 -4
- package/dist/cli/serve.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 +2 -2
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/serve/bundler.d.ts +13 -8
- package/dist/serve/bundler.d.ts.map +1 -1
- package/dist/serve/bundler.js +31 -36
- package/dist/serve/bundler.js.map +1 -1
- package/dist/serve/docs-ui/docs/_rhythm/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +1 -1
- package/dist/serve/docs-ui/docs/ai-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/api-reference/index.html +2 -2
- package/dist/serve/docs-ui/docs/api-reference.md +1 -1
- package/dist/serve/docs-ui/docs/app-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/auth-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/ai-logic/index.html +44 -22
- package/dist/serve/docs-ui/docs/build/ai-logic.md +69 -21
- package/dist/serve/docs-ui/docs/build/authentication/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/realtime-database/index.html +1 -1
- package/dist/serve/docs-ui/docs/conformance-scores/index.html +1 -1
- package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/database-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/firestore-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +2 -1
- package/dist/serve/docs-ui/docs/get-started/how-the-swap-works.md +2 -0
- package/dist/serve/docs-ui/docs/get-started/start-building/index.html +3 -2
- package/dist/serve/docs-ui/docs/get-started/start-building.md +3 -1
- package/dist/serve/docs-ui/docs/index.json +349 -29
- package/dist/serve/docs-ui/docs/messaging-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/observe/resolve-runtime-status/index.html +28 -0
- package/dist/serve/docs-ui/docs/observe/resolve-runtime-status.md +47 -0
- package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +1 -1
- package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +1 -1
- package/dist/serve/docs-ui/docs/overview/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api/index.html +916 -0
- package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api.md +706 -0
- package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ai-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api/index.html +168 -76
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api.md +156 -73
- package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +11 -8
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api.md +17 -4
- package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-rules-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api/index.html +37 -14
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api.md +28 -8
- package/dist/serve/docs-ui/docs/pyric-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/rules-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
- package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +1 -1
- package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +1 -1
- package/dist/serve/docs-ui/docs/storage-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
- package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
- package/dist/serve/docs-ui/docs/tutorial/index.html +429 -0
- package/dist/serve/docs-ui/docs/tutorial.md +701 -0
- package/dist/serve/docs-ui/llms.txt +3 -1
- package/dist/serve/entries/init.d.ts.map +1 -1
- package/dist/serve/entries/init.js +3 -0
- package/dist/serve/entries/init.js.map +1 -1
- package/dist/serve/entries/runtime.d.ts.map +1 -1
- package/dist/serve/entries/runtime.js +20 -5
- package/dist/serve/entries/runtime.js.map +1 -1
- package/dist/serve/entries/worker-runtime.d.ts +2 -2
- package/dist/serve/entries/worker-runtime.d.ts.map +1 -1
- package/dist/serve/entries/worker-runtime.js +45 -10
- package/dist/serve/entries/worker-runtime.js.map +1 -1
- package/dist/serve/runtime/chip-config.d.ts +19 -0
- package/dist/serve/runtime/chip-config.d.ts.map +1 -0
- package/dist/serve/runtime/chip-config.js +19 -0
- package/dist/serve/runtime/chip-config.js.map +1 -0
- package/dist/serve/runtime/chip-install.d.ts +10 -0
- package/dist/serve/runtime/chip-install.d.ts.map +1 -0
- package/dist/serve/runtime/chip-install.js +15 -0
- package/dist/serve/runtime/chip-install.js.map +1 -0
- package/dist/serve/runtime/chip.d.ts +17 -0
- package/dist/serve/runtime/chip.d.ts.map +1 -0
- package/dist/serve/runtime/chip.js +257 -0
- package/dist/serve/runtime/chip.js.map +1 -0
- package/dist/serve/runtime/manifest.d.ts +22 -0
- package/dist/serve/runtime/manifest.d.ts.map +1 -0
- package/dist/serve/runtime/manifest.js +20 -0
- package/dist/serve/runtime/manifest.js.map +1 -0
- package/dist/serve/runtime/status.d.ts +49 -0
- package/dist/serve/runtime/status.d.ts.map +1 -0
- package/dist/serve/runtime/status.js +164 -0
- package/dist/serve/runtime/status.js.map +1 -0
- package/dist/serve/runtime/worker-connection.d.ts +4 -0
- package/dist/serve/runtime/worker-connection.d.ts.map +1 -0
- package/dist/serve/runtime/worker-connection.js +11 -0
- package/dist/serve/runtime/worker-connection.js.map +1 -0
- package/dist/serve/runtime/worker-generation.d.ts +14 -0
- package/dist/serve/runtime/worker-generation.d.ts.map +1 -0
- package/dist/serve/runtime/worker-generation.js +56 -0
- package/dist/serve/runtime/worker-generation.js.map +1 -0
- package/dist/serve/runtime/worker-replacement.d.ts +18 -0
- package/dist/serve/runtime/worker-replacement.d.ts.map +1 -0
- package/dist/serve/runtime/worker-replacement.js +29 -0
- package/dist/serve/runtime/worker-replacement.js.map +1 -0
- package/dist/serve/standalone-assets.d.ts +2 -2
- package/dist/serve/standalone-assets.d.ts.map +1 -1
- package/dist/serve/standalone-assets.js +1 -1
- package/dist/serve/standalone-assets.js.map +1 -1
- package/dist/serve/studio-ui/assets/{RulesCodeEditor-CxVYcZXw.js → RulesCodeEditor-BDlH-5lp.js} +1 -1
- package/dist/serve/studio-ui/assets/{index-cpSfgQ7H.js → index-Bf9SSE8L.js} +5 -5
- package/dist/serve/studio-ui/assets/{seed-DeuFKi4J.js → seed-D_UjxfOU.js} +1 -1
- package/dist/serve/studio-ui/index.html +1 -1
- package/dist/serve/vite-ai-config.d.ts +25 -0
- package/dist/serve/vite-ai-config.d.ts.map +1 -0
- package/dist/serve/vite-ai-config.js +45 -0
- package/dist/serve/vite-ai-config.js.map +1 -0
- package/dist/serve/vite-plugin.d.ts +17 -36
- package/dist/serve/vite-plugin.d.ts.map +1 -1
- package/dist/serve/vite-plugin.js +38 -57
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-rules-source.d.ts +8 -0
- package/dist/serve/vite-rules-source.d.ts.map +1 -0
- package/dist/serve/vite-rules-source.js +23 -0
- package/dist/serve/vite-rules-source.js.map +1 -0
- package/dist/serve/vite-worker-runtime.d.ts +20 -0
- package/dist/serve/vite-worker-runtime.d.ts.map +1 -0
- package/dist/serve/vite-worker-runtime.js +25 -0
- package/dist/serve/vite-worker-runtime.js.map +1 -0
- package/dist/serve/worker/client/connection.d.ts +7 -2
- package/dist/serve/worker/client/connection.d.ts.map +1 -1
- package/dist/serve/worker/client/connection.js +13 -16
- package/dist/serve/worker/client/connection.js.map +1 -1
- package/dist/serve/worker/client/core.d.ts +7 -0
- package/dist/serve/worker/client/core.d.ts.map +1 -1
- package/dist/serve/worker/client/core.js +28 -0
- package/dist/serve/worker/client/core.js.map +1 -1
- package/dist/serve/worker/client/runtime-control.d.ts +8 -0
- package/dist/serve/worker/client/runtime-control.d.ts.map +1 -0
- package/dist/serve/worker/client/runtime-control.js +11 -0
- package/dist/serve/worker/client/runtime-control.js.map +1 -0
- package/dist/serve/worker/entry.js +44 -2
- package/dist/serve/worker/entry.js.map +1 -1
- package/dist/serve/worker/host/core.js +1 -1
- package/dist/serve/worker/host/core.js.map +1 -1
- package/dist/serve/worker/host/firestore-writes.d.ts.map +1 -1
- package/dist/serve/worker/host/firestore-writes.js +3 -2
- package/dist/serve/worker/host/firestore-writes.js.map +1 -1
- package/dist/serve/worker/host/studio.js +1 -1
- package/dist/serve/worker/host/studio.js.map +1 -1
- package/dist/serve/worker/host-context.d.ts +1 -1
- package/dist/serve/worker/host-context.d.ts.map +1 -1
- package/dist/serve/worker/index.d.ts +2 -1
- package/dist/serve/worker/index.d.ts.map +1 -1
- package/dist/serve/worker/index.js +2 -1
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/protocol.d.ts +15 -1
- package/dist/serve/worker/protocol.d.ts.map +1 -1
- package/dist/serve/worker/protocol.js +2 -2
- package/dist/serve/worker/protocol.js.map +1 -1
- package/dist/serve/worker/retirement.d.ts +21 -0
- package/dist/serve/worker/retirement.d.ts.map +1 -0
- package/dist/serve/worker/retirement.js +97 -0
- package/dist/serve/worker/retirement.js.map +1 -0
- package/dist/serve/worker/serve-init.d.ts.map +1 -1
- package/dist/serve/worker/serve-init.js +5 -6
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/dist/vite.d.ts +1 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js.map +1 -1
- package/package.json +6 -4
- package/src/assurance/.generated/conformance-verdicts.ts +1090 -0
- package/src/assurance/attachment.ts +211 -0
- package/src/assurance/browser.ts +80 -0
- package/src/assurance/campaign.ts +496 -0
- package/src/assurance/capabilities.ts +446 -0
- package/src/assurance/cases.ts +43 -0
- package/src/assurance/index.ts +75 -0
- package/src/assurance/runner.ts +885 -0
- package/src/assurance/tool-names.ts +15 -0
- package/src/assurance/tools.ts +830 -0
- package/src/assurance/types.ts +352 -0
- package/src/assurance/validation.ts +434 -0
- package/src/bridge/client/bridge.ts +550 -0
- package/src/bridge/client/dispatch.ts +137 -0
- package/src/bridge/client.ts +45 -0
- package/src/bridge/protocol.ts +351 -0
- package/src/bridge/server/audit.ts +53 -0
- package/src/bridge/server/bridge.ts +597 -0
- package/src/bridge/server/headless.ts +160 -0
- package/src/bridge/server/json-schema-to-zod.ts +108 -0
- package/src/bridge/server/local-bridge.ts +66 -0
- package/src/bridge/server/logger.ts +50 -0
- package/src/bridge/server/mcp-contract.ts +93 -0
- package/src/bridge/server/mcp.ts +129 -0
- package/src/bridge/server/peer.ts +232 -0
- package/src/bridge/server/standalone.ts +347 -0
- package/src/bridge/server/tool-metadata.ts +99 -0
- package/src/bridge/server.ts +28 -0
- package/src/cli/can-i-use.ts +50 -0
- package/src/cli/cli.test.ts +493 -0
- package/src/cli/database-rules.ts +329 -0
- package/src/cli/dev-runner.ts +282 -0
- package/src/cli/firebase-json.ts +100 -0
- package/src/cli/firestore-indexes.ts +70 -0
- package/src/cli/index.ts +425 -0
- package/src/cli/init.ts +260 -0
- package/src/cli/mcp-proxy.ts +196 -0
- package/src/cli/parse-args.ts +80 -0
- package/src/cli/rules.ts +259 -0
- package/src/cli/scope.ts +67 -0
- package/src/cli/serve.ts +996 -0
- package/src/cli/service-commands.ts +73 -0
- package/src/cli/snapshot.ts +164 -0
- package/src/cli/storage-rules.ts +172 -0
- package/src/cli/verify.ts +416 -0
- package/src/conformance/.generated/can-i-use-browser.ts +113 -0
- package/src/conformance/.generated/can-i-use.ts +117 -0
- package/src/conformance/.generated/conformance-docs.ts +14 -0
- package/src/conformance/browser.ts +24 -0
- package/src/conformance/can-i-use-tool.ts +51 -0
- package/src/conformance/can-i-use.ts +18 -0
- package/src/conformance/docs.ts +8 -0
- package/src/conformance/index.ts +20 -0
- package/src/conformance/tools.ts +16 -0
- package/src/credentials/core/memoize-ttl.ts +142 -0
- package/src/credentials/core/types.ts +10 -0
- package/src/credentials/node/from-adc.ts +96 -0
- package/src/credentials/node/from-service-account.ts +133 -0
- package/src/credentials/node/index.ts +6 -0
- package/src/discover/concurrency.ts +127 -0
- package/src/discover/crawler-adapter.ts +142 -0
- package/src/discover/crawler.ts +1127 -0
- package/src/discover/credential-free.ts +27 -0
- package/src/discover/findCollectionGroup.ts +131 -0
- package/src/discover/firestore-source.ts +59 -0
- package/src/discover/index.ts +5 -0
- package/src/discover/merge.ts +523 -0
- package/src/discover/session.ts +402 -0
- package/src/discover/tools.ts +201 -0
- package/src/discover/types.ts +187 -0
- package/src/discover/wire.ts +324 -0
- package/src/functions-rtdb/child.ts +382 -0
- package/src/functions-rtdb/delivery.ts +7 -0
- package/src/functions-rtdb/discovery.ts +136 -0
- package/src/functions-rtdb/event.ts +64 -0
- package/src/functions-rtdb/execution.ts +111 -0
- package/src/functions-rtdb/in-memory-delivery.ts +40 -0
- package/src/functions-rtdb/project.ts +74 -0
- package/src/functions-rtdb/projection.ts +104 -0
- package/src/functions-rtdb/reference-pattern.ts +20 -0
- package/src/functions-rtdb/remote-delivery.ts +23 -0
- package/src/pkg-version.ts +49 -0
- package/src/register/esm-exports.ts +63 -0
- package/src/register/hooks.ts +30 -0
- package/src/register/index.ts +150 -0
- package/src/register/mapping.ts +33 -0
- package/src/remote/index.ts +1050 -0
- package/src/rtdb/crawl-snapshot.ts +118 -0
- package/src/rtdb/inspection.ts +137 -0
- package/src/rtdb/load-rules-document.ts +56 -0
- package/src/rtdb/rules-generation-tool.ts +38 -0
- package/src/rtdb/rules-json.ts +29 -0
- package/src/serve/activity-guard.ts +29 -0
- package/src/serve/activity-route.ts +164 -0
- package/src/serve/activity-warning.ts +26 -0
- package/src/serve/bridge-mount.ts +200 -0
- package/src/serve/bundler.ts +519 -0
- package/src/serve/capture-store.ts +65 -0
- package/src/serve/discovery.ts +199 -0
- package/src/serve/entries/ai.ts +292 -0
- package/src/serve/entries/app-backend.ts +4 -0
- package/src/serve/entries/app-client.ts +26 -0
- package/src/serve/entries/app-session-store.ts +47 -0
- package/src/serve/entries/app.ts +11 -0
- package/src/serve/entries/auth-helper-core.ts +181 -0
- package/src/serve/entries/auth-helper-dom.ts +134 -0
- package/src/serve/entries/auth-helper-runtime.ts +20 -0
- package/src/serve/entries/auth.ts +255 -0
- package/src/serve/entries/bridge-url.ts +31 -0
- package/src/serve/entries/database.ts +129 -0
- package/src/serve/entries/firestore.ts +232 -0
- package/src/serve/entries/init.ts +49 -0
- package/src/serve/entries/keepalive.ts +46 -0
- package/src/serve/entries/messaging-sw.ts +75 -0
- package/src/serve/entries/messaging.ts +96 -0
- package/src/serve/entries/runtime.ts +556 -0
- package/src/serve/entries/session-store.ts +97 -0
- package/src/serve/entries/storage.ts +92 -0
- package/src/serve/entries/tab-sync-wiring.ts +274 -0
- package/src/serve/entries/worker-runtime.ts +135 -0
- package/src/serve/init-payload.ts +42 -0
- package/src/serve/namespace.ts +675 -0
- package/src/serve/open-browser.ts +68 -0
- package/src/serve/rules.ts +272 -0
- package/src/serve/runtime/chip-config.ts +30 -0
- package/src/serve/runtime/chip-install.ts +27 -0
- package/src/serve/runtime/chip.ts +282 -0
- package/src/serve/runtime/manifest.ts +37 -0
- package/src/serve/runtime/status.ts +216 -0
- package/src/serve/runtime/worker-connection.ts +14 -0
- package/src/serve/runtime/worker-generation.ts +75 -0
- package/src/serve/runtime/worker-replacement.ts +42 -0
- package/src/serve/sandbox-marker.ts +31 -0
- package/src/serve/server.ts +428 -0
- package/src/serve/standalone-assets.ts +180 -0
- package/src/serve/state-store.ts +166 -0
- package/src/serve/studio/disk-project-store.ts +185 -0
- package/src/serve/studio/disk-workspace.ts +162 -0
- package/src/serve/studio/index.ts +20 -0
- package/src/serve/studio/routes.ts +237 -0
- package/src/serve/studio/store-types.ts +48 -0
- package/src/serve/studio/studio-storage.test.ts +289 -0
- package/src/serve/vite-ai-config.ts +77 -0
- package/src/serve/vite-plugin.ts +1075 -0
- package/src/serve/vite-rules-source.ts +28 -0
- package/src/serve/vite-worker-runtime.ts +51 -0
- package/src/serve/worker/activity-bootstrap.ts +24 -0
- package/src/serve/worker/client/admin-firestore.ts +38 -0
- package/src/serve/worker/client/ai.ts +124 -0
- package/src/serve/worker/client/auth.ts +489 -0
- package/src/serve/worker/client/connection.ts +227 -0
- package/src/serve/worker/client/core.ts +384 -0
- package/src/serve/worker/client/disconnect.ts +45 -0
- package/src/serve/worker/client/firestore-reads.ts +181 -0
- package/src/serve/worker/client/firestore-refs.ts +226 -0
- package/src/serve/worker/client/firestore-writes.ts +232 -0
- package/src/serve/worker/client/handles.ts +91 -0
- package/src/serve/worker/client/messaging.ts +119 -0
- package/src/serve/worker/client/presence.ts +174 -0
- package/src/serve/worker/client/rtdb.ts +311 -0
- package/src/serve/worker/client/rules.ts +63 -0
- package/src/serve/worker/client/runtime-control.ts +22 -0
- package/src/serve/worker/client/service-worker-connection.ts +59 -0
- package/src/serve/worker/client/snapshots.ts +86 -0
- package/src/serve/worker/client/storage.ts +195 -0
- package/src/serve/worker/client/studio.ts +88 -0
- package/src/serve/worker/client.ts +57 -0
- package/src/serve/worker/durable-persistence.ts +137 -0
- package/src/serve/worker/entry.ts +223 -0
- package/src/serve/worker/host/admin-firestore.ts +88 -0
- package/src/serve/worker/host/connection.ts +179 -0
- package/src/serve/worker/host/core.ts +387 -0
- package/src/serve/worker/host/dispatch.ts +316 -0
- package/src/serve/worker/host/firestore-reads.ts +117 -0
- package/src/serve/worker/host/firestore-writes.ts +456 -0
- package/src/serve/worker/host/presence.ts +312 -0
- package/src/serve/worker/host/rtdb.ts +136 -0
- package/src/serve/worker/host/rules.ts +128 -0
- package/src/serve/worker/host/storage.ts +312 -0
- package/src/serve/worker/host/studio.ts +75 -0
- package/src/serve/worker/host/subscriptions.ts +238 -0
- package/src/serve/worker/host-ai.ts +165 -0
- package/src/serve/worker/host-auth.ts +469 -0
- package/src/serve/worker/host-context.ts +273 -0
- package/src/serve/worker/host-events.ts +94 -0
- package/src/serve/worker/host-messaging.ts +240 -0
- package/src/serve/worker/host.ts +47 -0
- package/src/serve/worker/index.ts +196 -0
- package/src/serve/worker/presence-timing.ts +15 -0
- package/src/serve/worker/protocol.ts +1124 -0
- package/src/serve/worker/retirement.ts +125 -0
- package/src/serve/worker/serve-init.ts +605 -0
- package/src/serve/worker/service-worker-channel.ts +33 -0
- package/src/serve/worker/service-worker-relay.ts +86 -0
- package/src/serve/writer-lock.ts +53 -0
- package/src/verify/cases.ts +233 -0
- package/src/verify/fixture.ts +258 -0
- package/src/verify/index.ts +519 -0
- package/src/verify/tools.ts +108 -0
- package/src/version/compat-target.ts +17 -0
- package/src/vite.ts +18 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api/index.html +0 -31
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api.md +0 -29
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SharedWorker host — the message dispatcher + port cleanup.
|
|
3
|
+
*
|
|
4
|
+
* The top of the host: `handleMessage` opens the op's ambient-provenance
|
|
5
|
+
* window and hands to `dispatchMessage`, which peels off the auth / AI /
|
|
6
|
+
* messaging / event families (their sibling `host-*.ts` modules), then routes
|
|
7
|
+
* ops to `handleOp` (the firestore/rules/admin/rtdb/storage/connection/studio
|
|
8
|
+
* orchestrator) and subs to the subscription registry. `cleanupPort` tears a
|
|
9
|
+
* disconnected port's per-subsystem state down.
|
|
10
|
+
*
|
|
11
|
+
* `handleOp` resolves the op's Firestore handle ONCE (the `db`/`lens`
|
|
12
|
+
* preamble) — the eager lens/session resolution every op sees — then dispatches
|
|
13
|
+
* to the per-family `handle*Op` handlers. This is the single unit-testable seam:
|
|
14
|
+
* tests build a real `HostCtx` over an in-memory sandbox and call
|
|
15
|
+
* `handleMessage` directly with fake ports.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { InboundMessage, OpMessage, ToolMessage } from '../protocol.js';
|
|
19
|
+
import {
|
|
20
|
+
isAuthSub,
|
|
21
|
+
isEventSub,
|
|
22
|
+
isRtdbSub,
|
|
23
|
+
isAiSub,
|
|
24
|
+
isMessagingSub,
|
|
25
|
+
isPresenceSub,
|
|
26
|
+
} from '../protocol.js';
|
|
27
|
+
// The canonical agent tool dispatcher — reused on the worker so a bridged agent
|
|
28
|
+
// executes against THIS sandbox (one backend for app + Studio + agent), instead
|
|
29
|
+
// of a separate in-page sandbox.
|
|
30
|
+
import { buildSandboxDispatcher } from '../../../bridge/client/dispatch.js';
|
|
31
|
+
import { firebaseOptionsEqual } from 'pyric/app/internal';
|
|
32
|
+
|
|
33
|
+
import { activityJourneyId, type HostCtx, type PortLike, ok, fail } from '../host-context.js';
|
|
34
|
+
import {
|
|
35
|
+
authSubsFor,
|
|
36
|
+
isAuthOp,
|
|
37
|
+
handleAuthOp,
|
|
38
|
+
handleAuthSub,
|
|
39
|
+
handleAuthUnsub,
|
|
40
|
+
cleanupPortSession,
|
|
41
|
+
} from '../host-auth.js';
|
|
42
|
+
import {
|
|
43
|
+
eventSubsFor,
|
|
44
|
+
handleEventSub,
|
|
45
|
+
handleEventUnsub,
|
|
46
|
+
} from '../host-events.js';
|
|
47
|
+
import { isAiOp, handleAiOp, handleAiSub } from '../host-ai.js';
|
|
48
|
+
import {
|
|
49
|
+
isMessagingOp,
|
|
50
|
+
handleMessagingOp,
|
|
51
|
+
handleMessagingSub,
|
|
52
|
+
cleanupPortMessaging,
|
|
53
|
+
} from '../host-messaging.js';
|
|
54
|
+
import {
|
|
55
|
+
lensDb,
|
|
56
|
+
lensProvenance,
|
|
57
|
+
sessionDb,
|
|
58
|
+
opProvenance,
|
|
59
|
+
} from './core.js';
|
|
60
|
+
import { isFirestoreReadOp, handleFirestoreReadOp } from './firestore-reads.js';
|
|
61
|
+
import { isFirestoreWriteOp, handleFirestoreWriteOp } from './firestore-writes.js';
|
|
62
|
+
import { isRulesOp, handleRulesOp } from './rules.js';
|
|
63
|
+
import { isAdminFirestoreOp, handleAdminFirestoreOp } from './admin-firestore.js';
|
|
64
|
+
import { isRtdbOp, handleRtdbOp } from './rtdb.js';
|
|
65
|
+
import { isStorageOp, handleStorageOp } from './storage.js';
|
|
66
|
+
import { isConnectionOp, handleConnectionOp } from './connection.js';
|
|
67
|
+
import { isStudioOp, handleStudioOp } from './studio.js';
|
|
68
|
+
import {
|
|
69
|
+
isPresenceOp,
|
|
70
|
+
handlePresenceOp,
|
|
71
|
+
handlePresenceSub,
|
|
72
|
+
handlePresenceUnsub,
|
|
73
|
+
cleanupPortPresence,
|
|
74
|
+
} from './presence.js';
|
|
75
|
+
import { handleSub, handleRtdbSub, handleUnsub, dropPortSessionSubs } from './subscriptions.js';
|
|
76
|
+
|
|
77
|
+
function configConflictError(): Error & { code: string } {
|
|
78
|
+
return Object.assign(
|
|
79
|
+
new Error('Pyric currently supports one Firebase configuration per runtime'),
|
|
80
|
+
{ code: 'app/multiple-configs-not-supported' },
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ─── Op orchestrator ────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
async function handleOp(ctx: HostCtx, port: PortLike, msg: OpMessage): Promise<void> {
|
|
87
|
+
// Explicit lens (Studio admin / as / app-session) → lensDb; no lens → the
|
|
88
|
+
// PORT'S SESSION (#754), so app ops run as whoever this tab signed in as.
|
|
89
|
+
const db = msg.actAs ? lensDb(ctx, msg.actAs) : sessionDb(ctx, port);
|
|
90
|
+
// Provenance the op runs under. Stamped onto the unified event stream's
|
|
91
|
+
// `authLens` by the emit path (C1 field / T1 emit). For `{ mode: 'as', uid }`
|
|
92
|
+
// the resolved `db` already carries `auth: { uid }`, so a rules eval emits
|
|
93
|
+
// under that identity; `lens` is the canonical normalised value the host
|
|
94
|
+
// hands forward when the explicit emit-time stamp seam exists (see lensProvenance).
|
|
95
|
+
const lens = lensProvenance(msg.actAs);
|
|
96
|
+
void lens;
|
|
97
|
+
|
|
98
|
+
// Firestore reads/writes run against the resolved `db` (lens/session)
|
|
99
|
+
// computed above; peeled off to their family modules.
|
|
100
|
+
if (isFirestoreReadOp(msg.method)) return handleFirestoreReadOp(ctx, port, msg, db);
|
|
101
|
+
if (isFirestoreWriteOp(msg.method)) return handleFirestoreWriteOp(ctx, port, msg, db);
|
|
102
|
+
if (isRulesOp(msg.method)) return handleRulesOp(ctx, port, msg, db);
|
|
103
|
+
if (isAdminFirestoreOp(msg.method)) return handleAdminFirestoreOp(ctx, port, msg);
|
|
104
|
+
if (isRtdbOp(msg.method)) return handleRtdbOp(ctx, port, msg);
|
|
105
|
+
if (isStorageOp(msg.method)) return handleStorageOp(ctx, port, msg);
|
|
106
|
+
if (isConnectionOp(msg.method)) return handleConnectionOp(ctx, port, msg);
|
|
107
|
+
if (isStudioOp(msg.method)) return handleStudioOp(ctx, port, msg);
|
|
108
|
+
if (isPresenceOp(msg.method)) return handlePresenceOp(ctx, port, msg);
|
|
109
|
+
|
|
110
|
+
// Auth (`auth.*`), AI (`ai.*`), and messaging (`messaging.*`) ops are routed
|
|
111
|
+
// to their handlers by dispatchMessage BEFORE reaching handleOp, so any
|
|
112
|
+
// method landing here is genuinely unknown.
|
|
113
|
+
fail(port, msg.id, new Error(`Unknown method: ${String((msg as { method: unknown }).method)}`));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─── Main dispatch ────────────────────────────────────────────────────────
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Agent tool-call dispatch. The bridge peer forwards `tool` messages so the
|
|
120
|
+
* agent runs the canonical sandbox tool set against THIS worker's sandbox (the
|
|
121
|
+
* same instance the app + Studio use) instead of a separate in-page backend.
|
|
122
|
+
* Replies with a `res` whose value is the `{ ok, summary, data }` result.
|
|
123
|
+
*/
|
|
124
|
+
async function handleTool(ctx: HostCtx, port: PortLike, msg: ToolMessage): Promise<void> {
|
|
125
|
+
try {
|
|
126
|
+
ctx.toolDispatch ??= buildSandboxDispatcher(ctx.sandbox);
|
|
127
|
+
const result = await ctx.toolDispatch(msg.name, msg.args ?? {});
|
|
128
|
+
// Pre-serialize via JSON BEFORE the structured-clone hop over the port. Read
|
|
129
|
+
// results carry real firebase wrapper instances (Timestamp/GeoPoint/Bytes/
|
|
130
|
+
// VectorValue) whose toJSON() produces the canonical agent-facing shapes.
|
|
131
|
+
// structuredClone would strip those prototypes (losing toJSON) and post
|
|
132
|
+
// mangled internals, and would throw DataCloneError on any non-cloneable
|
|
133
|
+
// field. JSON.stringify here runs toJSON() while the instances are intact and
|
|
134
|
+
// yields a plain, clone-safe object — matching the in-page path, which
|
|
135
|
+
// JSON-stringified at the bridge. A serialization error lands in the catch
|
|
136
|
+
// below, never in postMessage.
|
|
137
|
+
ok(port, msg.id, JSON.parse(JSON.stringify(result)));
|
|
138
|
+
} catch (e) {
|
|
139
|
+
fail(port, msg.id, e);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Handle one inbound message from a port.
|
|
145
|
+
*
|
|
146
|
+
* This is the primary unit-testable seam. Tests create a real `HostCtx`
|
|
147
|
+
* backed by an in-memory pyric sandbox and call this function directly
|
|
148
|
+
* with fake port objects, exercising the full op+subscription lifecycle
|
|
149
|
+
* without a real SharedWorker.
|
|
150
|
+
*/
|
|
151
|
+
export async function handleMessage(
|
|
152
|
+
ctx: HostCtx,
|
|
153
|
+
port: PortLike,
|
|
154
|
+
msg: InboundMessage,
|
|
155
|
+
): Promise<void> {
|
|
156
|
+
if (msg.t === 'appConfig') {
|
|
157
|
+
if (ctx.appOptions === undefined) {
|
|
158
|
+
ctx.appOptions = structuredClone(msg.options);
|
|
159
|
+
} else if (!firebaseOptionsEqual(ctx.appOptions, msg.options)) {
|
|
160
|
+
(ctx.rejectedConfigPorts ??= new WeakSet()).add(port);
|
|
161
|
+
}
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
// A rejected app port still owns host-side resources until its explicit
|
|
165
|
+
// disconnect handshake completes. Never swallow that teardown frame.
|
|
166
|
+
if (ctx.rejectedConfigPorts?.has(port) && msg.t !== 'disconnect') {
|
|
167
|
+
if (msg.t === 'op' || msg.t === 'tool') {
|
|
168
|
+
fail(port, msg.id, configConflictError());
|
|
169
|
+
} else if (msg.t === 'sub' && msg.target !== 'events') {
|
|
170
|
+
const error = configConflictError();
|
|
171
|
+
port.postMessage({
|
|
172
|
+
t: 'snap',
|
|
173
|
+
subId: msg.subId,
|
|
174
|
+
value: { __error: { code: error.code, message: error.message } },
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (ctx.disconnectedPorts?.has(port) && msg.t !== 'disconnect') {
|
|
180
|
+
if (msg.t === 'op' || msg.t === 'tool') {
|
|
181
|
+
fail(
|
|
182
|
+
port,
|
|
183
|
+
msg.id,
|
|
184
|
+
Object.assign(new Error('Firebase App was deleted'), { code: 'app/app-deleted' }),
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
// Op provenance, bound at dispatch by `opProvenance` (see its docs). Opened
|
|
190
|
+
// as the sandbox's SYNCHRONOUS ambient window so firestore/rtdb/auth emits —
|
|
191
|
+
// which run inside `dispatchMessage` before any await — pick it up. Storage
|
|
192
|
+
// ops emit AFTER async awaits, outside this window, so they thread the same
|
|
193
|
+
// provenance EXPLICITLY instead (see `handleOp`'s storage cases). Without the
|
|
194
|
+
// lens on admin ops, `verdictFor` mislabeled a rules BYPASS as ALLOW (the
|
|
195
|
+
// RTDB/Firestore asymmetry the traffic-metrics work flagged).
|
|
196
|
+
const isRemoteRelay = (msg as { relaySource?: 'remote' }).relaySource === 'remote';
|
|
197
|
+
const tracksFirestoreActivity = !isRemoteRelay && (msg.t === 'op'
|
|
198
|
+
? isFirestoreReadOp(msg.method)
|
|
199
|
+
: msg.t === 'sub'
|
|
200
|
+
&& msg.target !== null
|
|
201
|
+
&& typeof msg.target === 'object'
|
|
202
|
+
&& '__ref' in msg.target);
|
|
203
|
+
const prov = opProvenance(
|
|
204
|
+
msg,
|
|
205
|
+
tracksFirestoreActivity ? activityJourneyId(ctx, port) : undefined,
|
|
206
|
+
);
|
|
207
|
+
if (prov && ctx.sandbox.runWithProvenance) {
|
|
208
|
+
return ctx.sandbox.runWithProvenance(prov, () => dispatchMessage(ctx, port, msg));
|
|
209
|
+
}
|
|
210
|
+
return dispatchMessage(ctx, port, msg);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function dispatchMessage(
|
|
214
|
+
ctx: HostCtx,
|
|
215
|
+
port: PortLike,
|
|
216
|
+
msg: InboundMessage,
|
|
217
|
+
): Promise<void> {
|
|
218
|
+
if (msg.t === 'op') {
|
|
219
|
+
if (isAuthOp(msg.method)) {
|
|
220
|
+
await handleAuthOp(ctx, port, msg);
|
|
221
|
+
} else if (isAiOp(msg.method)) {
|
|
222
|
+
await handleAiOp(ctx, port, msg);
|
|
223
|
+
} else if (isMessagingOp(msg.method)) {
|
|
224
|
+
await handleMessagingOp(ctx, port, msg);
|
|
225
|
+
} else {
|
|
226
|
+
await handleOp(ctx, port, msg);
|
|
227
|
+
}
|
|
228
|
+
} else if (msg.t === 'sub') {
|
|
229
|
+
if (isAuthSub(msg)) {
|
|
230
|
+
handleAuthSub(ctx, port, msg);
|
|
231
|
+
} else if (isEventSub(msg)) {
|
|
232
|
+
handleEventSub(ctx, port, msg);
|
|
233
|
+
} else if (isRtdbSub(msg)) {
|
|
234
|
+
handleRtdbSub(ctx, port, msg);
|
|
235
|
+
} else if (isAiSub(msg)) {
|
|
236
|
+
// AI streams are FINITE subs registered in ctx.subs (so `unsub` cancels
|
|
237
|
+
// them); they auto-unsub on the terminal done/error snap. host-ai.ts.
|
|
238
|
+
handleAiSub(ctx, port, msg);
|
|
239
|
+
} else if (isMessagingSub(msg)) {
|
|
240
|
+
handleMessagingSub(ctx, port, msg);
|
|
241
|
+
} else if (isPresenceSub(msg)) {
|
|
242
|
+
handlePresenceSub(ctx, port, msg);
|
|
243
|
+
} else {
|
|
244
|
+
handleSub(ctx, port, msg);
|
|
245
|
+
}
|
|
246
|
+
} else if (msg.t === 'unsub') {
|
|
247
|
+
// An unsub may target an auth sub, an event-stream sub, a presence sub, or
|
|
248
|
+
// a Firestore listener — try the cheap routing registries first, then fall
|
|
249
|
+
// through to the Firestore listener teardown.
|
|
250
|
+
if (
|
|
251
|
+
!handleAuthUnsub(ctx, port, msg.subId) &&
|
|
252
|
+
!handleEventUnsub(ctx, port, msg.subId) &&
|
|
253
|
+
!handlePresenceUnsub(ctx, port, msg.subId)
|
|
254
|
+
) {
|
|
255
|
+
handleUnsub(ctx, port, msg);
|
|
256
|
+
}
|
|
257
|
+
} else if (msg.t === 'disconnect') {
|
|
258
|
+
try {
|
|
259
|
+
cleanupPort(ctx, port);
|
|
260
|
+
ok(port, msg.id, undefined);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
fail(port, msg.id, error);
|
|
263
|
+
}
|
|
264
|
+
} else if (msg.t === 'tool') {
|
|
265
|
+
await handleTool(ctx, port, msg);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ─── Port cleanup ─────────────────────────────────────────────────────────
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Tear down all subscriptions for a disconnected port.
|
|
273
|
+
* Called when a port's `close` event fires (browser best-effort) or
|
|
274
|
+
* when the entry point explicitly cleans up a port.
|
|
275
|
+
*/
|
|
276
|
+
export function cleanupPort(ctx: HostCtx, port: PortLike): void {
|
|
277
|
+
(ctx.disconnectedPorts ??= new WeakSet()).add(port);
|
|
278
|
+
const failures: unknown[] = [];
|
|
279
|
+
const attempt = (cleanup: () => void): void => {
|
|
280
|
+
try {
|
|
281
|
+
cleanup();
|
|
282
|
+
} catch (error) {
|
|
283
|
+
failures.push(error);
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
// Drop the port's auth subscriptions (routing entries — no real listener
|
|
287
|
+
// to tear down), its per-port session, and its session-bound sub records
|
|
288
|
+
// (#754).
|
|
289
|
+
attempt(() => { authSubsFor(ctx).delete(port); });
|
|
290
|
+
attempt(() => { cleanupPortSession(ctx, port); });
|
|
291
|
+
attempt(() => { dropPortSessionSubs(ctx, port); });
|
|
292
|
+
|
|
293
|
+
// Drop the port's event-stream subscriptions too (also routing entries off
|
|
294
|
+
// the single shared `sandbox.onEvent` subscription — nothing to unsubscribe,
|
|
295
|
+
// just stop fanning out to a dead port).
|
|
296
|
+
attempt(() => { eventSubsFor(ctx).delete(port); });
|
|
297
|
+
|
|
298
|
+
// Drop the port's messaging broker client so a closed tab's last-reported
|
|
299
|
+
// visibility stops feeding the routing rule. Its delivery-handler unsubs
|
|
300
|
+
// live in `ctx.subs` and are torn down with the loop below.
|
|
301
|
+
attempt(() => { cleanupPortMessaging(ctx, port); });
|
|
302
|
+
|
|
303
|
+
// Presence: best-effort remove this port's logical client when it was the
|
|
304
|
+
// last association (lease expiry remains the correctness path).
|
|
305
|
+
attempt(() => { cleanupPortPresence(ctx, port); });
|
|
306
|
+
|
|
307
|
+
const portSubs = ctx.subs.get(port);
|
|
308
|
+
if (portSubs) {
|
|
309
|
+
for (const unsub of portSubs.values()) attempt(unsub);
|
|
310
|
+
ctx.subs.delete(port);
|
|
311
|
+
}
|
|
312
|
+
if (failures.length === 1) throw failures[0];
|
|
313
|
+
if (failures.length > 1) {
|
|
314
|
+
throw new AggregateError(failures, 'Multiple SharedWorker port resources failed to tear down');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SharedWorker host — Firestore read + aggregate + keyspace ops.
|
|
3
|
+
*
|
|
4
|
+
* The rule-gated read surface: `getDoc`/`getDocs`, the `count`/`aggregate`
|
|
5
|
+
* server aggregations, and the lens-independent keyspace enumeration
|
|
6
|
+
* (`listRootCollections`/`listSubcollections`, the Pyric Studio data browse).
|
|
7
|
+
*
|
|
8
|
+
* Routed here by the host dispatcher (host/dispatch.ts) with the op's resolved
|
|
9
|
+
* Firestore handle (`db` — already lens/session-resolved). This module never
|
|
10
|
+
* imports the dispatcher; it leans only on host-context + host/core.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
doc as pyricDoc,
|
|
15
|
+
getDoc,
|
|
16
|
+
getDocs,
|
|
17
|
+
getCountFromServer,
|
|
18
|
+
getAggregateFromServer,
|
|
19
|
+
type AggregateSpec,
|
|
20
|
+
type Firestore,
|
|
21
|
+
type Query,
|
|
22
|
+
} from 'pyric/firestore';
|
|
23
|
+
import { getInternalEnv } from 'pyric/sandbox/internal';
|
|
24
|
+
|
|
25
|
+
import type { OpMessage } from '../protocol.js';
|
|
26
|
+
import { type HostCtx, type PortLike, ok, fail } from '../host-context.js';
|
|
27
|
+
import { resolveTarget, serializeDocSnap } from './core.js';
|
|
28
|
+
|
|
29
|
+
/** The read/aggregate/keyspace op methods routed to {@link handleFirestoreReadOp}. */
|
|
30
|
+
const READ_METHODS = new Set<string>([
|
|
31
|
+
'getDoc',
|
|
32
|
+
'getDocs',
|
|
33
|
+
'count',
|
|
34
|
+
'aggregate',
|
|
35
|
+
'listRootCollections',
|
|
36
|
+
'listSubcollections',
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
export function isFirestoreReadOp(method: OpMessage['method']): boolean {
|
|
40
|
+
return READ_METHODS.has(method);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function handleFirestoreReadOp(
|
|
44
|
+
ctx: HostCtx,
|
|
45
|
+
port: PortLike,
|
|
46
|
+
msg: OpMessage,
|
|
47
|
+
db: Firestore,
|
|
48
|
+
): Promise<void> {
|
|
49
|
+
const { sandbox } = ctx;
|
|
50
|
+
switch (msg.method) {
|
|
51
|
+
case 'getDoc': {
|
|
52
|
+
try {
|
|
53
|
+
const ref = pyricDoc(db, msg.path);
|
|
54
|
+
const snap = await getDoc(ref);
|
|
55
|
+
ok(port, msg.id, serializeDocSnap(snap as Parameters<typeof serializeDocSnap>[0]));
|
|
56
|
+
} catch (e) { fail(port, msg.id, e); }
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
case 'getDocs': {
|
|
61
|
+
try {
|
|
62
|
+
const source = resolveTarget(db, msg.source);
|
|
63
|
+
// CollectionReference is always also queryable — getDocs accepts Query<T>
|
|
64
|
+
// and CollectionReference is structurally compatible at runtime even though
|
|
65
|
+
// the type system doesn't know that (CollectionReference has no `_isQuery`
|
|
66
|
+
// brand). Cast through Query to satisfy the type checker.
|
|
67
|
+
const snap = await getDocs(source as Query);
|
|
68
|
+
const docs = snap.docs.map((d) =>
|
|
69
|
+
serializeDocSnap(d as Parameters<typeof serializeDocSnap>[0]),
|
|
70
|
+
);
|
|
71
|
+
ok(port, msg.id, { docs });
|
|
72
|
+
} catch (e) { fail(port, msg.id, e); }
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
case 'count': {
|
|
77
|
+
try {
|
|
78
|
+
const source = resolveTarget(db, msg.source);
|
|
79
|
+
const snap = await getCountFromServer(source as Query);
|
|
80
|
+
ok(port, msg.id, { count: snap.data().count });
|
|
81
|
+
} catch (e) { fail(port, msg.id, e); }
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
case 'aggregate': {
|
|
86
|
+
// Multi-field aggregates (count/sum/average). The wire spec is
|
|
87
|
+
// structurally pyric/firestore's AggregateSpec, so it passes straight
|
|
88
|
+
// through; the reply data is plain numbers / null (empty-input average).
|
|
89
|
+
try {
|
|
90
|
+
const source = resolveTarget(db, msg.source);
|
|
91
|
+
const snap = await getAggregateFromServer(source as Query, msg.spec as AggregateSpec);
|
|
92
|
+
ok(port, msg.id, { data: snap.data() });
|
|
93
|
+
} catch (e) { fail(port, msg.id, e); }
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
case 'listRootCollections': {
|
|
98
|
+
// Keyspace enumeration (Pyric Studio data browse). Lens-independent: it
|
|
99
|
+
// lists the collection ids present, not rule-gated reads.
|
|
100
|
+
try {
|
|
101
|
+
ok(port, msg.id, { ids: getInternalEnv(sandbox).listRootCollections() });
|
|
102
|
+
} catch (e) { fail(port, msg.id, e); }
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
case 'listSubcollections': {
|
|
107
|
+
try {
|
|
108
|
+
ok(port, msg.id, { ids: getInternalEnv(sandbox).listSubcollections(msg.docPath) });
|
|
109
|
+
} catch (e) { fail(port, msg.id, e); }
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
default: {
|
|
114
|
+
fail(port, msg.id, new Error(`Unknown method: ${String((msg as { method: unknown }).method)}`));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|