@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,489 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker-client Auth surface — mirrors `pyric/auth` / `firebase/auth` over the
|
|
3
|
+
* port. Per-port sessions (#754): each port owns its own session; the client
|
|
4
|
+
* keeps a local `currentUser` mirror updated from the authState stream while the
|
|
5
|
+
* worker owns the real `User` and token minting.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
InboundMessage,
|
|
10
|
+
SerializedUser,
|
|
11
|
+
SerializedUserCredential,
|
|
12
|
+
SerializedIdTokenResult,
|
|
13
|
+
AuthPersistenceMode,
|
|
14
|
+
ResolvedIdentity,
|
|
15
|
+
} from '../protocol.js';
|
|
16
|
+
import type { AuthUserRecord, CreateUserRequest, UpdateUserRequest } from 'pyric/auth';
|
|
17
|
+
import { closeSubscription, isDisconnectedPort, nextId, nextSubId, openSnapshotSubscription, rpc, wirePort } from './core.js';
|
|
18
|
+
import type { ClientDb, ClientPort, Unsubscribe } from './handles.js';
|
|
19
|
+
|
|
20
|
+
// ════════════════════════════════════════════════════════════════════════
|
|
21
|
+
// AUTH SURFACE (mirrors `pyric/auth` / `firebase/auth`)
|
|
22
|
+
// ════════════════════════════════════════════════════════════════════════
|
|
23
|
+
//
|
|
24
|
+
// PER-PORT SESSIONS (#754)
|
|
25
|
+
// ------------------------
|
|
26
|
+
// The worker hosts ONE sandbox (one user pool, one data store, one ruleset)
|
|
27
|
+
// but each port (tab / client) owns its OWN session: sign-ins bind to THIS
|
|
28
|
+
// port, `onAuthStateChanged` fires for THIS port's transitions only, and
|
|
29
|
+
// data ops from this port evaluate rules under its session. Two tabs can be
|
|
30
|
+
// two different users on the same live backend — the multi-user testing
|
|
31
|
+
// surface a single-identity sandbox can't provide. Session persistence
|
|
32
|
+
// across reloads is client-side (SessionStore + `restorePortSession`).
|
|
33
|
+
//
|
|
34
|
+
// CLIENT-SIDE currentUser MIRROR
|
|
35
|
+
// ------------------------------
|
|
36
|
+
// The worker holds the one real `User`. The client keeps a local
|
|
37
|
+
// `ClientUser` mirror updated from the authState stream, so `auth.currentUser`
|
|
38
|
+
// is synchronously readable (matching firebase/auth). Token accessors RPC to
|
|
39
|
+
// the worker (the worker owns token minting).
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Client-side User — a snapshot of the worker's `User` with token accessors
|
|
43
|
+
* that RPC back to the worker. Mirrors `firebase/auth`'s `User` shape.
|
|
44
|
+
*/
|
|
45
|
+
export interface ClientUser {
|
|
46
|
+
readonly uid: string;
|
|
47
|
+
readonly email: string | null;
|
|
48
|
+
readonly emailVerified: boolean;
|
|
49
|
+
readonly displayName: string | null;
|
|
50
|
+
readonly photoURL: string | null;
|
|
51
|
+
readonly phoneNumber: string | null;
|
|
52
|
+
readonly isAnonymous: boolean;
|
|
53
|
+
readonly providerId: string | null;
|
|
54
|
+
readonly providerData: SerializedUser['providerData'];
|
|
55
|
+
getIdToken(forceRefresh?: boolean): Promise<string>;
|
|
56
|
+
getIdTokenResult(forceRefresh?: boolean): Promise<SerializedIdTokenResult>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Client-side UserCredential — mirrors `firebase/auth`. */
|
|
60
|
+
export interface ClientUserCredential {
|
|
61
|
+
user: ClientUser;
|
|
62
|
+
providerId: string | null;
|
|
63
|
+
operationType: 'signIn' | 'reauthenticate' | 'link';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Client-side Auth handle. Holds the port + a local `currentUser` mirror.
|
|
68
|
+
* Returned by `getAuth(db | workerUrl)`. Mirrors `firebase/auth`'s `Auth`.
|
|
69
|
+
*/
|
|
70
|
+
export interface ClientAuth {
|
|
71
|
+
readonly __kind: 'client-auth';
|
|
72
|
+
readonly port: ClientPort;
|
|
73
|
+
/** Local mirror of the worker's currentUser, updated from the stream. */
|
|
74
|
+
currentUser: ClientUser | null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Hidden per-`ClientUser` port handle so the top-level `updateProfile(user, …)`
|
|
78
|
+
* free function can RPC without an `auth` handle in scope (mirrors
|
|
79
|
+
* `firebase/auth`'s user-only signature). Non-enumerable — never serialized. */
|
|
80
|
+
const CLIENT_USER_PORT: unique symbol = Symbol('pyric.clientUser.port');
|
|
81
|
+
|
|
82
|
+
/** Build a token-capable ClientUser from a wire SerializedUser. */
|
|
83
|
+
function makeClientUser(port: ClientPort, raw: SerializedUser): ClientUser {
|
|
84
|
+
const user: ClientUser = {
|
|
85
|
+
uid: raw.uid,
|
|
86
|
+
email: raw.email,
|
|
87
|
+
emailVerified: raw.emailVerified,
|
|
88
|
+
displayName: raw.displayName,
|
|
89
|
+
photoURL: raw.photoURL,
|
|
90
|
+
phoneNumber: raw.phoneNumber,
|
|
91
|
+
isAnonymous: raw.isAnonymous,
|
|
92
|
+
providerId: raw.providerId,
|
|
93
|
+
providerData: raw.providerData,
|
|
94
|
+
async getIdToken(forceRefresh?: boolean) {
|
|
95
|
+
return (await rpc(port, {
|
|
96
|
+
t: 'op', id: nextId(), method: 'auth.getIdToken', forceRefresh,
|
|
97
|
+
})) as string;
|
|
98
|
+
},
|
|
99
|
+
async getIdTokenResult(forceRefresh?: boolean) {
|
|
100
|
+
return (await rpc(port, {
|
|
101
|
+
t: 'op', id: nextId(), method: 'auth.getIdTokenResult', forceRefresh,
|
|
102
|
+
})) as SerializedIdTokenResult;
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
Object.defineProperty(user, CLIENT_USER_PORT, { value: port, enumerable: false });
|
|
106
|
+
return user;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Convert a wire SerializedUser|null to a ClientUser|null. */
|
|
110
|
+
function toClientUser(port: ClientPort, raw: SerializedUser | null): ClientUser | null {
|
|
111
|
+
return raw ? makeClientUser(port, raw) : null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get the worker-backed Auth handle.
|
|
116
|
+
*
|
|
117
|
+
* Mirrors `pyric/auth`'s `getAuth(sandbox)` / `firebase/auth`'s
|
|
118
|
+
* `getAuth(app)` — but the input is either an existing `ClientDb` (reusing
|
|
119
|
+
* its port, the common case in serve where Firestore + auth share one
|
|
120
|
+
* worker) or a worker URL (standalone).
|
|
121
|
+
*
|
|
122
|
+
* The returned handle seeds its `currentUser` mirror by opening an internal
|
|
123
|
+
* authState subscription that keeps it live across tabs.
|
|
124
|
+
*/
|
|
125
|
+
export function getAuth(source: ClientDb | string | URL, name?: string): ClientAuth {
|
|
126
|
+
let port: ClientPort;
|
|
127
|
+
if (typeof source === 'object' && '__kind' in source && source.__kind === 'client-db') {
|
|
128
|
+
port = source.port;
|
|
129
|
+
} else {
|
|
130
|
+
if (typeof SharedWorker === 'undefined') {
|
|
131
|
+
throw new Error(
|
|
132
|
+
'SharedWorker is not available. ' +
|
|
133
|
+
'Open this page over http:// (not file://) and use a supported browser ' +
|
|
134
|
+
'(Chrome 4+, Firefox 29+, Safari 16.4+).',
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
const worker = new SharedWorker(source as string | URL, {
|
|
138
|
+
type: 'classic',
|
|
139
|
+
name: name ?? 'pyric-shared-worker',
|
|
140
|
+
});
|
|
141
|
+
port = worker.port;
|
|
142
|
+
port.start();
|
|
143
|
+
wirePort(port);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const auth: ClientAuth = { __kind: 'client-auth', port, currentUser: null };
|
|
147
|
+
|
|
148
|
+
// Internal authState subscription keeps `auth.currentUser` live. Per-port
|
|
149
|
+
// sessions (#754): only THIS port's sign-ins/outs (and its session restore)
|
|
150
|
+
// fire here — another tab's sign-in is another user, not an update to us.
|
|
151
|
+
const subId = nextSubId();
|
|
152
|
+
openSnapshotSubscription(port, subId, {
|
|
153
|
+
port,
|
|
154
|
+
next: (raw) => {
|
|
155
|
+
auth.currentUser = toClientUser(port, raw as SerializedUser | null);
|
|
156
|
+
},
|
|
157
|
+
}, { t: 'sub', subId, target: 'authState' } satisfies InboundMessage);
|
|
158
|
+
|
|
159
|
+
return auth;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Connect to the auth emulator. No-op shim over the worker: the worker's
|
|
164
|
+
* sandbox IS the emulator-equivalent backend, so there's nothing to point at.
|
|
165
|
+
* Present for surface parity so app code that calls it doesn't break.
|
|
166
|
+
*/
|
|
167
|
+
export function connectAuthEmulator(
|
|
168
|
+
_auth: ClientAuth,
|
|
169
|
+
_url: string,
|
|
170
|
+
_options?: { disableWarnings?: boolean },
|
|
171
|
+
): void {
|
|
172
|
+
// Intentional no-op — the worker's sandbox is the local auth backend.
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ─── Sign-in / out / create (RPC) ─────────────────────────────────────────
|
|
176
|
+
|
|
177
|
+
export async function createUserWithEmailAndPassword(
|
|
178
|
+
auth: ClientAuth,
|
|
179
|
+
email: string,
|
|
180
|
+
password: string,
|
|
181
|
+
): Promise<ClientUserCredential> {
|
|
182
|
+
const raw = (await rpc(auth.port, {
|
|
183
|
+
t: 'op', id: nextId(), method: 'auth.createUser', email, password,
|
|
184
|
+
})) as SerializedUserCredential;
|
|
185
|
+
return hydrateCred(auth, raw);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ─── Admin user-DB ops (Pyric Studio data browse) ─────────────────────────
|
|
189
|
+
// Mirror `pyric/auth`'s `sandbox.{listUsers,createUser,updateUser,deleteUser,
|
|
190
|
+
// clearUsers}` over the port. No lens (admin control surface), so bare `rpc`.
|
|
191
|
+
|
|
192
|
+
export async function listUsers(auth: ClientAuth): Promise<AuthUserRecord[]> {
|
|
193
|
+
return (await rpc(auth.port, {
|
|
194
|
+
t: 'op', id: nextId(), method: 'auth.listUsers',
|
|
195
|
+
})) as AuthUserRecord[];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export async function adminCreateUser(
|
|
199
|
+
auth: ClientAuth,
|
|
200
|
+
request: CreateUserRequest,
|
|
201
|
+
): Promise<AuthUserRecord> {
|
|
202
|
+
return (await rpc(auth.port, {
|
|
203
|
+
t: 'op', id: nextId(), method: 'auth.adminCreateUser',
|
|
204
|
+
request: request as unknown as Record<string, unknown>,
|
|
205
|
+
})) as AuthUserRecord;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export async function adminUpdateUser(
|
|
209
|
+
auth: ClientAuth,
|
|
210
|
+
uid: string,
|
|
211
|
+
request: UpdateUserRequest,
|
|
212
|
+
): Promise<AuthUserRecord> {
|
|
213
|
+
return (await rpc(auth.port, {
|
|
214
|
+
t: 'op', id: nextId(), method: 'auth.adminUpdateUser', uid,
|
|
215
|
+
request: request as unknown as Record<string, unknown>,
|
|
216
|
+
})) as AuthUserRecord;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export async function adminDeleteUser(auth: ClientAuth, uid: string): Promise<void> {
|
|
220
|
+
await rpc(auth.port, { t: 'op', id: nextId(), method: 'auth.adminDeleteUser', uid });
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export async function adminClearUsers(auth: ClientAuth): Promise<void> {
|
|
224
|
+
await rpc(auth.port, { t: 'op', id: nextId(), method: 'auth.adminClearUsers' });
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ─── Sign-in provider config (Pyric Studio S-AUTH) ────────────────────────
|
|
228
|
+
// Mirror `pyric/auth`'s `sandbox.{getAuthProviderConfig,setAuthProviderConfig}`
|
|
229
|
+
// over the port. No dedicated subscription: `setProviderConfig` fires a
|
|
230
|
+
// `provider_config_update` sandbox event, so a caller re-reads via
|
|
231
|
+
// `getProviderConfig` on the SAME event feed `listUsers` callers already
|
|
232
|
+
// subscribe to (see `worker-live.ts`'s `subscribeUsers`).
|
|
233
|
+
|
|
234
|
+
export async function getProviderConfig(
|
|
235
|
+
auth: ClientAuth,
|
|
236
|
+
): Promise<Array<{ providerId: string; enabled: boolean }>> {
|
|
237
|
+
return (await rpc(auth.port, {
|
|
238
|
+
t: 'op', id: nextId(), method: 'auth.getProviderConfig',
|
|
239
|
+
})) as Array<{ providerId: string; enabled: boolean }>;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export async function setProviderConfig(
|
|
243
|
+
auth: ClientAuth,
|
|
244
|
+
providerId: string,
|
|
245
|
+
enabled: boolean,
|
|
246
|
+
): Promise<void> {
|
|
247
|
+
await rpc(auth.port, {
|
|
248
|
+
t: 'op', id: nextId(), method: 'auth.setProviderConfig', providerId, enabled,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export async function signInWithEmailAndPassword(
|
|
253
|
+
auth: ClientAuth,
|
|
254
|
+
email: string,
|
|
255
|
+
password: string,
|
|
256
|
+
): Promise<ClientUserCredential> {
|
|
257
|
+
const raw = (await rpc(auth.port, {
|
|
258
|
+
t: 'op', id: nextId(), method: 'auth.signInEmail', email, password,
|
|
259
|
+
})) as SerializedUserCredential;
|
|
260
|
+
return hydrateCred(auth, raw);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export async function signInAnonymously(auth: ClientAuth): Promise<ClientUserCredential> {
|
|
264
|
+
const raw = (await rpc(auth.port, {
|
|
265
|
+
t: 'op', id: nextId(), method: 'auth.signInAnonymously',
|
|
266
|
+
})) as SerializedUserCredential;
|
|
267
|
+
return hydrateCred(auth, raw);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export async function signOut(auth: ClientAuth): Promise<void> {
|
|
271
|
+
if (isDisconnectedPort(auth.port)) {
|
|
272
|
+
auth.currentUser = null;
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
await rpc(auth.port, { t: 'op', id: nextId(), method: 'auth.signOut' });
|
|
276
|
+
// The authState stream will also clear the mirror; set eagerly so a
|
|
277
|
+
// synchronous read right after `await signOut()` reflects the change.
|
|
278
|
+
auth.currentUser = null;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Bridge a provider identity resolved IN-PAGE to the worker (the provider
|
|
283
|
+
* sign-in seam). The entry adapter's worker-path `signInWithPopup`/
|
|
284
|
+
* `signInWithRedirect` runs the in-page `AuthFlowResolver` (which can't cross
|
|
285
|
+
* the worker port), then calls this with the picked identity; the worker seeds
|
|
286
|
+
* it + signs it in, returning a worker-backed credential. The mirror updates
|
|
287
|
+
* eagerly (like the email/anon paths) so a synchronous `auth.currentUser`
|
|
288
|
+
* read right after the await reflects the new user.
|
|
289
|
+
*/
|
|
290
|
+
export async function acceptProviderCredential(
|
|
291
|
+
auth: ClientAuth,
|
|
292
|
+
identity: ResolvedIdentity,
|
|
293
|
+
): Promise<ClientUserCredential> {
|
|
294
|
+
const raw = (await rpc(auth.port, {
|
|
295
|
+
t: 'op', id: nextId(), method: 'auth.acceptIdentity', identity,
|
|
296
|
+
})) as SerializedUserCredential;
|
|
297
|
+
return hydrateCred(auth, raw);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Re-establish THIS PORT's session for an existing identity (#754) — the
|
|
302
|
+
* per-tab reload restore. The page persists its uid in web storage
|
|
303
|
+
* (SessionStore); runtime.ts calls this at boot BEFORE app code runs. Soft:
|
|
304
|
+
* returns null (and leaves the port signed out) when the uid no longer
|
|
305
|
+
* resolves, so a stale record never throws.
|
|
306
|
+
*/
|
|
307
|
+
export async function restorePortSession(
|
|
308
|
+
auth: ClientAuth,
|
|
309
|
+
uid: string,
|
|
310
|
+
): Promise<ClientUser | null> {
|
|
311
|
+
const raw = (await rpc(auth.port, {
|
|
312
|
+
t: 'op', id: nextId(), method: 'auth.restorePortSession', uid,
|
|
313
|
+
})) as SerializedUser | null;
|
|
314
|
+
const user = toClientUser(auth.port, raw);
|
|
315
|
+
if (user) auth.currentUser = user;
|
|
316
|
+
return user;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function hydrateCred(auth: ClientAuth, raw: SerializedUserCredential): ClientUserCredential {
|
|
320
|
+
const user = makeClientUser(auth.port, raw.user);
|
|
321
|
+
// Eagerly update the mirror so `auth.currentUser` is correct immediately
|
|
322
|
+
// after the await, before the broadcast stream lands.
|
|
323
|
+
auth.currentUser = user;
|
|
324
|
+
return { user, providerId: raw.providerId, operationType: raw.operationType };
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ─── Persistence ──────────────────────────────────────────────────────────
|
|
328
|
+
|
|
329
|
+
/** Persistence markers — mirror `firebase/auth` / `pyric/auth`. */
|
|
330
|
+
export const inMemoryPersistence = { type: 'NONE' } as const;
|
|
331
|
+
|
|
332
|
+
export const browserSessionPersistence = { type: 'SESSION' } as const;
|
|
333
|
+
|
|
334
|
+
export const browserLocalPersistence = { type: 'LOCAL' } as const;
|
|
335
|
+
|
|
336
|
+
export type ClientPersistence = { readonly type: AuthPersistenceMode };
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Record the session-persistence mode on the worker (surface parity). The
|
|
340
|
+
* effective persistence is CLIENT-side (#754): the entry adapter mirrors the
|
|
341
|
+
* mode into the page's SessionStore, which decides where — or whether — this
|
|
342
|
+
* tab's session uid is stored for reload restore.
|
|
343
|
+
*/
|
|
344
|
+
export async function setPersistence(
|
|
345
|
+
auth: ClientAuth,
|
|
346
|
+
persistence: ClientPersistence,
|
|
347
|
+
): Promise<void> {
|
|
348
|
+
await rpc(auth.port, {
|
|
349
|
+
t: 'op', id: nextId(), method: 'auth.setPersistence', mode: persistence.type,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// ─── Observers (streaming subs) ────────────────────────────────────────────
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Subscribe to auth-state changes. Mirrors `firebase/auth`'s
|
|
357
|
+
* `onAuthStateChanged`. Fires immediately with THIS PORT's current session,
|
|
358
|
+
* then on every change to it (#754: sessions are per-port — another tab's
|
|
359
|
+
* sign-in is a different user, not an update to this one). Updates the
|
|
360
|
+
* handle's `currentUser` mirror before invoking the callback.
|
|
361
|
+
*/
|
|
362
|
+
export function onAuthStateChanged(
|
|
363
|
+
auth: ClientAuth,
|
|
364
|
+
callback: (user: ClientUser | null) => void,
|
|
365
|
+
): Unsubscribe {
|
|
366
|
+
return openAuthSub(auth, 'authState', callback);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Subscribe to ID-token changes. Mirrors `firebase/auth`'s
|
|
371
|
+
* `onIdTokenChanged` — fires on THIS PORT's identity transitions (per-port
|
|
372
|
+
* sessions, #754).
|
|
373
|
+
*/
|
|
374
|
+
export function onIdTokenChanged(
|
|
375
|
+
auth: ClientAuth,
|
|
376
|
+
callback: (user: ClientUser | null) => void,
|
|
377
|
+
): Unsubscribe {
|
|
378
|
+
return openAuthSub(auth, 'idToken', callback);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function openAuthSub(
|
|
382
|
+
auth: ClientAuth,
|
|
383
|
+
target: 'authState' | 'idToken',
|
|
384
|
+
callback: (user: ClientUser | null) => void,
|
|
385
|
+
): Unsubscribe {
|
|
386
|
+
const subId = nextSubId();
|
|
387
|
+
const port = auth.port;
|
|
388
|
+
|
|
389
|
+
openSnapshotSubscription(port, subId, {
|
|
390
|
+
port,
|
|
391
|
+
next: (raw) => {
|
|
392
|
+
const user = toClientUser(port, raw as SerializedUser | null);
|
|
393
|
+
auth.currentUser = user;
|
|
394
|
+
callback(user);
|
|
395
|
+
},
|
|
396
|
+
}, { t: 'sub', subId, target } satisfies InboundMessage);
|
|
397
|
+
|
|
398
|
+
return () => {
|
|
399
|
+
closeSubscription(port, subId);
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// ─── Token accessors (top-level mirrors) ──────────────────────────────────
|
|
404
|
+
|
|
405
|
+
/** Top-level mirror of `firebase/auth`'s `getIdToken(user)`. */
|
|
406
|
+
export async function getIdToken(user: ClientUser, forceRefresh?: boolean): Promise<string> {
|
|
407
|
+
return user.getIdToken(forceRefresh);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/** Top-level mirror of `firebase/auth`'s `getIdTokenResult(user)`. */
|
|
411
|
+
export async function getIdTokenResult(
|
|
412
|
+
user: ClientUser,
|
|
413
|
+
forceRefresh?: boolean,
|
|
414
|
+
): Promise<SerializedIdTokenResult> {
|
|
415
|
+
return user.getIdTokenResult(forceRefresh);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Top-level mirror of `firebase/auth`'s `updateProfile(user, profile)` over
|
|
420
|
+
* the worker. RPCs `auth.updateProfile` for THIS PORT's session (the worker
|
|
421
|
+
* owns the real `User`), then mutates the passed `user` mirror in place with
|
|
422
|
+
* the returned fields so a synchronous read right after the await is
|
|
423
|
+
* consistent. `null` clears a field; an absent field is left untouched.
|
|
424
|
+
*
|
|
425
|
+
* The port is recovered from the hidden {@link CLIENT_USER_PORT} handle stamped
|
|
426
|
+
* on every `ClientUser`, so this works without an `auth` handle in scope.
|
|
427
|
+
*/
|
|
428
|
+
export async function updateProfile(
|
|
429
|
+
user: ClientUser,
|
|
430
|
+
profile: { displayName?: string | null; photoURL?: string | null },
|
|
431
|
+
): Promise<void> {
|
|
432
|
+
const port = (user as { [CLIENT_USER_PORT]?: ClientPort })[CLIENT_USER_PORT];
|
|
433
|
+
if (!port) {
|
|
434
|
+
const err = new Error(
|
|
435
|
+
'updateProfile: unrecognized user — was it produced by a worker-path sign-in?',
|
|
436
|
+
) as Error & { code: string };
|
|
437
|
+
err.code = 'auth/invalid-user-token';
|
|
438
|
+
throw err;
|
|
439
|
+
}
|
|
440
|
+
const raw = (await rpc(port, {
|
|
441
|
+
t: 'op', id: nextId(), method: 'auth.updateProfile',
|
|
442
|
+
displayName: profile.displayName, photoURL: profile.photoURL,
|
|
443
|
+
})) as SerializedUser;
|
|
444
|
+
// Mutate the passed mirror in place (readonly at the type level, plain data
|
|
445
|
+
// at runtime) so held references reflect the change immediately.
|
|
446
|
+
const mutable = user as { -readonly [K in keyof ClientUser]: ClientUser[K] };
|
|
447
|
+
mutable.displayName = raw.displayName;
|
|
448
|
+
mutable.photoURL = raw.photoURL;
|
|
449
|
+
mutable.providerData = raw.providerData;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// ─── Provider flows — NOT supported over the worker yet ───────────────────
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Provider sign-in (`signInWithCredential`, `signInWithPopup`,
|
|
456
|
+
* `signInWithRedirect`) needs the AuthFlowResolver, which lives in-page and
|
|
457
|
+
* can't cross the worker port. NOT SUPPORTED over the SharedWorker in v1 —
|
|
458
|
+
* a clear error rather than silent breakage. Tracked as a Phase 2 follow-up:
|
|
459
|
+
* thread the resolver through, or run provider flows in-page and hand the
|
|
460
|
+
* resulting credential to the worker.
|
|
461
|
+
*/
|
|
462
|
+
export function signInWithCredential(): Promise<never> {
|
|
463
|
+
return Promise.reject(makeUnsupported('signInWithCredential'));
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* `beforeAuthStateChanged` gates a LOCAL identity transition — the
|
|
468
|
+
* worker owns the shared user pool + fires the real transition on its
|
|
469
|
+
* own side of the port, so a page-local gate registered here would
|
|
470
|
+
* either never run (silently useless) or run too late to actually
|
|
471
|
+
* block anything. Rather than accept a callback that quietly does
|
|
472
|
+
* nothing, fail loudly at registration time — same defensive pattern
|
|
473
|
+
* as {@link signInWithCredential}. Follow-up: thread registration
|
|
474
|
+
* through the worker RPC protocol so the gate can run host-side before
|
|
475
|
+
* the worker commits a transition.
|
|
476
|
+
*/
|
|
477
|
+
export function beforeAuthStateChanged(): never {
|
|
478
|
+
throw makeUnsupported('beforeAuthStateChanged');
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function makeUnsupported(api: string): Error & { code: string } {
|
|
482
|
+
const err = new Error(
|
|
483
|
+
`${api} is not supported over the SharedWorker yet (provider flows need ` +
|
|
484
|
+
'the in-page AuthFlowResolver). Follow-up: thread the resolver through or ' +
|
|
485
|
+
'run the flow in-page and hand the credential to the worker.',
|
|
486
|
+
) as Error & { code: string };
|
|
487
|
+
err.code = 'auth/operation-not-supported-in-this-environment';
|
|
488
|
+
return err;
|
|
489
|
+
}
|