feat(client): generic shared-wallet shim surface (docs/storeRegistry/isolation/accounts)
Port the shared-wallet shim mechanics from the Festipod app into the
generic @ng-eventually/client library — zero app-specific knowledge, the
consumer injects the domain (entity->scope mapping, connections, storage).
New namespaces exposed from src/index.ts:
- docs docCreate/sparqlUpdate/sparqlQuery via the REAL injected `ng`
(getConfig().ng), never the public makeNg proxy — the JS-over-
iframe double proxy breaks doc_create postMessage marshaling
(DataCloneError). Validated hard constraint.
- storeRegistry generic (account,scope)->NURI resolver, createEntityDoc/
listEntityDocs + per-scope index, sharedWalletShim in the
private_store, cache. Consumer wiring injected via
configureStoreRegistry({ getSession, normalizeUser }).
- isolation pure applyIsolation (public=all / protected=owner+connections
/ private=owner); accessors + connection graph injected.
- accounts AccountStore (localStorage-backed faux login, storage injected)
+ normalizeUsername. React wrapper intentionally NOT ported.
polyfill.ts gains configureStoreRegistry/getStoreRegistryDeps + resetConfig.
36/36 bun test, tsc --noEmit rc=0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Low-level document + SPARQL primitives.
|
||||
*
|
||||
* These call the **REAL injected `ng`** (`getConfig().ng`) DIRECTLY — never the
|
||||
* public `ng` proxy (`makeNg`). This is a validated hard constraint, NOT a style
|
||||
* choice: the public `ng` is a JS `Proxy` over `@ng-org/web`'s iframe-RPC proxy,
|
||||
* and layering our Proxy on top breaks `doc_create`'s `postMessage` marshaling
|
||||
* (`DataCloneError: function ... could not be cloned`). Reaching the real `ng`
|
||||
* held in the config avoids the double-proxy. Do NOT import from `./ng-proxy`.
|
||||
*
|
||||
* Signatures mirror the real `@ng-org/web` `ng` surface (verified against the
|
||||
* app's storeRegistry usage), so this is a drop-in for those raw calls.
|
||||
*/
|
||||
|
||||
import { getConfig } from "./polyfill";
|
||||
import type { Nuri } from "./types";
|
||||
|
||||
/**
|
||||
* Create one document → its NURI.
|
||||
*
|
||||
* Mirrors `ng.doc_create(session_id, crdt, cls, dest, store_repo?)`. For a graph
|
||||
* document in the (shared) private store: `docCreate(sid, "Graph", "data:graph",
|
||||
* "store")` (store_repo left undefined → private store).
|
||||
*/
|
||||
export async function docCreate(
|
||||
sessionId: string,
|
||||
crdt: string,
|
||||
cls: string,
|
||||
dest: string,
|
||||
store?: unknown,
|
||||
): Promise<Nuri> {
|
||||
const { ng } = getConfig();
|
||||
return ng.doc_create(sessionId, crdt, cls, dest, store);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a SPARQL UPDATE (INSERT/DELETE DATA, etc.).
|
||||
*
|
||||
* Mirrors `ng.sparql_update(session_id, query, anchor?)`, where `anchor` is the
|
||||
* document NURI the update is scoped/base'd to (optional).
|
||||
*/
|
||||
export async function sparqlUpdate(
|
||||
sessionId: string,
|
||||
query: string,
|
||||
anchor?: Nuri,
|
||||
): Promise<void> {
|
||||
const { ng } = getConfig();
|
||||
return ng.sparql_update(sessionId, query, anchor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a SPARQL SELECT/CONSTRUCT/ASK query → the raw SDK result.
|
||||
*
|
||||
* Mirrors `ng.sparql_query(session_id, query, base?, anchor?)`. `base` is the
|
||||
* query base IRI (usually `undefined`); `anchor` is the document NURI to query.
|
||||
*/
|
||||
export async function sparqlQuery(
|
||||
sessionId: string,
|
||||
query: string,
|
||||
base?: string,
|
||||
anchor?: Nuri,
|
||||
): Promise<unknown> {
|
||||
const { ng } = getConfig();
|
||||
return ng.sparql_query(sessionId, query, base, anchor);
|
||||
}
|
||||
Reference in New Issue
Block a user