@pyric/cli 0.1.0-alpha.11 → 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/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/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 +1 -1
- 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 +1 -1
- package/dist/serve/docs-ui/docs/get-started/start-building/index.html +1 -1
- package/dist/serve/docs-ui/docs/index.json +200 -25
- package/dist/serve/docs-ui/docs/messaging-compat/index.html +1 -1
- 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 +131 -66
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api.md +130 -65
- 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 +1 -1
- 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/llms.txt +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/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.js +2 -2
- package/dist/serve/worker/protocol.js.map +1 -1
- package/package.json +5 -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 -31
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api.md +0 -29
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bundle the import map serves for `firebase/database`.
|
|
3
|
+
*
|
|
4
|
+
* The SharedWorker client already carries the RTDB data-plane used by Studio
|
|
5
|
+
* and the Playground. This entry gives served apps the same common modular SDK
|
|
6
|
+
* surface while the in-page fallback delegates to `pyric/database`.
|
|
7
|
+
*/
|
|
8
|
+
import * as ip from 'pyric/database';
|
|
9
|
+
import { getDatabase as pyricGetDatabase } from 'pyric/database';
|
|
10
|
+
import {
|
|
11
|
+
rtdbChild,
|
|
12
|
+
rtdbConnectDatabaseEmulator,
|
|
13
|
+
rtdbGet,
|
|
14
|
+
rtdbGetDatabase,
|
|
15
|
+
rtdbOff,
|
|
16
|
+
rtdbOnValue,
|
|
17
|
+
rtdbPush,
|
|
18
|
+
rtdbRef,
|
|
19
|
+
rtdbRemove,
|
|
20
|
+
rtdbServerTimestamp,
|
|
21
|
+
rtdbSet,
|
|
22
|
+
rtdbUpdate,
|
|
23
|
+
} from '../worker/client.js';
|
|
24
|
+
import { useWorker } from './worker-runtime.js';
|
|
25
|
+
import { getApp, type FirebaseApp } from 'pyric/app';
|
|
26
|
+
import { workerClientForApp } from './app-client.js';
|
|
27
|
+
|
|
28
|
+
const workerDatabaseByApp = new WeakMap<FirebaseApp, ReturnType<typeof pyricGetDatabase>>();
|
|
29
|
+
|
|
30
|
+
export const getDatabase = ((app?: FirebaseApp) => {
|
|
31
|
+
const resolved = app ?? getApp();
|
|
32
|
+
if (!useWorker) return pyricGetDatabase(resolved);
|
|
33
|
+
const existing = workerDatabaseByApp.get(resolved);
|
|
34
|
+
if (existing) return existing;
|
|
35
|
+
const client = workerClientForApp(resolved);
|
|
36
|
+
const handle = Object.assign(rtdbGetDatabase(client), { app: resolved }) as unknown as ReturnType<typeof pyricGetDatabase>;
|
|
37
|
+
workerDatabaseByApp.set(resolved, handle);
|
|
38
|
+
return handle;
|
|
39
|
+
}) as typeof pyricGetDatabase;
|
|
40
|
+
|
|
41
|
+
export const ref = (useWorker ? rtdbRef : ip.ref) as typeof ip.ref;
|
|
42
|
+
export const child = (useWorker ? rtdbChild : ip.child) as typeof ip.child;
|
|
43
|
+
export const get = (useWorker ? rtdbGet : ip.get) as typeof ip.get;
|
|
44
|
+
export const set = (useWorker ? rtdbSet : ip.set) as typeof ip.set;
|
|
45
|
+
export const update = (useWorker ? rtdbUpdate : ip.update) as typeof ip.update;
|
|
46
|
+
export const remove = (useWorker ? rtdbRemove : ip.remove) as typeof ip.remove;
|
|
47
|
+
export const push = (useWorker ? rtdbPush : ip.push) as typeof ip.push;
|
|
48
|
+
export const onValue = (useWorker ? rtdbOnValue : ip.onValue) as typeof ip.onValue;
|
|
49
|
+
export const off = (useWorker ? rtdbOff : ip.off) as typeof ip.off;
|
|
50
|
+
export const serverTimestamp = (
|
|
51
|
+
useWorker ? rtdbServerTimestamp : ip.serverTimestamp
|
|
52
|
+
) as typeof ip.serverTimestamp;
|
|
53
|
+
export const connectDatabaseEmulator = (
|
|
54
|
+
useWorker ? rtdbConnectDatabaseEmulator : ip.connectDatabaseEmulator
|
|
55
|
+
) as typeof ip.connectDatabaseEmulator;
|
|
56
|
+
|
|
57
|
+
// ── Low-hanging-fruit exports (issue #149) ────────────────────────────────
|
|
58
|
+
// Served mode is always sandbox-backed (never a prod handle), and these are
|
|
59
|
+
// honest no-ops in the sandbox model regardless of the worker/in-page split,
|
|
60
|
+
// so they are unconditional no-ops here — no worker RPC needed. This also
|
|
61
|
+
// gives served apps import-time parity for the `firebase/database` surface.
|
|
62
|
+
export const goOffline = ((_db?: unknown) => {}) as typeof ip.goOffline;
|
|
63
|
+
export const goOnline = ((_db?: unknown) => {}) as typeof ip.goOnline;
|
|
64
|
+
export const forceLongPolling = (() => {}) as typeof ip.forceLongPolling;
|
|
65
|
+
export const forceWebSockets = (() => {}) as typeof ip.forceWebSockets;
|
|
66
|
+
export const enableLogging = ((_logger?: unknown, _persistent?: unknown) => {}) as typeof ip.enableLogging;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* `refFromURL(db, url)` — parse the path out of the URL and delegate to the
|
|
70
|
+
* picked `ref` (worker or in-page), so the resolved ref behaves exactly like
|
|
71
|
+
* `ref(db, path)`. The URL host/namespace is not honored (served sandbox is
|
|
72
|
+
* single-database) — matching the in-page `pyric/database` behavior.
|
|
73
|
+
*/
|
|
74
|
+
export const refFromURL = ((db: unknown, url: string) => {
|
|
75
|
+
let path: string;
|
|
76
|
+
try {
|
|
77
|
+
path = new URL(url).pathname;
|
|
78
|
+
} catch {
|
|
79
|
+
throw new Error(
|
|
80
|
+
`firebase/database refFromURL received a value that is not an absolute URL: ${url}`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return (ref as (db: unknown, path?: string) => unknown)(db, path);
|
|
84
|
+
}) as typeof ip.refFromURL;
|
|
85
|
+
|
|
86
|
+
function unsupportedWorkerApi(name: string): never {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`firebase/database ${name}() is not supported over the pyric SharedWorker yet. ` +
|
|
89
|
+
'Use the in-page fallback for this operation.',
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const runTransaction = (
|
|
94
|
+
useWorker ? (() => unsupportedWorkerApi('runTransaction')) : ip.runTransaction
|
|
95
|
+
) as typeof ip.runTransaction;
|
|
96
|
+
|
|
97
|
+
export const query = (
|
|
98
|
+
useWorker ? (() => unsupportedWorkerApi('query')) : ip.query
|
|
99
|
+
) as typeof ip.query;
|
|
100
|
+
export const orderByChild = (
|
|
101
|
+
useWorker ? (() => unsupportedWorkerApi('orderByChild')) : ip.orderByChild
|
|
102
|
+
) as typeof ip.orderByChild;
|
|
103
|
+
export const orderByKey = (
|
|
104
|
+
useWorker ? (() => unsupportedWorkerApi('orderByKey')) : ip.orderByKey
|
|
105
|
+
) as typeof ip.orderByKey;
|
|
106
|
+
export const orderByValue = (
|
|
107
|
+
useWorker ? (() => unsupportedWorkerApi('orderByValue')) : ip.orderByValue
|
|
108
|
+
) as typeof ip.orderByValue;
|
|
109
|
+
export const startAt = (
|
|
110
|
+
useWorker ? (() => unsupportedWorkerApi('startAt')) : ip.startAt
|
|
111
|
+
) as typeof ip.startAt;
|
|
112
|
+
export const startAfter = (
|
|
113
|
+
useWorker ? (() => unsupportedWorkerApi('startAfter')) : ip.startAfter
|
|
114
|
+
) as typeof ip.startAfter;
|
|
115
|
+
export const endAt = (
|
|
116
|
+
useWorker ? (() => unsupportedWorkerApi('endAt')) : ip.endAt
|
|
117
|
+
) as typeof ip.endAt;
|
|
118
|
+
export const endBefore = (
|
|
119
|
+
useWorker ? (() => unsupportedWorkerApi('endBefore')) : ip.endBefore
|
|
120
|
+
) as typeof ip.endBefore;
|
|
121
|
+
export const equalTo = (
|
|
122
|
+
useWorker ? (() => unsupportedWorkerApi('equalTo')) : ip.equalTo
|
|
123
|
+
) as typeof ip.equalTo;
|
|
124
|
+
export const limitToFirst = (
|
|
125
|
+
useWorker ? (() => unsupportedWorkerApi('limitToFirst')) : ip.limitToFirst
|
|
126
|
+
) as typeof ip.limitToFirst;
|
|
127
|
+
export const limitToLast = (
|
|
128
|
+
useWorker ? (() => unsupportedWorkerApi('limitToLast')) : ip.limitToLast
|
|
129
|
+
) as typeof ip.limitToLast;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bundle the import map serves for `firebase/firestore`.
|
|
3
|
+
*
|
|
4
|
+
* DUAL-PATH (Phase 3c): when a SharedWorker is available, the data ops route
|
|
5
|
+
* to the ONE worker-hosted sandbox (multi-tab sync + IDB/`--persist`
|
|
6
|
+
* durability); otherwise they run against the in-page sandbox — the unchanged
|
|
7
|
+
* fallback. The branch is picked ONCE at module load (`useWorker`).
|
|
8
|
+
*
|
|
9
|
+
* The COMPLETE modular surface is exported on BOTH paths: a missing named
|
|
10
|
+
* export fails the page at import time (the firebase/app failure class), so the
|
|
11
|
+
* worker path fills the functions the thin worker-client lacks (`or`/`and`,
|
|
12
|
+
* `Timestamp`, the client-cache config no-ops) right here.
|
|
13
|
+
*
|
|
14
|
+
* Browser-bundled by `../bundler.ts`; never imported by node-side code.
|
|
15
|
+
*/
|
|
16
|
+
import * as ip from 'pyric/firestore';
|
|
17
|
+
import { getFirestore as pyricGetFirestore } from 'pyric/firestore';
|
|
18
|
+
import * as wcRaw from '../worker/client.js';
|
|
19
|
+
import { useWorker } from './worker-runtime.js';
|
|
20
|
+
import { getApp, type FirebaseApp } from 'pyric/app';
|
|
21
|
+
import { workerClientForApp } from './app-client.js';
|
|
22
|
+
|
|
23
|
+
// The worker client mirrors pyric/firestore's DATA surface (same names + arg
|
|
24
|
+
// shapes); cast so the picked bindings type-check against the canonical module.
|
|
25
|
+
// Members the worker client genuinely lacks (or/and/Timestamp/cache config) are
|
|
26
|
+
// handled explicitly below — NOT taken from this cast.
|
|
27
|
+
const wc = wcRaw as unknown as typeof ip;
|
|
28
|
+
|
|
29
|
+
/** The data-path implementation chosen at load. */
|
|
30
|
+
const D = useWorker ? wc : ip;
|
|
31
|
+
|
|
32
|
+
// ── Data ops — route to the worker-hosted or in-page sandbox ──────────────
|
|
33
|
+
export const onSnapshot = D.onSnapshot;
|
|
34
|
+
export const collection = D.collection;
|
|
35
|
+
export const collectionGroup = D.collectionGroup;
|
|
36
|
+
export const doc = D.doc;
|
|
37
|
+
export const getDoc = D.getDoc;
|
|
38
|
+
export const getDocs = D.getDocs;
|
|
39
|
+
export const setDoc = D.setDoc;
|
|
40
|
+
export const addDoc = D.addDoc;
|
|
41
|
+
export const updateDoc = D.updateDoc;
|
|
42
|
+
export const deleteDoc = D.deleteDoc;
|
|
43
|
+
export const query = D.query;
|
|
44
|
+
export const where = D.where;
|
|
45
|
+
export const orderBy = D.orderBy;
|
|
46
|
+
export const limit = D.limit;
|
|
47
|
+
export const limitToLast = D.limitToLast;
|
|
48
|
+
export const startAt = D.startAt;
|
|
49
|
+
export const startAfter = D.startAfter;
|
|
50
|
+
export const endAt = D.endAt;
|
|
51
|
+
export const endBefore = D.endBefore;
|
|
52
|
+
export const runTransaction = D.runTransaction;
|
|
53
|
+
export const writeBatch = D.writeBatch;
|
|
54
|
+
export const serverTimestamp = D.serverTimestamp;
|
|
55
|
+
export const increment = D.increment;
|
|
56
|
+
export const arrayUnion = D.arrayUnion;
|
|
57
|
+
export const arrayRemove = D.arrayRemove;
|
|
58
|
+
export const deleteField = D.deleteField;
|
|
59
|
+
|
|
60
|
+
// ── Value class — path-independent (builds data; the worker serializes it via
|
|
61
|
+
// the shared codec) ──────────────────────────────────────────────────────
|
|
62
|
+
export const Timestamp = ip.Timestamp;
|
|
63
|
+
|
|
64
|
+
// ── Composite filters — path-independent (issue #144). The worker query
|
|
65
|
+
// protocol carries the composite filter tree end-to-end: the client `or`/
|
|
66
|
+
// `and` factories emit nested `FilterConstraintDescriptor`s, `query()`
|
|
67
|
+
// embeds them in the query descriptor, and the host rebuilds them through
|
|
68
|
+
// the REAL `pyric/firestore` `and`/`or` factories (see
|
|
69
|
+
// `worker/host.ts` resolveConstraint + `worker/protocol.ts`
|
|
70
|
+
// FilterConstraintDescriptor). So on BOTH paths `or`/`and` come from the
|
|
71
|
+
// chosen data impl `D` — the worker client on the worker path, in-page
|
|
72
|
+
// otherwise. Nested `and`/`or`/`where` composites and composition with
|
|
73
|
+
// orderBy/limit all cross intact; malformed composites (empty / non-filter
|
|
74
|
+
// operand) still raise the same modular-SDK TypeError. ────────────────────
|
|
75
|
+
export const or = D.or;
|
|
76
|
+
export const and = D.and;
|
|
77
|
+
|
|
78
|
+
// ── getFirestore — the canonical bare call returns the page's shared backend:
|
|
79
|
+
// the worker ClientDb on the worker path, the in-page sandbox otherwise. ──
|
|
80
|
+
const workerFirestoreByApp = new WeakMap<FirebaseApp, ReturnType<typeof pyricGetFirestore>>();
|
|
81
|
+
|
|
82
|
+
export const getFirestore = ((app?: FirebaseApp) => {
|
|
83
|
+
const resolved = app ?? getApp();
|
|
84
|
+
if (!useWorker) return pyricGetFirestore(resolved);
|
|
85
|
+
const existing = workerFirestoreByApp.get(resolved);
|
|
86
|
+
if (existing) return existing;
|
|
87
|
+
const client = workerClientForApp(resolved);
|
|
88
|
+
const handle = Object.assign(client, { app: resolved }) as unknown as ReturnType<typeof pyricGetFirestore>;
|
|
89
|
+
workerFirestoreByApp.set(resolved, handle);
|
|
90
|
+
return handle;
|
|
91
|
+
}) as typeof pyricGetFirestore;
|
|
92
|
+
|
|
93
|
+
// ── section 3c tier 2: ACCEPTED, sandbox-managed (no-op + one-time notice). ──────
|
|
94
|
+
// Apps configure client caching unconditionally; a missing named export
|
|
95
|
+
// fails the page at IMPORT time (the firebase/app failure class). None of
|
|
96
|
+
// these are emulated — the sandbox (in-page OR worker) IS the source of
|
|
97
|
+
// truth, so the client cache layer these configure has no role. Durable data
|
|
98
|
+
// is the worker's IDB (default) + `pyric dev --persist`. Path-independent.
|
|
99
|
+
|
|
100
|
+
let cacheNoticeShown = false;
|
|
101
|
+
function acceptedNoOp(name: string): void {
|
|
102
|
+
if (cacheNoticeShown) return;
|
|
103
|
+
cacheNoticeShown = true;
|
|
104
|
+
console.info(
|
|
105
|
+
`[pyric dev] ${name}(): client cache/persistence settings are accepted but unused — ` +
|
|
106
|
+
'the pyric sandbox is the source of truth. Durable state is the worker store / `pyric dev --persist`.',
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** firebase's sentinel value, re-exported for settings parity. */
|
|
111
|
+
export const CACHE_SIZE_UNLIMITED = -1;
|
|
112
|
+
|
|
113
|
+
export function initializeFirestore(
|
|
114
|
+
app?: Parameters<typeof pyricGetFirestore>[0],
|
|
115
|
+
settings?: unknown,
|
|
116
|
+
): ReturnType<typeof getFirestore> {
|
|
117
|
+
if (settings && Object.keys(settings as object).length > 0) acceptedNoOp('initializeFirestore');
|
|
118
|
+
return getFirestore(app as never);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function persistentLocalCache(_settings?: unknown): { kind: string } {
|
|
122
|
+
acceptedNoOp('persistentLocalCache');
|
|
123
|
+
return { kind: 'persistent' };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function memoryLocalCache(_settings?: unknown): { kind: string } {
|
|
127
|
+
return { kind: 'memory' };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function persistentSingleTabManager(_settings?: unknown): { kind: string } {
|
|
131
|
+
return { kind: 'persistentSingleTab' };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function persistentMultipleTabManager(): { kind: string } {
|
|
135
|
+
return { kind: 'persistentMultipleTab' };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function enableIndexedDbPersistence(_db?: unknown): Promise<void> {
|
|
139
|
+
acceptedNoOp('enableIndexedDbPersistence');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** No-op success, same rationale as `enableIndexedDbPersistence` — the
|
|
143
|
+
* SharedWorker path already IS the one store every tab reads/writes, so
|
|
144
|
+
* there's no separate multi-tab mode to opt into over the worker; the
|
|
145
|
+
* in-page fallback has no multi-tab story to begin with. */
|
|
146
|
+
export async function enableMultiTabIndexedDbPersistence(_db?: unknown): Promise<void> {
|
|
147
|
+
acceptedNoOp('enableMultiTabIndexedDbPersistence');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export async function clearIndexedDbPersistence(_db?: unknown): Promise<void> {
|
|
151
|
+
acceptedNoOp('clearIndexedDbPersistence');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Resolves immediately — sandbox writes apply synchronously in-page; over the
|
|
155
|
+
* worker the RPC ack already settled (judgment zone 4, recorded). */
|
|
156
|
+
export async function waitForPendingWrites(_db?: unknown): Promise<void> {}
|
|
157
|
+
|
|
158
|
+
// ── network toggles — no-op (accepted, unused). No network exists in the
|
|
159
|
+
// sandbox (in-page OR worker): every op is a local call, never a request
|
|
160
|
+
// that could be offline. Writes issued after `disableNetwork()` still
|
|
161
|
+
// commit immediately — no offline queue is simulated, because the sandbox
|
|
162
|
+
// cannot honestly deliver "queued until reconnected" with no connection to
|
|
163
|
+
// lose in the first place. ───────────────────────────────────────────────
|
|
164
|
+
export async function disableNetwork(_db?: unknown): Promise<void> {
|
|
165
|
+
acceptedNoOp('disableNetwork');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export async function enableNetwork(_db?: unknown): Promise<void> {
|
|
169
|
+
acceptedNoOp('enableNetwork');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* In-page fallback: forwards to `pyric/firestore`'s `terminate`, which
|
|
174
|
+
* genuinely tears the sandbox down via `Sandbox.dispose()`.
|
|
175
|
+
*
|
|
176
|
+
* Worker path: accepted no-op. The SharedWorker-hosted sandbox is
|
|
177
|
+
* shared across every tab on the page's origin — disposing it here
|
|
178
|
+
* would tear down listener registries out from under other open tabs,
|
|
179
|
+
* which the real `terminate()` contract (single-instance teardown)
|
|
180
|
+
* never implies. Documented divergence: over the worker, `terminate`
|
|
181
|
+
* settles without tearing anything down.
|
|
182
|
+
*/
|
|
183
|
+
export async function terminate(db?: unknown): Promise<void> {
|
|
184
|
+
if (useWorker) {
|
|
185
|
+
console.info(
|
|
186
|
+
'[pyric dev] terminate(): the SharedWorker-hosted sandbox is shared across every tab; ' +
|
|
187
|
+
'it is not torn down by a single tab calling terminate().',
|
|
188
|
+
);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
return ip.terminate(db as Parameters<typeof ip.terminate>[0]);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ── tier-1 cache-init + get-from-* + log-level + snapshot-sync (issue #144,
|
|
195
|
+
// tier-1 pass). Aliases and honest no-op config tokens — see
|
|
196
|
+
// `packages/pyric/src/firestore/index.ts`'s tier-1 section for the full
|
|
197
|
+
// rationale. `memoryEagerGarbageCollector`/`memoryLruGarbageCollector` and
|
|
198
|
+
// `setLogLevel` are path-independent (no data routing), so they delegate
|
|
199
|
+
// straight to `pyric/firestore`. `getDocFromServer`/`getDocFromCache` and
|
|
200
|
+
// their plural forms MUST route through `D` (the worker-vs-in-page pick)
|
|
201
|
+
// like `getDoc`/`getDocs` above, not straight to `ip`, so they read from
|
|
202
|
+
// whichever backend this page actually uses. ─────────────────────────────
|
|
203
|
+
|
|
204
|
+
export const memoryEagerGarbageCollector = ip.memoryEagerGarbageCollector;
|
|
205
|
+
export const memoryLruGarbageCollector = ip.memoryLruGarbageCollector;
|
|
206
|
+
export const setLogLevel = ip.setLogLevel;
|
|
207
|
+
|
|
208
|
+
export const getDocFromServer = D.getDoc;
|
|
209
|
+
export const getDocsFromServer = D.getDocs;
|
|
210
|
+
export const getDocFromCache = D.getDoc;
|
|
211
|
+
export const getDocsFromCache = D.getDocs;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Local no-op reimplementation rather than delegating to `ip.onSnapshotsInSync`:
|
|
215
|
+
* on the worker path `db` is a `ClientDb`, not a `pyric/firestore` `Firestore`
|
|
216
|
+
* handle, so it doesn't carry the `TARGET_SYMBOL` brand `ip.onSnapshotsInSync`
|
|
217
|
+
* dispatches on. Fires the callback once the current microtask queue settles —
|
|
218
|
+
* same honest approximation as the in-page implementation — on both paths.
|
|
219
|
+
*/
|
|
220
|
+
export function onSnapshotsInSync(
|
|
221
|
+
_db: unknown,
|
|
222
|
+
observerOrCallback: (() => void) | { next?: () => void },
|
|
223
|
+
): () => void {
|
|
224
|
+
const cb = typeof observerOrCallback === 'function' ? observerOrCallback : observerOrCallback.next;
|
|
225
|
+
let cancelled = false;
|
|
226
|
+
queueMicrotask(() => {
|
|
227
|
+
if (!cancelled && cb) cb();
|
|
228
|
+
});
|
|
229
|
+
return () => {
|
|
230
|
+
cancelled = true;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/__pyric/sdk/init.js` — the script tag `pyric dev` injects into every
|
|
3
|
+
* served HTML page. Pulls the shared runtime and mounts the sign-in helper.
|
|
4
|
+
* In worker mode the helper reads the worker user directory and owns UI state
|
|
5
|
+
* only; in fallback mode it adapts the page sandbox's Auth store.
|
|
6
|
+
*/
|
|
7
|
+
import { getAuth, sandbox as authSandbox } from 'pyric/auth';
|
|
8
|
+
import {
|
|
9
|
+
getAuth as getWorkerAuth,
|
|
10
|
+
listUsers,
|
|
11
|
+
} from '../worker/client.js';
|
|
12
|
+
import { sandbox } from './runtime.js';
|
|
13
|
+
import { useWorker, workerDb } from './worker-runtime.js';
|
|
14
|
+
import { ServeAuthHelper } from './auth-helper-core.js';
|
|
15
|
+
import { installServeAuthResolver } from './auth-helper-runtime.js';
|
|
16
|
+
import { mountAuthHelperDialog } from './auth-helper-dom.js';
|
|
17
|
+
|
|
18
|
+
const localAuth = useWorker ? null : getAuth(sandbox);
|
|
19
|
+
const workerAuth = useWorker && workerDb ? getWorkerAuth(workerDb) : null;
|
|
20
|
+
const helper = new ServeAuthHelper(
|
|
21
|
+
workerAuth
|
|
22
|
+
? {
|
|
23
|
+
list: async () => (await listUsers(workerAuth)).map((user) => ({
|
|
24
|
+
uid: user.uid,
|
|
25
|
+
email: user.email,
|
|
26
|
+
displayName: user.displayName,
|
|
27
|
+
customClaims: user.customClaims,
|
|
28
|
+
})),
|
|
29
|
+
}
|
|
30
|
+
: {
|
|
31
|
+
list: () => authSandbox.listIdentities(localAuth!),
|
|
32
|
+
add: (identity) => authSandbox.seedUsers(localAuth!, [{
|
|
33
|
+
uid: identity.uid,
|
|
34
|
+
email: identity.email ?? '',
|
|
35
|
+
password: '__pyric_popup_no_password__',
|
|
36
|
+
displayName: identity.displayName ?? undefined,
|
|
37
|
+
customClaims: identity.customClaims,
|
|
38
|
+
}]),
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
const resolver = helper.resolver();
|
|
42
|
+
installServeAuthResolver(resolver);
|
|
43
|
+
if (localAuth) authSandbox.setAuthFlowResolver(localAuth, resolver);
|
|
44
|
+
mountAuthHelperDialog(helper);
|
|
45
|
+
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `keepalive` size gate for the persist flush (pre-mortem #1).
|
|
3
|
+
*
|
|
4
|
+
* The persistence controller's `beforeunload` flush fires while the page is
|
|
5
|
+
* unloading; a plain `fetch` is aborted on unload, so the final delta is
|
|
6
|
+
* lost (the original "crash-only loss window" claim was wrong). `fetch(...,
|
|
7
|
+
* {keepalive: true})` survives unload — but the browser caps the TOTAL body
|
|
8
|
+
* size of in-flight keepalive requests at ~64KB. Above that the request is
|
|
9
|
+
* rejected, so we only set keepalive when the body comfortably fits, and
|
|
10
|
+
* warn once when it doesn't (that page's final unsaved change can be lost on
|
|
11
|
+
* tab close; reload-triggered flushes are unaffected because they complete
|
|
12
|
+
* before navigation).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Below this, keepalive is safe; above, skip it (and warn once). 60KB
|
|
16
|
+
* leaves headroom under the ~64KB spec cap for headers/other requests. */
|
|
17
|
+
export const KEEPALIVE_MAX_BYTES = 60_000;
|
|
18
|
+
|
|
19
|
+
let warnedLargeState = false;
|
|
20
|
+
|
|
21
|
+
export function keepaliveSafe(
|
|
22
|
+
body: string,
|
|
23
|
+
warn: (msg: string) => void = (m) => console.warn(m),
|
|
24
|
+
): boolean {
|
|
25
|
+
const bytes = byteLength(body);
|
|
26
|
+
if (bytes <= KEEPALIVE_MAX_BYTES) return true;
|
|
27
|
+
if (!warnedLargeState) {
|
|
28
|
+
warnedLargeState = true;
|
|
29
|
+
warn(
|
|
30
|
+
`[pyric dev] persisted state is ${Math.round(bytes / 1024)}KB — too large for an ` +
|
|
31
|
+
'unload-time flush; the final unsaved change may be lost if you CLOSE the tab before ' +
|
|
32
|
+
'the next auto-flush. Reloads and normal saves are unaffected.',
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Reset module state — tests only. */
|
|
39
|
+
export function __resetKeepaliveWarning(): void {
|
|
40
|
+
warnedLargeState = false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function byteLength(s: string): number {
|
|
44
|
+
// TextEncoder is in every browser + bun; avoids assuming Buffer.
|
|
45
|
+
return typeof TextEncoder !== 'undefined' ? new TextEncoder().encode(s).length : s.length;
|
|
46
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** The canonical `firebase/messaging/sw` served mirror. */
|
|
2
|
+
import * as inPage from 'pyric/messaging/sw';
|
|
3
|
+
import type {
|
|
4
|
+
MessagePayload,
|
|
5
|
+
Messaging,
|
|
6
|
+
NextFn,
|
|
7
|
+
Observer,
|
|
8
|
+
Unsubscribe,
|
|
9
|
+
} from 'pyric/messaging/sw';
|
|
10
|
+
import { getApp, type FirebaseApp } from 'pyric/app';
|
|
11
|
+
import { registerSandboxDelivery } from 'pyric/messaging/internal';
|
|
12
|
+
import {
|
|
13
|
+
messagingDeliver,
|
|
14
|
+
messagingGetMessaging,
|
|
15
|
+
messagingSubscribe,
|
|
16
|
+
type ClientMessaging,
|
|
17
|
+
} from '../worker/client/messaging.js';
|
|
18
|
+
import { workerClientForApp } from './app-client.js';
|
|
19
|
+
import { useWorker } from './worker-runtime.js';
|
|
20
|
+
|
|
21
|
+
export type {
|
|
22
|
+
FcmOptions,
|
|
23
|
+
GetTokenOptions,
|
|
24
|
+
MessagePayload,
|
|
25
|
+
Messaging,
|
|
26
|
+
NextFn,
|
|
27
|
+
NotificationPayload,
|
|
28
|
+
Observer,
|
|
29
|
+
Unsubscribe,
|
|
30
|
+
} from 'pyric/messaging/sw';
|
|
31
|
+
|
|
32
|
+
type WorkerMessaging = Messaging & ClientMessaging;
|
|
33
|
+
const workerMessagingByApp = new WeakMap<FirebaseApp, WorkerMessaging>();
|
|
34
|
+
const bigQueryExport = new WeakMap<Messaging, boolean>();
|
|
35
|
+
|
|
36
|
+
export function getMessaging(app?: FirebaseApp): Messaging {
|
|
37
|
+
const resolved = app ?? getApp();
|
|
38
|
+
if (!useWorker) return inPage.getMessaging(resolved);
|
|
39
|
+
const existing = workerMessagingByApp.get(resolved);
|
|
40
|
+
if (existing) return existing;
|
|
41
|
+
const handle = Object.assign(
|
|
42
|
+
messagingGetMessaging(workerClientForApp(resolved)),
|
|
43
|
+
{ app: resolved },
|
|
44
|
+
) as WorkerMessaging;
|
|
45
|
+
workerMessagingByApp.set(resolved, handle);
|
|
46
|
+
// Symmetric with the client entry: let `pyric/messaging/sw`'s `sandbox.deliver`
|
|
47
|
+
// drive this worker-backed handle over the transport (same broker, same op).
|
|
48
|
+
registerSandboxDelivery(handle, (spec) => messagingDeliver(handle, spec));
|
|
49
|
+
return handle;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function onBackgroundMessage(
|
|
53
|
+
messaging: Messaging,
|
|
54
|
+
nextOrObserver: NextFn<MessagePayload> | Observer<MessagePayload>,
|
|
55
|
+
): Unsubscribe {
|
|
56
|
+
return useWorker
|
|
57
|
+
? messagingSubscribe(messaging as WorkerMessaging, 'messaging.background', nextOrObserver)
|
|
58
|
+
: inPage.onBackgroundMessage(messaging, nextOrObserver);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function experimentalSetDeliveryMetricsExportedToBigQueryEnabled(
|
|
62
|
+
messaging: Messaging,
|
|
63
|
+
enable: boolean,
|
|
64
|
+
): void {
|
|
65
|
+
if (!useWorker) {
|
|
66
|
+
inPage.experimentalSetDeliveryMetricsExportedToBigQueryEnabled(messaging, enable);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if ((messaging as Partial<ClientMessaging>).__kind !== 'client-messaging') {
|
|
70
|
+
throw new Error('firebase/messaging/sw: unrecognized Messaging instance');
|
|
71
|
+
}
|
|
72
|
+
bigQueryExport.set(messaging, enable);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const isSupported = inPage.isSupported;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/** The canonical `firebase/messaging` served mirror. */
|
|
2
|
+
import * as inPage from 'pyric/messaging';
|
|
3
|
+
import type {
|
|
4
|
+
GetTokenOptions,
|
|
5
|
+
MessagePayload,
|
|
6
|
+
Messaging,
|
|
7
|
+
NextFn,
|
|
8
|
+
Observer,
|
|
9
|
+
Unsubscribe,
|
|
10
|
+
} from 'pyric/messaging';
|
|
11
|
+
import { getApp, type FirebaseApp } from 'pyric/app';
|
|
12
|
+
import { registerAppCleanup } from 'pyric/app/internal';
|
|
13
|
+
import { registerSandboxDelivery } from 'pyric/messaging/internal';
|
|
14
|
+
import {
|
|
15
|
+
messagingDeleteToken,
|
|
16
|
+
messagingDeliver,
|
|
17
|
+
messagingGetMessaging,
|
|
18
|
+
messagingGetToken,
|
|
19
|
+
messagingSetVisibility,
|
|
20
|
+
messagingSubscribe,
|
|
21
|
+
type ClientMessaging,
|
|
22
|
+
} from '../worker/client/messaging.js';
|
|
23
|
+
import { workerClientForApp } from './app-client.js';
|
|
24
|
+
import { useWorker } from './worker-runtime.js';
|
|
25
|
+
|
|
26
|
+
export type {
|
|
27
|
+
FcmOptions,
|
|
28
|
+
GetTokenOptions,
|
|
29
|
+
MessagePayload,
|
|
30
|
+
Messaging,
|
|
31
|
+
NextFn,
|
|
32
|
+
NotificationPayload,
|
|
33
|
+
Observer,
|
|
34
|
+
Unsubscribe,
|
|
35
|
+
} from 'pyric/messaging';
|
|
36
|
+
|
|
37
|
+
type WorkerMessaging = Messaging & ClientMessaging;
|
|
38
|
+
const workerMessagingByApp = new WeakMap<FirebaseApp, WorkerMessaging>();
|
|
39
|
+
const visibilityWired = new WeakSet<FirebaseApp>();
|
|
40
|
+
|
|
41
|
+
function wireVisibility(app: FirebaseApp, messaging: WorkerMessaging): void {
|
|
42
|
+
if (visibilityWired.has(app) || typeof document === 'undefined') return;
|
|
43
|
+
visibilityWired.add(app);
|
|
44
|
+
const sync = (): void => {
|
|
45
|
+
const state = document.visibilityState === 'visible' ? 'visible' : 'hidden';
|
|
46
|
+
void messagingSetVisibility(messaging, state).catch(() => {});
|
|
47
|
+
};
|
|
48
|
+
document.addEventListener('visibilitychange', sync);
|
|
49
|
+
registerAppCleanup(app, () => {
|
|
50
|
+
visibilityWired.delete(app);
|
|
51
|
+
document.removeEventListener('visibilitychange', sync);
|
|
52
|
+
});
|
|
53
|
+
sync();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getMessaging(app?: FirebaseApp): Messaging {
|
|
57
|
+
const resolved = app ?? getApp();
|
|
58
|
+
if (!useWorker) return inPage.getMessaging(resolved);
|
|
59
|
+
const existing = workerMessagingByApp.get(resolved);
|
|
60
|
+
if (existing) return existing;
|
|
61
|
+
const handle = Object.assign(
|
|
62
|
+
messagingGetMessaging(workerClientForApp(resolved)),
|
|
63
|
+
{ app: resolved },
|
|
64
|
+
) as WorkerMessaging;
|
|
65
|
+
workerMessagingByApp.set(resolved, handle);
|
|
66
|
+
wireVisibility(resolved, handle);
|
|
67
|
+
// The worker-backed handle isn't in pyric's in-page instance registry, so
|
|
68
|
+
// teach `pyric/messaging`'s `sandbox.deliver` to drive it over the transport
|
|
69
|
+
// (visibility+routing resolved host-side). Keeps `firebase/messaging` itself
|
|
70
|
+
// free of any `sandbox` surface — production parity is untouched.
|
|
71
|
+
registerSandboxDelivery(handle, (spec) => messagingDeliver(handle, spec));
|
|
72
|
+
return handle;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getToken(messaging: Messaging, options?: GetTokenOptions): Promise<string> {
|
|
76
|
+
return useWorker
|
|
77
|
+
? messagingGetToken(messaging as WorkerMessaging, options)
|
|
78
|
+
: inPage.getToken(messaging, options);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function deleteToken(messaging: Messaging): Promise<boolean> {
|
|
82
|
+
return useWorker
|
|
83
|
+
? messagingDeleteToken(messaging as WorkerMessaging)
|
|
84
|
+
: inPage.deleteToken(messaging);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function onMessage(
|
|
88
|
+
messaging: Messaging,
|
|
89
|
+
nextOrObserver: NextFn<MessagePayload> | Observer<MessagePayload>,
|
|
90
|
+
): Unsubscribe {
|
|
91
|
+
return useWorker
|
|
92
|
+
? messagingSubscribe(messaging as WorkerMessaging, 'messaging.foreground', nextOrObserver)
|
|
93
|
+
: inPage.onMessage(messaging, nextOrObserver);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const isSupported = inPage.isSupported;
|