/** * The polyfill bootstrap — the ONLY non-SDK surface of the client. * * It injects the REAL SDK and the polyfill settings; afterwards the SDK-shaped * exports (`ng`, `useShape`, `inbox`) behave as drop-ins. This is exposed at the * subpath `@ng-eventually/client/polyfill` so the main entry * (`@ng-eventually/client`) stays a **pure, SDK-identical** surface. Everything * here is removed at migration. */ import type { NgLike, UseShapeLike, PrincipalId } from "./types"; import type { RegistrySession } from "./store-registry"; import { CapRegistry } from "./caps"; /** * Consumer-injected dependencies of the storeRegistry (polyfill-era). The * registry itself is generic (it knows only native scopes); the consumer wires * up how to reach the shared-wallet session and how to normalize a username * used as the shim key. Removed at migration along with the whole shim. */ export interface StoreRegistryDeps { /** Resolve the current shared-wallet session (id + private-store anchor). */ getSession: () => Promise; /** Normalize a username for shim keying. Default: trim (identity-ish). */ normalizeUser?: (username: string) => string; } export interface EventuallyConfig { /** The REAL `@ng-org/web` `ng` (injected to avoid a hard import / alias loop). */ ng: NgLike; /** The REAL `@ng-org/orm` `useShape`. */ useShape: UseShapeLike; /** Shared-wallet credentials — polyfill only (one wallet for everyone). */ sharedWallet?: { name: string; secret: string }; /** Initial current user; may also be set later via {@link setCurrentUser}. */ currentUser?: PrincipalId; /** REAL `@ng-org/web` `init` (lifecycle) — forwarded by the lib's `init()`. */ init?: (...args: any[]) => any; /** REAL `@ng-org/orm` `initNg` (ORM signals) — forwarded by the lib's `initNg()`. */ initNg?: (...args: any[]) => any; } let cfg: EventuallyConfig | null = null; let currentUser: PrincipalId | null = null; let registryDeps: Required | null = null; /** The emulated ReadCap/WriteCap registry. Empty until the app declares caps; * while it has no read policy the read filter passes through (no regression). */ let caps = new CapRegistry(); export function configure(c: EventuallyConfig): void { cfg = c; currentUser = c.currentUser ?? null; } /** @internal — used by the SDK-shaped wrappers to reach the injected real SDK. */ export function getConfig(): EventuallyConfig { if (!cfg) throw new Error("[ng-eventually] configure() must be called before use"); return cfg; } /** Reset the injected config back to un-configured (mainly for tests, so a * suite that calls configure() can restore the not-configured guard state). */ export function resetConfig(): void { cfg = null; currentUser = null; } /** * Wire the storeRegistry's consumer-injected dependencies (session + username * normalization). Must be called before any storeRegistry.* use. Separate from * {@link configure} because it's storeRegistry-specific and, like the shim, * disappears at migration. */ export function configureStoreRegistry(deps: StoreRegistryDeps): void { registryDeps = { getSession: deps.getSession, normalizeUser: deps.normalizeUser ?? ((u: string) => u.trim()), }; } /** @internal — used by the storeRegistry to reach its injected dependencies. */ export function getStoreRegistryDeps(): Required { if (!registryDeps) { throw new Error("[ng-eventually] configureStoreRegistry() must be called before use"); } return registryDeps; } /** Reset storeRegistry deps (mainly for tests). */ export function resetStoreRegistry(): void { registryDeps = null; } /** Set the current app-level user (the polyfill's notion of "who am I"). */ export function setCurrentUser(id: PrincipalId | null): void { currentUser = id; } export function getCurrentUser(): PrincipalId | null { return currentUser; } /** The emulated cap registry — the app grants/opens caps on it (as it will via * real cap operations in the target). The read filter consults it. */ export function getCaps(): CapRegistry { return caps; } /** Reset all emulated caps (mainly for tests / fresh sessions). */ export function resetCaps(): void { caps = new CapRegistry(); } // Cap surface — polyfill-era (caps are emulated now; native at migration). // Re-exported here so the whole polyfill API lives under /polyfill. export { CapRegistry } from "./caps";