@pyric/cli 0.1.0-alpha.10 → 0.1.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md.orig +2 -2
- package/dist/assurance/.generated/conformance-verdicts.d.ts +16 -0
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +16 -0
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/bridge/server/peer.d.ts +1 -1
- package/dist/bridge/server.d.ts +1 -1
- package/dist/bridge/server.js +1 -1
- package/dist/cli/index.d.ts +11 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +13 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts +3 -3
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +5 -5
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +8 -2
- 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/conformance/.generated/conformance-docs.d.ts +12 -0
- package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -0
- package/dist/conformance/.generated/conformance-docs.js +2 -0
- package/dist/conformance/.generated/conformance-docs.js.map +1 -0
- package/dist/conformance/docs.d.ts +6 -0
- package/dist/conformance/docs.d.ts.map +1 -0
- package/dist/conformance/docs.js +6 -0
- package/dist/conformance/docs.js.map +1 -0
- package/dist/remote/index.d.ts.map +1 -1
- package/dist/remote/index.js +1 -0
- package/dist/remote/index.js.map +1 -1
- package/dist/serve/activity-guard.d.ts +4 -0
- package/dist/serve/activity-guard.d.ts.map +1 -0
- package/dist/serve/activity-guard.js +22 -0
- package/dist/serve/activity-guard.js.map +1 -0
- package/dist/serve/activity-route.d.ts +4 -0
- package/dist/serve/activity-route.d.ts.map +1 -0
- package/dist/serve/activity-route.js +157 -0
- package/dist/serve/activity-route.js.map +1 -0
- package/dist/serve/activity-warning.d.ts +4 -0
- package/dist/serve/activity-warning.d.ts.map +1 -0
- package/dist/serve/activity-warning.js +21 -0
- package/dist/serve/activity-warning.js.map +1 -0
- package/dist/serve/bridge-mount.d.ts +5 -0
- package/dist/serve/bridge-mount.d.ts.map +1 -1
- package/dist/serve/bridge-mount.js +1 -0
- package/dist/serve/bridge-mount.js.map +1 -1
- package/dist/serve/docs-ui/404.html +3 -0
- package/dist/serve/docs-ui/_astro/{_slug_.DPUwShm2.css → _slug_.CXh9yTP1.css} +1 -1
- package/dist/serve/docs-ui/_astro/_slug_.DUci-duz.css +1 -0
- package/dist/serve/docs-ui/docs/_rhythm/index.html +2 -1
- package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +3 -2
- package/dist/serve/docs-ui/docs/agent/set-up-your-agent.md +1 -1
- package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +2 -1
- package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +2 -1
- package/dist/serve/docs-ui/docs/ai-compat/index.html +2 -1
- package/dist/serve/docs-ui/docs/api-reference/index.html +51 -49
- package/dist/serve/docs-ui/docs/api-reference.md +3 -3
- package/dist/serve/docs-ui/docs/app-compat/index.html +2 -1
- package/dist/serve/docs-ui/docs/auth-compat/index.html +2 -1
- package/dist/serve/docs-ui/docs/build/ai-logic/index.html +18 -3
- package/dist/serve/docs-ui/docs/build/ai-logic.md +30 -2
- package/dist/serve/docs-ui/docs/build/authentication/index.html +2 -1
- package/dist/serve/docs-ui/docs/build/authentication.md +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +2 -1
- package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +46 -2
- package/dist/serve/docs-ui/docs/build/cloud-messaging.md +56 -1
- package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +2 -1
- package/dist/serve/docs-ui/docs/build/cloud-storage.md +1 -1
- package/dist/serve/docs-ui/docs/build/realtime-database/index.html +21 -3
- package/dist/serve/docs-ui/docs/build/realtime-database.md +25 -1
- package/dist/serve/docs-ui/docs/conformance-scores/index.html +2 -1
- package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +61 -28
- package/dist/serve/docs-ui/docs/create-pyric-reference-api.md +65 -20
- package/dist/serve/docs-ui/docs/database-compat/index.html +2 -1
- package/dist/serve/docs-ui/docs/firestore-compat/index.html +6 -5
- package/dist/serve/docs-ui/docs/firestore-compat.md +4 -4
- package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +2 -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/start-building/index.html +4 -3
- package/dist/serve/docs-ui/docs/get-started/start-building.md +2 -2
- package/dist/serve/docs-ui/docs/index.json +979 -579
- package/dist/serve/docs-ui/docs/messaging-compat/index.html +2 -1
- package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +2 -1
- package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +2 -1
- package/dist/serve/docs-ui/docs/overview/index.html +2 -1
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +5 -4
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api.md +3 -4
- package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api/index.html +5 -4
- package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api.md +3 -4
- package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api/index.html +5 -4
- package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api.md +3 -4
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api/index.html +2503 -12
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api.md +2219 -8
- 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 +4 -3
- package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api.md +2 -3
- package/dist/serve/docs-ui/docs/pyric-ai-reference-api/index.html +16 -11
- package/dist/serve/docs-ui/docs/pyric-ai-reference-api.md +14 -13
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +4 -3
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api.md +2 -3
- package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +7 -2
- package/dist/serve/docs-ui/docs/pyric-app-reference-api.md +5 -2
- package/dist/serve/docs-ui/docs/pyric-auth-reference-api/index.html +23 -12
- package/dist/serve/docs-ui/docs/pyric-auth-reference-api.md +15 -12
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +10 -48
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api.md +11 -24
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api/index.html +87 -97
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api.md +53 -65
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api/index.html +14 -15
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api.md +19 -28
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +4 -3
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api.md +2 -3
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +3 -2
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api.md +1 -2
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +51 -0
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api.md +36 -0
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +3 -2
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api.md +1 -2
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +3 -2
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api.md +1 -2
- package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api/index.html +3 -2
- package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api.md +1 -2
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +3 -2
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api.md +1 -2
- package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api/index.html +1067 -83
- package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api.md +1291 -160
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api/index.html +253 -157
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api.md +179 -85
- package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api/index.html +72 -7
- package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api.md +22 -7
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +33 -12
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api.md +15 -12
- package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +18 -17
- package/dist/serve/docs-ui/docs/pyric-database-reference-api.md +19 -22
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-api/index.html +1512 -545
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-api.md +1311 -316
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +5 -4
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api.md +3 -4
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +69 -369
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api.md +103 -216
- package/dist/serve/docs-ui/docs/pyric-rules-reference-api/index.html +10 -9
- package/dist/serve/docs-ui/docs/pyric-rules-reference-api.md +9 -10
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +8 -7
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api.md +6 -7
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +10 -9
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api.md +9 -10
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api/index.html +371 -884
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api.md +369 -883
- package/dist/serve/docs-ui/docs/pyric-storage-reference-api/index.html +25 -17
- package/dist/serve/docs-ui/docs/pyric-storage-reference-api.md +21 -19
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +3 -2
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api.md +1 -2
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +63 -776
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api.md +69 -510
- package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api/index.html +22 -21
- package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api.md +29 -30
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +15 -168
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api.md +17 -87
- package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api/index.html +6 -5
- package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api.md +5 -6
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +82 -970
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api.md +104 -479
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api/index.html +30 -29
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api.md +54 -55
- package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api/index.html +3 -2
- package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api.md +1 -2
- package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -4
- package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api.md +3 -4
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +9 -124
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api.md +7 -58
- package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api/index.html +24 -23
- package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api.md +31 -34
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +104 -1385
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api.md +133 -817
- package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api/index.html +34 -33
- package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api.md +37 -38
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +116 -1169
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api.md +142 -590
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api/index.html +4 -3
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api.md +3 -4
- package/dist/serve/docs-ui/docs/rules-compat/index.html +34 -1
- package/dist/serve/docs-ui/docs/rules-compat.md +32 -0
- package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +19 -2
- package/dist/serve/docs-ui/docs/secure/audit-your-rules.md +32 -0
- package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +2 -1
- package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +2 -1
- package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +2 -1
- package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript.md +1 -1
- package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +2 -1
- package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +2 -1
- package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +2 -1
- package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +2 -1
- package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +2 -1
- package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +2 -1
- package/dist/serve/docs-ui/docs/storage-compat/index.html +2 -1
- package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +2 -1
- package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +2 -1
- package/dist/serve/docs-ui/llms.txt +2 -1
- package/dist/serve/entries/ai.d.ts.map +1 -1
- package/dist/serve/entries/ai.js +39 -1
- package/dist/serve/entries/ai.js.map +1 -1
- package/dist/serve/entries/messaging-sw.d.ts.map +1 -1
- package/dist/serve/entries/messaging-sw.js +5 -1
- package/dist/serve/entries/messaging-sw.js.map +1 -1
- package/dist/serve/entries/messaging.d.ts.map +1 -1
- package/dist/serve/entries/messaging.js +7 -1
- package/dist/serve/entries/messaging.js.map +1 -1
- package/dist/serve/entries/runtime.d.ts.map +1 -1
- package/dist/serve/entries/runtime.js +20 -1
- package/dist/serve/entries/runtime.js.map +1 -1
- package/dist/serve/init-payload.d.ts +25 -0
- package/dist/serve/init-payload.d.ts.map +1 -1
- package/dist/serve/namespace.d.ts +39 -0
- package/dist/serve/namespace.d.ts.map +1 -1
- package/dist/serve/namespace.js +80 -1
- package/dist/serve/namespace.js.map +1 -1
- package/dist/serve/standalone-assets.d.ts +11 -9
- package/dist/serve/standalone-assets.d.ts.map +1 -1
- package/dist/serve/standalone-assets.js +6 -5
- package/dist/serve/standalone-assets.js.map +1 -1
- package/dist/serve/studio-ui/assets/{RulesCodeEditor-CXdSLKhO.js → RulesCodeEditor-CxVYcZXw.js} +1 -1
- package/dist/serve/studio-ui/assets/index-cpSfgQ7H.js +1218 -0
- package/dist/serve/studio-ui/assets/seed-DeuFKi4J.js +20 -0
- package/dist/serve/studio-ui/index.html +1 -1
- package/dist/serve/vite-plugin.d.ts +92 -15
- package/dist/serve/vite-plugin.d.ts.map +1 -1
- package/dist/serve/vite-plugin.js +281 -11
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/worker/activity-bootstrap.d.ts +8 -0
- package/dist/serve/worker/activity-bootstrap.d.ts.map +1 -0
- package/dist/serve/worker/activity-bootstrap.js +11 -0
- package/dist/serve/worker/activity-bootstrap.js.map +1 -0
- package/dist/serve/worker/client/connection.d.ts.map +1 -1
- package/dist/serve/worker/client/connection.js +17 -5
- package/dist/serve/worker/client/connection.js.map +1 -1
- package/dist/serve/worker/client/core.d.ts +2 -2
- package/dist/serve/worker/client/core.d.ts.map +1 -1
- package/dist/serve/worker/client/core.js +33 -5
- package/dist/serve/worker/client/core.js.map +1 -1
- package/dist/serve/worker/client/firestore-writes.d.ts.map +1 -1
- package/dist/serve/worker/client/firestore-writes.js +1 -0
- package/dist/serve/worker/client/firestore-writes.js.map +1 -1
- package/dist/serve/worker/client/messaging.d.ts +9 -1
- package/dist/serve/worker/client/messaging.d.ts.map +1 -1
- package/dist/serve/worker/client/messaging.js +15 -0
- package/dist/serve/worker/client/messaging.js.map +1 -1
- package/dist/serve/worker/client/studio.d.ts +10 -0
- package/dist/serve/worker/client/studio.d.ts.map +1 -1
- package/dist/serve/worker/client/studio.js +11 -0
- package/dist/serve/worker/client/studio.js.map +1 -1
- package/dist/serve/worker/durable-persistence.d.ts +12 -0
- package/dist/serve/worker/durable-persistence.d.ts.map +1 -0
- package/dist/serve/worker/durable-persistence.js +118 -0
- package/dist/serve/worker/durable-persistence.js.map +1 -0
- package/dist/serve/worker/entry.d.ts +7 -3
- package/dist/serve/worker/entry.d.ts.map +1 -1
- package/dist/serve/worker/entry.js +7 -3
- package/dist/serve/worker/entry.js.map +1 -1
- package/dist/serve/worker/host/core.d.ts +9 -5
- package/dist/serve/worker/host/core.d.ts.map +1 -1
- package/dist/serve/worker/host/core.js +34 -9
- package/dist/serve/worker/host/core.js.map +1 -1
- package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
- package/dist/serve/worker/host/dispatch.js +9 -2
- package/dist/serve/worker/host/dispatch.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.d.ts +1 -1
- package/dist/serve/worker/host/studio.d.ts.map +1 -1
- package/dist/serve/worker/host/studio.js +36 -1
- package/dist/serve/worker/host/studio.js.map +1 -1
- package/dist/serve/worker/host/subscriptions.d.ts.map +1 -1
- package/dist/serve/worker/host/subscriptions.js +27 -7
- package/dist/serve/worker/host/subscriptions.js.map +1 -1
- package/dist/serve/worker/host-context.d.ts +15 -0
- package/dist/serve/worker/host-context.d.ts.map +1 -1
- package/dist/serve/worker/host-context.js +10 -0
- package/dist/serve/worker/host-context.js.map +1 -1
- package/dist/serve/worker/host-messaging.d.ts.map +1 -1
- package/dist/serve/worker/host-messaging.js +9 -2
- package/dist/serve/worker/host-messaging.js.map +1 -1
- package/dist/serve/worker/index.d.ts +3 -2
- package/dist/serve/worker/index.d.ts.map +1 -1
- package/dist/serve/worker/index.js +4 -1
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/protocol.d.ts +25 -3
- 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/serve-init.d.ts +23 -37
- package/dist/serve/worker/serve-init.d.ts.map +1 -1
- package/dist/serve/worker/serve-init.js +95 -172
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/dist/vite.d.ts +4 -4
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +3 -3
- package/dist/vite.js.map +1 -1
- package/package.json +9 -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 +493 -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 +46 -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 +540 -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 +75 -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/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-plugin.ts +1102 -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 +202 -0
- package/src/serve/worker/client/core.ts +350 -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/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 +179 -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 +1112 -0
- package/src/serve/worker/serve-init.ts +606 -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 +17 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api/index.html +0 -30
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api.md +0 -30
- package/dist/serve/studio-ui/assets/index-BvtQIpGn.js +0 -1211
- package/dist/serve/studio-ui/assets/seed-3DMedLL3.js +0 -2
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firestore read execution — document/collection reads, keyspace enumeration,
|
|
3
|
+
* count/aggregate reads, and the `onSnapshot` listener. Each RPCs the worker and
|
|
4
|
+
* rehydrates the reply into the modular SDK's snapshot shapes.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
TargetDescriptor,
|
|
9
|
+
AggregateFieldDescriptor,
|
|
10
|
+
AggregateSpecDescriptor,
|
|
11
|
+
InboundMessage,
|
|
12
|
+
} from '../protocol.js';
|
|
13
|
+
import { closeSubscription, nextId, nextSubId, dataRpc, _defaultLens, openSnapshotSubscription, stampIssuer } from './core.js';
|
|
14
|
+
import type { ClientDb, DocRefHandle, CollRefHandle, QueryHandle, Unsubscribe } from './handles.js';
|
|
15
|
+
import { makeDocSnapshot, makeQuerySnapshot } from './snapshots.js';
|
|
16
|
+
import type { RawDocResult, RawQueryResult, ClientDocSnapshot, ClientQuerySnapshot } from './snapshots.js';
|
|
17
|
+
|
|
18
|
+
// ─── Execution functions (RPC) ────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
export async function getDoc(ref: DocRefHandle): Promise<ClientDocSnapshot> {
|
|
21
|
+
const result = await dataRpc(ref.port, {
|
|
22
|
+
t: 'op',
|
|
23
|
+
id: nextId(),
|
|
24
|
+
method: 'getDoc',
|
|
25
|
+
path: ref.descriptor.path,
|
|
26
|
+
}) as RawDocResult;
|
|
27
|
+
return makeDocSnapshot(result, ref.port);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function getDocs(
|
|
31
|
+
source: CollRefHandle | QueryHandle,
|
|
32
|
+
): Promise<ClientQuerySnapshot> {
|
|
33
|
+
const result = await dataRpc(source.port, {
|
|
34
|
+
t: 'op',
|
|
35
|
+
id: nextId(),
|
|
36
|
+
method: 'getDocs',
|
|
37
|
+
source: source.__kind === 'coll-ref'
|
|
38
|
+
? (source as CollRefHandle).descriptor
|
|
39
|
+
: (source as QueryHandle).descriptor,
|
|
40
|
+
}) as RawQueryResult;
|
|
41
|
+
return makeQuerySnapshot(result, source.port);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Enumerate root collection ids (Pyric Studio data browse). The modular SDK has
|
|
46
|
+
* no client `listCollections`, so the host scans the sandbox keyspace and
|
|
47
|
+
* returns the ids. Lens is attached (via dataRpc) but the host enumeration is
|
|
48
|
+
* lens-independent.
|
|
49
|
+
*/
|
|
50
|
+
export async function listRootCollections(db: ClientDb): Promise<string[]> {
|
|
51
|
+
const r = (await dataRpc(db.port, {
|
|
52
|
+
t: 'op',
|
|
53
|
+
id: nextId(),
|
|
54
|
+
method: 'listRootCollections',
|
|
55
|
+
})) as { ids: string[] };
|
|
56
|
+
return r.ids;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Enumerate subcollection ids under a document path (Pyric Studio data browse). */
|
|
60
|
+
export async function listSubcollections(db: ClientDb, docPath: string): Promise<string[]> {
|
|
61
|
+
const r = (await dataRpc(db.port, {
|
|
62
|
+
t: 'op',
|
|
63
|
+
id: nextId(),
|
|
64
|
+
method: 'listSubcollections',
|
|
65
|
+
docPath,
|
|
66
|
+
})) as { ids: string[] };
|
|
67
|
+
return r.ids;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function getCountFromServer(
|
|
71
|
+
source: CollRefHandle | QueryHandle,
|
|
72
|
+
): Promise<{ data(): { count: number } }> {
|
|
73
|
+
const result = await dataRpc(source.port, {
|
|
74
|
+
t: 'op',
|
|
75
|
+
id: nextId(),
|
|
76
|
+
method: 'count',
|
|
77
|
+
source: source.__kind === 'coll-ref'
|
|
78
|
+
? (source as CollRefHandle).descriptor
|
|
79
|
+
: (source as QueryHandle).descriptor,
|
|
80
|
+
}) as { count: number };
|
|
81
|
+
return { data: () => ({ count: result.count }) };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ─── Multi-field aggregates (count / sum / average) ───────────────────────
|
|
85
|
+
|
|
86
|
+
/** Factory: count() aggregate field. Mirrors `pyric/firestore`'s `count()`. */
|
|
87
|
+
export function count(): AggregateFieldDescriptor {
|
|
88
|
+
return { kind: 'count' };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Factory: sum-of-`field` aggregate. Mirrors `pyric/firestore`'s `sum()`. */
|
|
92
|
+
export function sum(field: string): AggregateFieldDescriptor {
|
|
93
|
+
return { kind: 'sum', field };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Factory: average-of-`field` aggregate. Empty input yields `null`. */
|
|
97
|
+
export function average(field: string): AggregateFieldDescriptor {
|
|
98
|
+
return { kind: 'average', field };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Run a multi-field aggregate on the worker. Mirrors `pyric/firestore`'s
|
|
103
|
+
* `getAggregateFromServer(query, spec)`: spec entries are keyed by
|
|
104
|
+
* caller-chosen aliases; `.data()` returns the numbers under the same keys
|
|
105
|
+
* (`average` over no rows is `null`).
|
|
106
|
+
*/
|
|
107
|
+
export async function getAggregateFromServer<S extends AggregateSpecDescriptor>(
|
|
108
|
+
source: CollRefHandle | QueryHandle,
|
|
109
|
+
spec: S,
|
|
110
|
+
): Promise<{ data(): { [K in keyof S]: number | null } }> {
|
|
111
|
+
const result = await dataRpc(source.port, {
|
|
112
|
+
t: 'op',
|
|
113
|
+
id: nextId(),
|
|
114
|
+
method: 'aggregate',
|
|
115
|
+
source: source.__kind === 'coll-ref'
|
|
116
|
+
? (source as CollRefHandle).descriptor
|
|
117
|
+
: (source as QueryHandle).descriptor,
|
|
118
|
+
spec,
|
|
119
|
+
}) as { data: { [K in keyof S]: number | null } };
|
|
120
|
+
return { data: () => result.data };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ─── onSnapshot ──────────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Subscribe to a document or query. Mirrors `pyric/firestore`'s `onSnapshot`.
|
|
127
|
+
*
|
|
128
|
+
* Returns an `unsub` function. Sends `{ t:'unsub', subId }` to the worker
|
|
129
|
+
* to deregister the listener on the worker side.
|
|
130
|
+
*/
|
|
131
|
+
export function onSnapshot(
|
|
132
|
+
target: DocRefHandle | CollRefHandle | QueryHandle,
|
|
133
|
+
callback: (snap: ClientDocSnapshot | ClientQuerySnapshot) => void,
|
|
134
|
+
errorCallback?: (err: unknown) => void,
|
|
135
|
+
): Unsubscribe {
|
|
136
|
+
const subId = nextSubId();
|
|
137
|
+
const port = target.port;
|
|
138
|
+
|
|
139
|
+
const subscription = {
|
|
140
|
+
port,
|
|
141
|
+
service: 'firestore' as const,
|
|
142
|
+
next: (raw: unknown) => {
|
|
143
|
+
const r = raw as Record<string, unknown>;
|
|
144
|
+
if ('docs' in r) {
|
|
145
|
+
callback(makeQuerySnapshot(r as unknown as RawQueryResult, port));
|
|
146
|
+
} else {
|
|
147
|
+
callback(makeDocSnapshot(r as unknown as RawDocResult, port));
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
error: errorCallback,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const descriptor: TargetDescriptor =
|
|
154
|
+
target.__kind === 'doc-ref'
|
|
155
|
+
? (target as DocRefHandle).descriptor
|
|
156
|
+
: target.__kind === 'coll-ref'
|
|
157
|
+
? (target as CollRefHandle).descriptor
|
|
158
|
+
: (target as QueryHandle).descriptor;
|
|
159
|
+
|
|
160
|
+
// Stamp the active default lens onto the sub (Pyric Studio "watch as user")
|
|
161
|
+
// exactly as `dataRpc` does for ops, so a `setLens({mode:'as',uid})` choice
|
|
162
|
+
// makes listeners impersonate too. Omitted when no lens is set → byte-identical
|
|
163
|
+
// wire message, preserving the additive contract. The declared op source
|
|
164
|
+
// rides along the same way (client-constructed subs only — the relay's
|
|
165
|
+
// subs post verbatim).
|
|
166
|
+
const opened = openSnapshotSubscription(
|
|
167
|
+
port,
|
|
168
|
+
subId,
|
|
169
|
+
subscription,
|
|
170
|
+
stampIssuer(
|
|
171
|
+
(_defaultLens
|
|
172
|
+
? { t: 'sub', subId, target: descriptor, actAs: _defaultLens }
|
|
173
|
+
: { t: 'sub', subId, target: descriptor }) satisfies InboundMessage,
|
|
174
|
+
),
|
|
175
|
+
);
|
|
176
|
+
if (!opened && errorCallback) queueMicrotask(() => errorCallback(new Error('Firebase App was deleted')));
|
|
177
|
+
|
|
178
|
+
return () => {
|
|
179
|
+
closeSubscription(port, subId);
|
|
180
|
+
};
|
|
181
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firestore reference, query, and sentinel factories — the synchronous,
|
|
3
|
+
* client-side descriptor builders. No RPC fires here: each returns a handle or
|
|
4
|
+
* marker carrying a serializable descriptor the execution functions send later.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
DocRef,
|
|
9
|
+
CollRef,
|
|
10
|
+
GroupRef,
|
|
11
|
+
QueryDescriptor,
|
|
12
|
+
QueryConstraintDescriptor,
|
|
13
|
+
FilterConstraintDescriptor,
|
|
14
|
+
TargetDescriptor,
|
|
15
|
+
SentinelMarker,
|
|
16
|
+
} from '../protocol.js';
|
|
17
|
+
import { lastSegment } from './handles.js';
|
|
18
|
+
import type { ClientDb, DocRefHandle, CollRefHandle, QueryHandle } from './handles.js';
|
|
19
|
+
|
|
20
|
+
// ─── Path factories (client-side only — no RPC) ──────────────────────────
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Build a document reference. Mirrors `pyric/firestore`'s `doc(db, path)`.
|
|
24
|
+
*
|
|
25
|
+
* WHY CLIENT-SIDE: Firebase's `doc()` is synchronous and path-only — it
|
|
26
|
+
* needs no data from the sandbox. We build a descriptor object here and
|
|
27
|
+
* include the port so execution calls can route to the worker.
|
|
28
|
+
*/
|
|
29
|
+
export function doc(
|
|
30
|
+
parent: ClientDb | CollRefHandle,
|
|
31
|
+
...pathSegments: string[]
|
|
32
|
+
): DocRefHandle {
|
|
33
|
+
const port = 'port' in parent ? parent.port : (parent as ClientDb).port;
|
|
34
|
+
let path: string;
|
|
35
|
+
|
|
36
|
+
if (parent.__kind === 'client-db') {
|
|
37
|
+
if (pathSegments.length === 0) throw new TypeError('doc(db, path) requires a path segment.');
|
|
38
|
+
path = pathSegments.join('/');
|
|
39
|
+
} else {
|
|
40
|
+
// parent is a CollRefHandle
|
|
41
|
+
const collPath = (parent as CollRefHandle).descriptor.path;
|
|
42
|
+
path = pathSegments.length > 0
|
|
43
|
+
? `${collPath}/${pathSegments.join('/')}`
|
|
44
|
+
: collPath; // caller will get auto-id via addDoc; doc() without id is unusual
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const descriptor: DocRef = { __ref: 'doc', path };
|
|
48
|
+
return {
|
|
49
|
+
__kind: 'doc-ref',
|
|
50
|
+
descriptor,
|
|
51
|
+
port,
|
|
52
|
+
id: lastSegment(path),
|
|
53
|
+
path,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Build a collection reference. Mirrors `pyric/firestore`'s `collection(db, path)`.
|
|
59
|
+
*/
|
|
60
|
+
export function collection(
|
|
61
|
+
parent: ClientDb | DocRefHandle,
|
|
62
|
+
...pathSegments: string[]
|
|
63
|
+
): CollRefHandle {
|
|
64
|
+
const port = parent.port;
|
|
65
|
+
if (pathSegments.length === 0) throw new TypeError('collection() requires a path segment.');
|
|
66
|
+
|
|
67
|
+
let path: string;
|
|
68
|
+
if (parent.__kind === 'client-db') {
|
|
69
|
+
path = pathSegments.join('/');
|
|
70
|
+
} else {
|
|
71
|
+
const docPath = (parent as DocRefHandle).descriptor.path;
|
|
72
|
+
path = `${docPath}/${pathSegments.join('/')}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const descriptor: CollRef = { __ref: 'collection', path };
|
|
76
|
+
return {
|
|
77
|
+
__kind: 'coll-ref',
|
|
78
|
+
descriptor,
|
|
79
|
+
port,
|
|
80
|
+
id: lastSegment(path),
|
|
81
|
+
path,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Build a collection-group query. Mirrors `pyric/firestore`'s `collectionGroup(db, id)`.
|
|
87
|
+
*/
|
|
88
|
+
export function collectionGroup(db: ClientDb, collectionId: string): QueryHandle {
|
|
89
|
+
const descriptor: QueryDescriptor = {
|
|
90
|
+
__ref: 'query',
|
|
91
|
+
source: { __ref: 'group', collectionId },
|
|
92
|
+
constraints: [],
|
|
93
|
+
};
|
|
94
|
+
return { __kind: 'query', descriptor, port: db.port };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─── Query constraint factories (client-side) ─────────────────────────────
|
|
98
|
+
|
|
99
|
+
/** Opaque query constraint — carries its descriptor for embedding in queries. */
|
|
100
|
+
export interface QueryConstraintHandle {
|
|
101
|
+
readonly _descriptor: QueryConstraintDescriptor;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function where(field: string, op: string, value: unknown): QueryConstraintHandle {
|
|
105
|
+
return { _descriptor: { kind: 'where', field, op, value } };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Extract a constraint's FILTER descriptor for composite embedding — throws
|
|
110
|
+
* the same TypeError `pyric/firestore`'s `and()`/`or()` raise when handed a
|
|
111
|
+
* non-filter (`orderBy` / `limit` / cursors are not valid inside composites).
|
|
112
|
+
*/
|
|
113
|
+
function toFilterDescriptor(
|
|
114
|
+
kind: 'and' | 'or',
|
|
115
|
+
c: QueryConstraintHandle,
|
|
116
|
+
): FilterConstraintDescriptor {
|
|
117
|
+
const d = c._descriptor;
|
|
118
|
+
if (d.kind !== 'where' && d.kind !== 'and' && d.kind !== 'or') {
|
|
119
|
+
throw new TypeError(
|
|
120
|
+
`pyric worker client: ${kind}() received a non-filter constraint (orderBy / limit are not valid here).`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return d;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function composite(kind: 'and' | 'or', filters: QueryConstraintHandle[]): QueryConstraintHandle {
|
|
127
|
+
if (filters.length === 0) {
|
|
128
|
+
throw new TypeError(`pyric worker client: ${kind}() requires at least one filter argument.`);
|
|
129
|
+
}
|
|
130
|
+
return { _descriptor: { kind, filters: filters.map((f) => toFilterDescriptor(kind, f)) } };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* OR composite filter — at least one operand must match. Operands must be
|
|
135
|
+
* filters (`where()`, or nested `or()`/`and()`). Mirrors `pyric/firestore`'s
|
|
136
|
+
* `or(...)`; the worker rebuilds it with the real modular factory.
|
|
137
|
+
*/
|
|
138
|
+
export function or(...filters: QueryConstraintHandle[]): QueryConstraintHandle {
|
|
139
|
+
return composite('or', filters);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** AND composite filter — every operand must match. See {@link or}. */
|
|
143
|
+
export function and(...filters: QueryConstraintHandle[]): QueryConstraintHandle {
|
|
144
|
+
return composite('and', filters);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function orderBy(field: string, direction?: 'asc' | 'desc'): QueryConstraintHandle {
|
|
148
|
+
return { _descriptor: { kind: 'orderBy', field, direction } };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function limit(n: number): QueryConstraintHandle {
|
|
152
|
+
return { _descriptor: { kind: 'limit', n } };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function limitToLast(n: number): QueryConstraintHandle {
|
|
156
|
+
return { _descriptor: { kind: 'limitToLast', n } };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function startAt(...values: unknown[]): QueryConstraintHandle {
|
|
160
|
+
return { _descriptor: { kind: 'startAt', values } };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function startAfter(...values: unknown[]): QueryConstraintHandle {
|
|
164
|
+
return { _descriptor: { kind: 'startAfter', values } };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function endAt(...values: unknown[]): QueryConstraintHandle {
|
|
168
|
+
return { _descriptor: { kind: 'endAt', values } };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function endBefore(...values: unknown[]): QueryConstraintHandle {
|
|
172
|
+
return { _descriptor: { kind: 'endBefore', values } };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Apply query constraints to a source ref or query.
|
|
177
|
+
* Mirrors `pyric/firestore`'s `query(source, ...constraints)`.
|
|
178
|
+
*/
|
|
179
|
+
export function query(
|
|
180
|
+
source: CollRefHandle | QueryHandle,
|
|
181
|
+
...constraints: QueryConstraintHandle[]
|
|
182
|
+
): QueryHandle {
|
|
183
|
+
const sourceDescriptor: TargetDescriptor =
|
|
184
|
+
source.__kind === 'coll-ref'
|
|
185
|
+
? (source as CollRefHandle).descriptor
|
|
186
|
+
: (source as QueryHandle).descriptor;
|
|
187
|
+
|
|
188
|
+
const existingConstraints: readonly QueryConstraintDescriptor[] =
|
|
189
|
+
source.__kind === 'query'
|
|
190
|
+
? (source as QueryHandle).descriptor.constraints
|
|
191
|
+
: [];
|
|
192
|
+
|
|
193
|
+
const descriptor: QueryDescriptor = {
|
|
194
|
+
__ref: 'query',
|
|
195
|
+
source: sourceDescriptor.__ref === 'query'
|
|
196
|
+
? (sourceDescriptor as QueryDescriptor).source
|
|
197
|
+
: (sourceDescriptor as DocRef | CollRef | GroupRef),
|
|
198
|
+
constraints: [
|
|
199
|
+
...existingConstraints,
|
|
200
|
+
...constraints.map((c) => c._descriptor),
|
|
201
|
+
],
|
|
202
|
+
};
|
|
203
|
+
return { __kind: 'query', descriptor, port: source.port };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ─── Sentinel factories (client-side markers) ────────────────────────────
|
|
207
|
+
|
|
208
|
+
export function serverTimestamp(): SentinelMarker {
|
|
209
|
+
return { __sentinel: 'serverTimestamp' };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function increment(n: number): SentinelMarker {
|
|
213
|
+
return { __sentinel: 'increment', n };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function arrayUnion(...values: unknown[]): SentinelMarker {
|
|
217
|
+
return { __sentinel: 'arrayUnion', values };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function arrayRemove(...values: unknown[]): SentinelMarker {
|
|
221
|
+
return { __sentinel: 'arrayRemove', values };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function deleteField(): SentinelMarker {
|
|
225
|
+
return { __sentinel: 'deleteField' };
|
|
226
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firestore write execution — single-document writes, `writeBatch`, and
|
|
3
|
+
* `runTransaction` with read-set validation + retry for multi-tab correctness.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { WriteDescriptor, TxnReadEntry } from '../protocol.js';
|
|
7
|
+
import { nextId, dataRpc } from './core.js';
|
|
8
|
+
import type { ClientDb, DocRefHandle, CollRefHandle } from './handles.js';
|
|
9
|
+
import { makeDocSnapshot } from './snapshots.js';
|
|
10
|
+
import type { RawDocResult, ClientDocSnapshot } from './snapshots.js';
|
|
11
|
+
|
|
12
|
+
export async function setDoc(
|
|
13
|
+
ref: DocRefHandle,
|
|
14
|
+
data: Record<string, unknown>,
|
|
15
|
+
options?: { merge?: boolean; mergeFields?: string[] },
|
|
16
|
+
): Promise<void> {
|
|
17
|
+
await dataRpc(ref.port, {
|
|
18
|
+
t: 'op',
|
|
19
|
+
id: nextId(),
|
|
20
|
+
method: 'setDoc',
|
|
21
|
+
path: ref.descriptor.path,
|
|
22
|
+
data,
|
|
23
|
+
options,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function updateDoc(
|
|
28
|
+
ref: DocRefHandle,
|
|
29
|
+
data: Record<string, unknown>,
|
|
30
|
+
): Promise<void> {
|
|
31
|
+
await dataRpc(ref.port, {
|
|
32
|
+
t: 'op',
|
|
33
|
+
id: nextId(),
|
|
34
|
+
method: 'updateDoc',
|
|
35
|
+
path: ref.descriptor.path,
|
|
36
|
+
data,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function deleteDoc(ref: DocRefHandle): Promise<void> {
|
|
41
|
+
await dataRpc(ref.port, {
|
|
42
|
+
t: 'op',
|
|
43
|
+
id: nextId(),
|
|
44
|
+
method: 'deleteDoc',
|
|
45
|
+
path: ref.descriptor.path,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function addDoc(
|
|
50
|
+
coll: CollRefHandle,
|
|
51
|
+
data: Record<string, unknown>,
|
|
52
|
+
): Promise<DocRefHandle> {
|
|
53
|
+
const result = await dataRpc(coll.port, {
|
|
54
|
+
t: 'op',
|
|
55
|
+
id: nextId(),
|
|
56
|
+
method: 'addDoc',
|
|
57
|
+
collectionPath: coll.descriptor.path,
|
|
58
|
+
data,
|
|
59
|
+
}) as { id: string; path: string };
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
__kind: 'doc-ref',
|
|
63
|
+
descriptor: { __ref: 'doc', path: result.path },
|
|
64
|
+
port: coll.port,
|
|
65
|
+
id: result.id,
|
|
66
|
+
path: result.path,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ─── writeBatch ──────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Client-side write batch. Buffers `set`/`update`/`delete` calls and
|
|
74
|
+
* sends them all to the worker on `.commit()`.
|
|
75
|
+
*
|
|
76
|
+
* Mirrors `pyric/firestore`'s `writeBatch(db)` shape:
|
|
77
|
+
* const batch = writeBatch(db);
|
|
78
|
+
* batch.set(ref, { ... });
|
|
79
|
+
* batch.delete(ref2);
|
|
80
|
+
* await batch.commit();
|
|
81
|
+
*/
|
|
82
|
+
export interface ClientWriteBatch {
|
|
83
|
+
set(ref: DocRefHandle, data: Record<string, unknown>, options?: { merge?: boolean; mergeFields?: string[] }): ClientWriteBatch;
|
|
84
|
+
update(ref: DocRefHandle, data: Record<string, unknown>): ClientWriteBatch;
|
|
85
|
+
delete(ref: DocRefHandle): ClientWriteBatch;
|
|
86
|
+
commit(): Promise<void>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function writeBatch(db: ClientDb): ClientWriteBatch {
|
|
90
|
+
const writes: WriteDescriptor[] = [];
|
|
91
|
+
const port = db.port;
|
|
92
|
+
|
|
93
|
+
const batch: ClientWriteBatch = {
|
|
94
|
+
set(ref, data, options) {
|
|
95
|
+
writes.push({ method: 'set', path: ref.descriptor.path, data, options });
|
|
96
|
+
return batch;
|
|
97
|
+
},
|
|
98
|
+
update(ref, data) {
|
|
99
|
+
writes.push({ method: 'update', path: ref.descriptor.path, data });
|
|
100
|
+
return batch;
|
|
101
|
+
},
|
|
102
|
+
delete(ref) {
|
|
103
|
+
writes.push({ method: 'delete', path: ref.descriptor.path });
|
|
104
|
+
return batch;
|
|
105
|
+
},
|
|
106
|
+
async commit() {
|
|
107
|
+
await dataRpc(port, {
|
|
108
|
+
t: 'op',
|
|
109
|
+
id: nextId(),
|
|
110
|
+
method: 'batchCommit',
|
|
111
|
+
writes: [...writes],
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
return batch;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ─── runTransaction ──────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
/** Client-side transaction handle. */
|
|
121
|
+
export interface ClientTransaction {
|
|
122
|
+
get(ref: DocRefHandle): Promise<ClientDocSnapshot>;
|
|
123
|
+
set(ref: DocRefHandle, data: Record<string, unknown>, options?: { merge?: boolean; mergeFields?: string[] }): void;
|
|
124
|
+
update(ref: DocRefHandle, data: Record<string, unknown>): void;
|
|
125
|
+
delete(ref: DocRefHandle): void;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Maximum number of times the client will retry `updateFn` on a
|
|
130
|
+
* worker-reported conflict (`aborted`). Matches Firestore SDK default.
|
|
131
|
+
*/
|
|
132
|
+
const TXN_MAX_ATTEMPTS = 5;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Run a transaction. Mirrors `pyric/firestore`'s `runTransaction(db, fn)`.
|
|
136
|
+
*
|
|
137
|
+
* MULTI-TAB CORRECTNESS — READ-SET VALIDATION + RETRY
|
|
138
|
+
* ----------------------------------------------------
|
|
139
|
+
* A transaction spans two messages: the `txn.get` RPC (read) and the
|
|
140
|
+
* `txnCommit` RPC (commit). Between those two messages another tab may
|
|
141
|
+
* write to a doc the current tab read — a silent lost update without
|
|
142
|
+
* validation. We fix this the standard way:
|
|
143
|
+
*
|
|
144
|
+
* 1. Each `txn.get(ref)` records `{ path, data }` in a per-attempt
|
|
145
|
+
* read-set (`data` is the raw `SerializedDocData` the worker
|
|
146
|
+
* returned, or `null` if the doc was missing).
|
|
147
|
+
* 2. `txnCommit` carries both `reads` (the read-set) and `writes`.
|
|
148
|
+
* 3. The worker re-reads each doc inside a sandbox transaction, re-
|
|
149
|
+
* serializes it the same way, and compares the JSON strings.
|
|
150
|
+
* Any mismatch → `{ ok: false, error: { code: 'aborted' } }`.
|
|
151
|
+
* 4. On `aborted`, the client discards the result of `updateFn` and
|
|
152
|
+
* re-runs it with a fresh transaction object (fresh reads, empty
|
|
153
|
+
* write buffer). Up to `TXN_MAX_ATTEMPTS` attempts are made.
|
|
154
|
+
* 5. After the cap, throws an error with `.code === 'aborted'`.
|
|
155
|
+
*
|
|
156
|
+
* This matches real Firestore's behaviour: the SDK retries `updateFn`
|
|
157
|
+
* on conflict rather than surfacing the error immediately.
|
|
158
|
+
*/
|
|
159
|
+
export async function runTransaction<R>(
|
|
160
|
+
db: ClientDb,
|
|
161
|
+
updateFn: (txn: ClientTransaction) => Promise<R> | R,
|
|
162
|
+
): Promise<R> {
|
|
163
|
+
const port = db.port;
|
|
164
|
+
|
|
165
|
+
for (let attempt = 0; attempt < TXN_MAX_ATTEMPTS; attempt++) {
|
|
166
|
+
// Fresh read-set and write buffer for each attempt.
|
|
167
|
+
const reads: TxnReadEntry[] = [];
|
|
168
|
+
const writes: WriteDescriptor[] = [];
|
|
169
|
+
|
|
170
|
+
const txn: ClientTransaction = {
|
|
171
|
+
async get(ref) {
|
|
172
|
+
// RPC to the worker — capture the raw result before rehydration.
|
|
173
|
+
const rawResult = await dataRpc(ref.port, {
|
|
174
|
+
t: 'op',
|
|
175
|
+
id: nextId(),
|
|
176
|
+
method: 'getDoc',
|
|
177
|
+
path: ref.descriptor.path,
|
|
178
|
+
activity: { groupKind: 'transaction' },
|
|
179
|
+
}) as RawDocResult;
|
|
180
|
+
|
|
181
|
+
// Record the raw serialized data (or null) in the read-set.
|
|
182
|
+
// We preserve the wire-form SerializedDocData so the worker can
|
|
183
|
+
// re-serialize the current doc and compare JSON strings.
|
|
184
|
+
reads.push({
|
|
185
|
+
path: ref.descriptor.path,
|
|
186
|
+
data: (rawResult.exists && rawResult.data) ? rawResult.data : null,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return makeDocSnapshot(rawResult, ref.port);
|
|
190
|
+
},
|
|
191
|
+
set(ref, data, options) {
|
|
192
|
+
writes.push({ method: 'set', path: ref.descriptor.path, data, options });
|
|
193
|
+
},
|
|
194
|
+
update(ref, data) {
|
|
195
|
+
writes.push({ method: 'update', path: ref.descriptor.path, data });
|
|
196
|
+
},
|
|
197
|
+
delete(ref) {
|
|
198
|
+
writes.push({ method: 'delete', path: ref.descriptor.path });
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const result = await updateFn(txn);
|
|
203
|
+
|
|
204
|
+
// Send read-set + writes to the worker for validation and commit.
|
|
205
|
+
try {
|
|
206
|
+
await dataRpc(port, {
|
|
207
|
+
t: 'op',
|
|
208
|
+
id: nextId(),
|
|
209
|
+
method: 'txnCommit',
|
|
210
|
+
reads: [...reads],
|
|
211
|
+
writes: [...writes],
|
|
212
|
+
});
|
|
213
|
+
return result;
|
|
214
|
+
} catch (err) {
|
|
215
|
+
const e = err as { code?: string };
|
|
216
|
+
if (e.code === 'aborted') {
|
|
217
|
+
// Conflict detected — retry updateFn on the next attempt.
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
// Permission-denied, not-found, etc. — propagate immediately.
|
|
221
|
+
throw err;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Exceeded max attempts.
|
|
226
|
+
const abortErr = new Error(
|
|
227
|
+
`Transaction failed after ${TXN_MAX_ATTEMPTS} attempts due to repeated conflicts. ` +
|
|
228
|
+
'Another tab is concurrently writing to the same documents.',
|
|
229
|
+
) as Error & { code: string };
|
|
230
|
+
abortErr.code = 'aborted';
|
|
231
|
+
throw abortErr;
|
|
232
|
+
}
|