refactor(layout): extraire le magasin d'injection vers shared-wallet/bootstrap

L'entrée publique `/polyfill` portait le magasin d'injection (le `ng` injecté,
les dépendances du registre, QUI est connecté, le singleton `CapRegistry`). Tout
module interne l'importait donc pour atteindre la config — ce qui faisait de
l'entrée une dépendance du code qu'elle publie, avec les cycles
`polyfill` <-> `connect` et `polyfill` <-> `inbox`.

Le magasin rejoint `shared-wallet/` : rien n'est injecté en amont, l'app importe
le SDK et « qui suis-je » est la session — il n'y a pas de relais d'utilisateur
courant parce qu'un wallet a exactement un user. Ce module est la forme de cette
absence, il s'évapore en entier à la migration.

L'entrée ne fait plus que ré-exporter. Plus aucun module interne n'importe
`polyfill`.
This commit is contained in:
Sylvain Duchesne
2026-08-04 13:51:56 +02:00
parent 0b37d17c2f
commit 36c0148750
16 changed files with 266 additions and 229 deletions
@@ -34,7 +34,7 @@
* them and this drains each in turn.
*/
import { getCaps, getCurrentUser } from "../polyfill";
import { getCaps, getCurrentUser } from "../shared-wallet/bootstrap";
import { myInboxes, readLinks, resolveAccount } from "../shared-wallet/account-registry";
import { processInbox } from "../surface/inbox";
@@ -60,7 +60,7 @@
*/
import { mustNotAttempt } from "./reach";
import { getConfig, getStoreRegistryDeps } from "../polyfill";
import { getConfig, getStoreRegistryDeps } from "../shared-wallet/bootstrap";
import { subscribeDocUnguarded, type Unsubscribe } from "../surface/subscribe";
import { logStage, shortNuri } from "../shared-wallet/access-log";
import type { Nuri } from "../model/types";
@@ -40,7 +40,7 @@
* At migration this module disappears: the boundary becomes the wallet itself.
*/
import { getCaps } from "../polyfill";
import { getCaps } from "../shared-wallet/bootstrap";
import { targetOf } from "../model/nuri";
import type { Nuri } from "../model/types";
+24 -215
View File
@@ -1,223 +1,32 @@
/**
* The polyfill bootstrap — the ONLY non-SDK surface of the client.
* `@ng-eventually/client/polyfill` — the polyfill-era door.
*
* 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, Nuri, PrincipalId, ReadCap } from "./model/types";
import type { RegistrySession } from "./shared-wallet/account-registry";
import { CapRegistry } from "./emulated-verifier/caps";
import { setAccessLog } from "./shared-wallet/access-log";
import { inspectOutbox } from "./shared-wallet/outbox-log";
import { startConnect } from "./emulated-verifier/connect";
/**
* 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 an identity id
* 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<RegistrySession>;
/** Normalize an identity id for shim keying. Default: trim (identity-ish). */
normalizeId?: (id: string) => string;
/**
* POINTER micro-guard budget. The account records now live in a subscribable
* doc-shim (`did:ng:o:...`) reached through a well-known write-once POINTER triple
* in the store-root graph. The doc-shim read is barrier-AUTHORITATIVE, so accounts
* need NO retry (this replaces the deleted account-level `provisionRetry`). The
* ONLY residual sync-lag window is the store-root pointer read itself — one
* write-once triple. This bounded guard re-reads JUST that pointer a few times if a
* fresh cold read misses it; it can never provision or fork an account (worst case:
* a couple extra reads before an existing pointer is seen). Enable it where the REAL
* broker is used (app + e2e). Left UNSET (the default) → `attempts: 1` = single
* read, keeping the synchronous unit fakes fast and unchanged.
*/
pointerGuard?: { attempts?: number; baseMs?: number; maxStepMs?: number };
}
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;
/**
* Turn on the OFF-by-default document access log (see {@link ./access-log}):
* every real read/write is printed, prefixed by the active identity, to
* diagnose the shared-wallet isolation leak. Also enablable without a code
* change via the env var `NG_EVENTUALLY_ACCESS_LOG=1`. Default: false.
*/
debugAccessLog?: boolean;
/** 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;
/** Required fields of StoreRegistryDeps after defaults are applied. `pointerGuard`
* defaults to `{ attempts: 1 }` (single read) when the consumer leaves it unset. */
type ResolvedRegistryDeps = Required<
Pick<StoreRegistryDeps, "getSession" | "normalizeId" | "pointerGuard">
>;
let registryDeps: ResolvedRegistryDeps | null = null;
/**
* The map key of the current identity — deliberately NOT the raw id.
* Everything importable here disappears at migration, and that is the point of the
* separate entry: what an application imports from this path is exactly what it will
* have to delete. The SDK-identical entry (`@ng-eventually/client`) carries the other
* promise — a target counterpart for every symbol.
*
* A virtual user IS a shim account, and the shim keys accounts by the
* consumer-injected `normalizeId` ("@Alice" and "alice" are ONE account, with one
* set of scope documents). This record must key the same way, or a consumer that
* spells its own id differently between two calls gets a SECOND record and stops
* reading its own documents — the caps are filed under one spelling and looked up
* under the other. Falls back to the raw id while the registry deps are not yet
* configured (nothing can be filed before that anyway).
* This file only RE-EXPORTS. The implementation lives with the fate it belongs to:
* the injection store and the current-user relay in `shared-wallet/bootstrap.ts`
* (no counterpart, evaporates), the cap registry in `emulated-verifier/caps.ts`
* (stands in for the verifier's own bookkeeping). Keeping the store here made the
* published entry a dependency of the code it publishes.
*/
function capsHolder(): PrincipalId | null {
if (currentUser === null) return null;
return registryDeps ? registryDeps.normalizeId(currentUser) : currentUser;
}
/**
* The emulated cap registry — one record PER identity (per virtual user),
* resolved through {@link capsHolder} on every call. So switching identity
* SWITCHES heldByHolder (nothing to reset, nothing wiped); see `caps.ts`. Empty until
* the first cap is issued, and while it is empty the read filter passes through
* (no regression).
*/
let caps = new CapRegistry(capsHolder);
export function configure(c: EventuallyConfig): void {
cfg = c;
currentUser = c.currentUser ?? null;
setAccessLog(c.debugAccessLog ?? false);
}
/** @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 + identity-id
* 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 {
// Fire the outbox inspection (Volet 3 of the low-level data-path trace) once,
// on the FIRST successful `getSession()` resolution — the most reliable
// "a session is established" signal available: every low-level reader/writer
// (store-registry, open-repo, read-model, subscribe, inbox) reaches its
// session through this SAME injected `getSession`, so wrapping it HERE catches
// the first success from whichever caller happens to run first, instead of
// tying the probe to one particular call site. Only on SUCCESS (an error
// propagates untouched, exactly as before) and only ONCE per
// `configureStoreRegistry()` call (a fresh session config → a fresh check).
let outboxInspected = false;
const getSession = async (): Promise<RegistrySession> => {
const session = await deps.getSession();
if (!outboxInspected) {
outboxInspected = true;
inspectOutbox();
}
return session;
};
registryDeps = {
getSession,
normalizeId: deps.normalizeId ?? ((id: string) => id.trim()),
// Default: single read (no re-read). Only the real-broker consumers (app + e2e)
// opt into the bounded pointer micro-guard; unit fakes stay synchronous.
pointerGuard: deps.pointerGuard ?? { attempts: 1 },
};
}
/** @internal — used by the storeRegistry to reach its injected dependencies. */
export function getStoreRegistryDeps(): ResolvedRegistryDeps {
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 identity id — who the SDK is reading/writing as. In the target
* this is the wallet user established at wallet-import time; here the consumer
* relays that id through this call so the read filter and the inbox `from` know
* who is acting. Passing `null` clears it (no identity yet, e.g. during startup).
*/
export function setCurrentUser(id: PrincipalId | null): void {
const changed = currentUser !== id;
currentUser = id;
// Connecting a user is what triggers inbox processing — the library's job, not
// the app's. Fire-and-forget: this setter is synchronous and every consumer calls
// it from synchronous code, so the work announces itself through the cap
// registry's change signal instead of making callers await. See `connect.ts`.
//
// Gated on the registry being configured, and that is not a test convenience: an
// identity set before the session resolves has nothing to restore and no inbox to
// reach, so firing would be I/O that can only fail. The consumer's real sequence
// is `configureStoreRegistry` then `setCurrentUser`; anything else can call
// `connectedUser()` explicitly.
if (changed && id !== null && registryDeps !== null) startConnect();
}
export function getCurrentUser(): PrincipalId | null {
return currentUser;
}
/** The emulated cap registry — what the current identity holds, plus the emulated
* public store. The read filter and the read-model consult it. */
export function getCaps(): CapRegistry {
return caps;
}
/**
* Do I hold the cap of `nuri`? — the held-caps lookup, the ONLY way a cap is
* obtained besides being given one. Returns `undefined` when what I hold has none;
* that is the whole answer the model can give (there is no "may P read D?").
*
* Shorthand for `getCaps().capFor(nuri)`, exposed because it is the surface the
* consumer actually uses.
*/
export function capFor(nuri: Nuri): ReadCap | undefined {
return caps.capFor(nuri);
}
/**
* Drop EVERY holder's caps (tests / a fresh wallet). This is **not** what an identity
* change does: switching identity switches heldByHolder, it never wipes one — if it
* wiped, durability would be a lie and per-session re-declaration would come back
* under another name. Nothing in the library calls this on `setCurrentUser`.
*/
export function resetCaps(): void {
// Clear IN PLACE rather than rebuilding: whoever subscribed to the registry's
// change signal (`watchShape`) stays subscribed to the live instance instead of
// silently holding a listener on an orphaned one.
caps.clear();
}
export type { StoreRegistryDeps, EventuallyConfig } from "./shared-wallet/bootstrap";
export {
configure,
getConfig,
resetConfig,
configureStoreRegistry,
getStoreRegistryDeps,
resetStoreRegistry,
setCurrentUser,
getCurrentUser,
getCaps,
capFor,
resetCaps,
} from "./shared-wallet/bootstrap";
// Cap surface — polyfill-era (caps are emulated now; native at migration).
// Re-exported here so the whole polyfill API lives under /polyfill. `shareCap`
@@ -19,7 +19,7 @@
* migration where the broker/verifier enforces isolation natively.
*/
import { getCurrentUser } from "../polyfill";
import { getCurrentUser } from "./bootstrap";
/** Access kind: a document READ or a document WRITE. */
export type AccessOp = "READ" | "WRITE";
@@ -63,7 +63,7 @@
import { sparqlUpdate, sparqlQuery } from "../surface/docs";
import { physicalCreate, physicalQuery, physicalUpdate } from "./physical";
import { getCaps, getCurrentUser, getStoreRegistryDeps } from "../polyfill";
import { getCaps, getCurrentUser, getStoreRegistryDeps } from "./bootstrap";
import { ensureRepoOpen } from "../emulated-verifier/open-repo";
import { ensurePhysicalRepoOpen, subscribePhysicalDoc } from "./physical";
import { escapeLiteral, escapeIri, assertNuri } from "../surface/sparql";
@@ -0,0 +1,228 @@
/**
* The injection store — where the consumer application plugs the real SDK in, and
* where the emulation keeps the state that only exists because one wallet hosts every
* identity: the injected `ng`/`useShape`, the registry dependencies, WHO is currently
* connected, and the `CapRegistry` singleton keyed by that holder.
*
* **NO COUNTERPART at any layer, by construction.** Upstream nothing is injected: the
* app imports the SDK, and "who am I" is the session — there is no current-user relay
* because a wallet has exactly one user. This module is the shape of that absence, so
* it belongs with the shared-wallet machinery and evaporates whole at migration.
*
* Extracted from `polyfill.ts` on 2026-08-03. Before that, every internal module
* imported the published ENTRY to reach the config, which made the entry a dependency
* of the code it publishes — cycles `polyfill` <-> `connect` and `polyfill` <-> `inbox`.
* The entry now only re-exports; the internals import this module instead.
*/
import type { NgLike, UseShapeLike, Nuri, PrincipalId, ReadCap } from "../model/types";
import type { RegistrySession } from "./account-registry";
import { CapRegistry } from "../emulated-verifier/caps";
import { setAccessLog } from "./access-log";
import { inspectOutbox } from "./outbox-log";
import { startConnect } from "../emulated-verifier/connect";
/**
* 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 an identity id
* 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<RegistrySession>;
/** Normalize an identity id for shim keying. Default: trim (identity-ish). */
normalizeId?: (id: string) => string;
/**
* POINTER micro-guard budget. The account records now live in a subscribable
* doc-shim (`did:ng:o:...`) reached through a well-known write-once POINTER triple
* in the store-root graph. The doc-shim read is barrier-AUTHORITATIVE, so accounts
* need NO retry (this replaces the deleted account-level `provisionRetry`). The
* ONLY residual sync-lag window is the store-root pointer read itself — one
* write-once triple. This bounded guard re-reads JUST that pointer a few times if a
* fresh cold read misses it; it can never provision or fork an account (worst case:
* a couple extra reads before an existing pointer is seen). Enable it where the REAL
* broker is used (app + e2e). Left UNSET (the default) → `attempts: 1` = single
* read, keeping the synchronous unit fakes fast and unchanged.
*/
pointerGuard?: { attempts?: number; baseMs?: number; maxStepMs?: number };
}
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;
/**
* Turn on the OFF-by-default document access log (see {@link ./access-log}):
* every real read/write is printed, prefixed by the active identity, to
* diagnose the shared-wallet isolation leak. Also enablable without a code
* change via the env var `NG_EVENTUALLY_ACCESS_LOG=1`. Default: false.
*/
debugAccessLog?: boolean;
/** 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;
/** Required fields of StoreRegistryDeps after defaults are applied. `pointerGuard`
* defaults to `{ attempts: 1 }` (single read) when the consumer leaves it unset. */
type ResolvedRegistryDeps = Required<
Pick<StoreRegistryDeps, "getSession" | "normalizeId" | "pointerGuard">
>;
let registryDeps: ResolvedRegistryDeps | null = null;
/**
* The map key of the current identity — deliberately NOT the raw id.
*
* A virtual user IS a shim account, and the shim keys accounts by the
* consumer-injected `normalizeId` ("@Alice" and "alice" are ONE account, with one
* set of scope documents). This record must key the same way, or a consumer that
* spells its own id differently between two calls gets a SECOND record and stops
* reading its own documents — the caps are filed under one spelling and looked up
* under the other. Falls back to the raw id while the registry deps are not yet
* configured (nothing can be filed before that anyway).
*/
function capsHolder(): PrincipalId | null {
if (currentUser === null) return null;
return registryDeps ? registryDeps.normalizeId(currentUser) : currentUser;
}
/**
* The emulated cap registry — one record PER identity (per virtual user),
* resolved through {@link capsHolder} on every call. So switching identity
* SWITCHES heldByHolder (nothing to reset, nothing wiped); see `caps.ts`. Empty until
* the first cap is issued, and while it is empty the read filter passes through
* (no regression).
*/
let caps = new CapRegistry(capsHolder);
export function configure(c: EventuallyConfig): void {
cfg = c;
currentUser = c.currentUser ?? null;
setAccessLog(c.debugAccessLog ?? false);
}
/** @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 + identity-id
* 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 {
// Fire the outbox inspection (Volet 3 of the low-level data-path trace) once,
// on the FIRST successful `getSession()` resolution — the most reliable
// "a session is established" signal available: every low-level reader/writer
// (store-registry, open-repo, read-model, subscribe, inbox) reaches its
// session through this SAME injected `getSession`, so wrapping it HERE catches
// the first success from whichever caller happens to run first, instead of
// tying the probe to one particular call site. Only on SUCCESS (an error
// propagates untouched, exactly as before) and only ONCE per
// `configureStoreRegistry()` call (a fresh session config → a fresh check).
let outboxInspected = false;
const getSession = async (): Promise<RegistrySession> => {
const session = await deps.getSession();
if (!outboxInspected) {
outboxInspected = true;
inspectOutbox();
}
return session;
};
registryDeps = {
getSession,
normalizeId: deps.normalizeId ?? ((id: string) => id.trim()),
// Default: single read (no re-read). Only the real-broker consumers (app + e2e)
// opt into the bounded pointer micro-guard; unit fakes stay synchronous.
pointerGuard: deps.pointerGuard ?? { attempts: 1 },
};
}
/** @internal — used by the storeRegistry to reach its injected dependencies. */
export function getStoreRegistryDeps(): ResolvedRegistryDeps {
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 identity id — who the SDK is reading/writing as. In the target
* this is the wallet user established at wallet-import time; here the consumer
* relays that id through this call so the read filter and the inbox `from` know
* who is acting. Passing `null` clears it (no identity yet, e.g. during startup).
*/
export function setCurrentUser(id: PrincipalId | null): void {
const changed = currentUser !== id;
currentUser = id;
// Connecting a user is what triggers inbox processing — the library's job, not
// the app's. Fire-and-forget: this setter is synchronous and every consumer calls
// it from synchronous code, so the work announces itself through the cap
// registry's change signal instead of making callers await. See `connect.ts`.
//
// Gated on the registry being configured, and that is not a test convenience: an
// identity set before the session resolves has nothing to restore and no inbox to
// reach, so firing would be I/O that can only fail. The consumer's real sequence
// is `configureStoreRegistry` then `setCurrentUser`; anything else can call
// `connectedUser()` explicitly.
if (changed && id !== null && registryDeps !== null) startConnect();
}
export function getCurrentUser(): PrincipalId | null {
return currentUser;
}
/** The emulated cap registry — what the current identity holds, plus the emulated
* public store. The read filter and the read-model consult it. */
export function getCaps(): CapRegistry {
return caps;
}
/**
* Do I hold the cap of `nuri`? — the held-caps lookup, the ONLY way a cap is
* obtained besides being given one. Returns `undefined` when what I hold has none;
* that is the whole answer the model can give (there is no "may P read D?").
*
* Shorthand for `getCaps().capFor(nuri)`, exposed because it is the surface the
* consumer actually uses.
*/
export function capFor(nuri: Nuri): ReadCap | undefined {
return caps.capFor(nuri);
}
/**
* Drop EVERY holder's caps (tests / a fresh wallet). This is **not** what an identity
* change does: switching identity switches heldByHolder, it never wipes one — if it
* wiped, durability would be a lie and per-session re-declaration would come back
* under another name. Nothing in the library calls this on `setCurrentUser`.
*/
export function resetCaps(): void {
// Clear IN PLACE rather than rebuilding: whoever subscribed to the registry's
// change signal (`watchShape`) stays subscribed to the live instance instead of
// silently holding a listener on an orphaned one.
caps.clear();
}
@@ -38,7 +38,7 @@
* split once each user opens their own wallet.
*/
import { getConfig } from "../polyfill";
import { getConfig } from "./bootstrap";
import { logAccess } from "./access-log";
import { subscribeDocUnguarded } from "../surface/subscribe";
import { openRepoUnguarded } from "../emulated-verifier/open-repo";
+1 -1
View File
@@ -13,7 +13,7 @@
* app's storeRegistry usage), so this is a drop-in for those raw calls.
*/
import { getCaps, getConfig } from "../polyfill";
import { getCaps, getConfig } from "../shared-wallet/bootstrap";
import { logAccess, enabled as accessLogEnabled } from "../shared-wallet/access-log";
import { isNuri } from "../model/nuri";
import { assertMayReach } from "../emulated-verifier/reach";
+1 -1
View File
@@ -29,7 +29,7 @@
import { depositInto, sparqlQuery } from "./docs";
import { subscribeDoc } from "./subscribe";
import { ensureRepoOpen } from "../emulated-verifier/open-repo";
import { getCaps, getCurrentUser, getStoreRegistryDeps } from "../polyfill";
import { getCaps, getCurrentUser, getStoreRegistryDeps } from "../shared-wallet/bootstrap";
import { addLink, documentInboxAddress, isOwnInbox } from "../shared-wallet/account-registry";
import { escapeLiteral } from "./sparql";
import { hasReadCap } from "../model/nuri";
+1 -1
View File
@@ -5,7 +5,7 @@
* a hook point later (e.g. opening the shared wallet on `init`).
*/
import { getConfig } from "../polyfill";
import { getConfig } from "../shared-wallet/bootstrap";
/** Forwards to the real `@ng-org/web` `init`. */
export function init(...args: any[]): any {
+1 -1
View File
@@ -4,7 +4,7 @@
* surface stays identical to `@ng-org/web`'s `ng`.
*/
import { getConfig, getCaps, getCurrentUser } from "../polyfill";
import { getConfig, getCaps, getCurrentUser } from "../shared-wallet/bootstrap";
import type { Nuri } from "../model/types";
export function makeNg(): Record<string, any> {
+1 -1
View File
@@ -42,7 +42,7 @@
*/
import { docCreate, sparqlUpdate, sparqlQuery } from "./docs";
import { getCaps, getStoreRegistryDeps } from "../polyfill";
import { getCaps, getStoreRegistryDeps } from "../shared-wallet/bootstrap";
import { mustNotAttempt } from "../emulated-verifier/reach";
import { ensureReposOpen } from "../emulated-verifier/open-repo";
import { assertNuri } from "./sparql";
+1 -1
View File
@@ -33,7 +33,7 @@
* builds a set of these with per-doc error isolation to preserve that property.
*/
import { getConfig, getStoreRegistryDeps } from "../polyfill";
import { getConfig, getStoreRegistryDeps } from "../shared-wallet/bootstrap";
import { assertMayReach } from "../emulated-verifier/reach";
import type { Nuri } from "../model/types";
+1 -1
View File
@@ -6,7 +6,7 @@
* only delivers documents whose cap the wallet holds.
*/
import { getConfig, getCaps } from "../polyfill";
import { getConfig, getCaps } from "../shared-wallet/bootstrap";
import { makeReadFilteredView } from "../emulated-verifier/read-filter";
export function useShape(shapeType: unknown, scope: unknown): unknown {
+1 -1
View File
@@ -51,7 +51,7 @@
* `isError` fires ONLY on a real thrown exception in the pipeline.
*/
import { getCaps, getCurrentUser } from "../polyfill";
import { getCaps, getCurrentUser } from "../shared-wallet/bootstrap";
import { ensureReposOpen, getSyncState } from "../emulated-verifier/open-repo";
import { readUnion, type UnionSubject } from "./read-model";
import { subscribeDoc, type Unsubscribe } from "./subscribe";