/** * The wrapped `ng`: a Proxy that forwards every method to the real SDK and * overrides only what the broker/verifier will do natively at migration. The * surface stays identical to `@ng-org/web`'s `ng`. */ import { getConfig, getCaps, getCurrentUser } from "./polyfill"; import type { Nuri } from "./types"; export function makeNg(): Record { return new Proxy({} as Record, { get(_target, prop: string) { const { ng } = getConfig(); // login / session_start → open the SHARED wallet invisibly. if (prop === "login" || prop === "session_start") { return (...args: any[]) => { // TODO(polyfill): supply shared-wallet credentials so no wallet UI // is shown. For now, passthrough. return ng[prop]!(...args); }; } // sparql_update → write guard (emulated write-cap check). // Mirrors the target broker/verifier: a write is refused unless the wallet // holds the document's WRITE cap. Emulated per-document via CapRegistry. // args = (session_id, query, anchor?) — `anchor` is the target doc NURI. if (prop === "sparql_update") { return (...args: any[]) => { const anchor = args[2] as Nuri | undefined; const caps = getCaps(); // Passthrough (no regression) unless a WRITE policy exists AND this // specific document is governed by it. Ungoverned docs (mono-store // default, no cap declared) flow through exactly as before. if ( typeof anchor === "string" && caps.hasWritePolicy() && caps.governsWrite(anchor) && !caps.canWrite(anchor, getCurrentUser()) ) { return Promise.reject( new Error( `[ng-eventually] write denied: current user lacks the write cap for ${anchor}`, ), ); } return ng.sparql_update!(...args); }; } // TODO(anticipated API): inbox_post_link + capability operations — expose // here with their anticipated signatures, emulated for now. // Everything else: passthrough to the real SDK, unchanged. const real = ng[prop]; return typeof real === "function" ? real.bind(ng) : real; }, }); }