feat!: useShapeQuery lit par la requete de forme du SDK
This commit is contained in:
@@ -15,6 +15,11 @@
|
||||
*/
|
||||
|
||||
import { ng as realNg, init as realInit } from "@ng-org/web";
|
||||
// The REAL ORM. `useShapeQuery` reads through the SDK's own shape query since
|
||||
// `1.0.0-dev.6`, so the harness has to hand it one: a fake Set-like is enough for the
|
||||
// read FILTER (which is pure) and says nothing about a read that reaches the broker.
|
||||
// `initNg` is what resolves the ORM's own session promise; nothing starts before it.
|
||||
import { initNg as ormInitNg, RdfOrmSubscription } from "@ng-org/orm";
|
||||
import {
|
||||
configure,
|
||||
docs,
|
||||
@@ -26,6 +31,7 @@ import {
|
||||
storeRegistry,
|
||||
useShape as libUseShape,
|
||||
useShapeQuery,
|
||||
initNg,
|
||||
} from "@ng-eventually/polyfill";
|
||||
// The harness tests the LIBRARY, so it legitimately reaches machinery a consumer
|
||||
// application must not — but through the internal path, never the published entry.
|
||||
@@ -60,13 +66,50 @@ import { isNuri } from "../src/model/nuri";
|
||||
/** The whole local dataset - upstream's own marker, what `""` normalises to. */
|
||||
const EVERYTHING = { graphs: "did:ng:i" };
|
||||
|
||||
/**
|
||||
* The shape the two `useShapeQuery` journeys read - built here rather than inline, since
|
||||
* both of them need the same one and it is now handed to the SDK.
|
||||
*
|
||||
* Two predicates, both `minCardinality: 1`, because that is what
|
||||
* `engine/verifier/src/orm/graph/query.rs:schema_shape_to_sparql` turns into REQUIRED
|
||||
* triple patterns: a shape constraining nothing would match every subject in the dataset.
|
||||
* The title is the second one, and it is what proves the real data landed rather than an
|
||||
* empty object of the right type.
|
||||
*/
|
||||
function wsShape(cls: string) {
|
||||
return {
|
||||
shape: "urn:e2e:ws:Shape",
|
||||
schema: {
|
||||
"urn:e2e:ws:Shape": {
|
||||
iri: "urn:e2e:ws:Shape",
|
||||
predicates: [
|
||||
{
|
||||
iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
||||
readablePredicate: "type",
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
dataTypes: [{ literals: [cls], valType: "iri" }],
|
||||
},
|
||||
{
|
||||
iri: "urn:e2e:ws:title",
|
||||
readablePredicate: "title",
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
dataTypes: [{ valType: "string" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
} satisfies ShapeType<BaseType>;
|
||||
}
|
||||
|
||||
const storeOfType = (t: "public" | "protected" | "private"): Promise<Nuri> =>
|
||||
t === "public"
|
||||
? storeRegistry.publicStore()
|
||||
: t === "protected"
|
||||
? storeRegistry.protectedStore()
|
||||
: storeRegistry.privateStore();
|
||||
import type { Nuri, ShapeObservable, ShapeQuery } from "@ng-eventually/polyfill";
|
||||
import type { BaseType, Nuri, ShapeObservable, ShapeQuery, ShapeType } from "@ng-eventually/polyfill";
|
||||
|
||||
const { IdentityStore } = virtualUsers;
|
||||
|
||||
@@ -120,7 +163,12 @@ function fakeUseShape(_shape: unknown, _scope: unknown): any {
|
||||
configure({
|
||||
ng: realNg,
|
||||
useShape: fakeUseShape,
|
||||
// The SDK's own shape query, passed as it stands - no wrapper, no cast. This is what
|
||||
// `useShapeQuery` reads through, so the journeys below run against the REAL broker
|
||||
// rather than against anything this page composed.
|
||||
ormSubscription: RdfOrmSubscription.getOrCreate,
|
||||
init: realInit,
|
||||
initNg: ormInitNg,
|
||||
// The harness already holds an open wallet (the suite imports it itself), so it never
|
||||
// needs the gate's assisted import. These values exist only so the gate has something
|
||||
// to render when the access-gate steps exercise it — they are never used to import.
|
||||
@@ -794,9 +842,9 @@ const identity = new IdentityStore(
|
||||
},
|
||||
|
||||
// ── useShapeQuery (reactive useQuery-shaped read) ────────────────────────
|
||||
// A minimal SHEX-ish ShapeType pinning rdf:type to an e2e class IRI. useShapeQuery
|
||||
// reads only `.shape`/`.schema[...].predicates[rdf:type].dataTypes[].literals`
|
||||
// to know which @type to keep — generic, no application domain.
|
||||
// The shape is `wsShape(cls)` above: a hand-written `ShapeType`, two required
|
||||
// predicates, generic and with no application domain. The read goes through the
|
||||
// SDK's own shape query now, so these two journeys measure the REAL broker.
|
||||
_wsProbes: {} as Record<
|
||||
string,
|
||||
{ obs: ShapeObservable; initial: ShapeQuery; unsub: () => void }
|
||||
@@ -828,23 +876,7 @@ const identity = new IdentityStore(
|
||||
if (listed.includes(doc)) break;
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
}
|
||||
const shape = {
|
||||
shape: "urn:e2e:ws:Shape",
|
||||
schema: {
|
||||
"urn:e2e:ws:Shape": {
|
||||
iri: "urn:e2e:ws:Shape",
|
||||
predicates: [
|
||||
{
|
||||
iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
||||
readablePredicate: "type",
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
dataTypes: [{ literals: [cls], valType: "iri" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const shape = wsShape(cls);
|
||||
const obs = useShapeQuery(shape, EVERYTHING) as ShapeObservable;
|
||||
const unsub = obs.subscribe(() => {});
|
||||
// First snapshot immediately after subscribe — the barrier is not yet crossed
|
||||
@@ -866,8 +898,10 @@ const identity = new IdentityStore(
|
||||
isSuccess: snap.isSuccess,
|
||||
isError: snap.isError,
|
||||
dataLen: snap.data.length,
|
||||
// The seeded title, if the datum is present (proves the real data landed).
|
||||
titles: snap.data.flatMap((d: any) => d.props?.["urn:e2e:ws:title"] ?? []),
|
||||
// The seeded title, if the datum is present (proves the real data landed). It is the
|
||||
// shape's own readable predicate now, not a property bag: the objects come from the
|
||||
// ORM.
|
||||
titles: snap.data.map((d) => d.title).filter((v) => typeof v === "string"),
|
||||
};
|
||||
},
|
||||
useShapeQueryStop(handle: string) {
|
||||
@@ -884,23 +918,7 @@ const identity = new IdentityStore(
|
||||
registryInternals.resetRegistryCache();
|
||||
const id = "@ws-empty-" + handle;
|
||||
setCurrentUser(id);
|
||||
const shape = {
|
||||
shape: "urn:e2e:ws:Shape",
|
||||
schema: {
|
||||
"urn:e2e:ws:Shape": {
|
||||
iri: "urn:e2e:ws:Shape",
|
||||
predicates: [
|
||||
{
|
||||
iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
||||
readablePredicate: "type",
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
dataTypes: [{ literals: [cls], valType: "iri" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const shape = wsShape(cls);
|
||||
const obs = useShapeQuery(shape, EVERYTHING) as ShapeObservable;
|
||||
const unsub = obs.subscribe(() => {});
|
||||
const initial = obs.getSnapshot();
|
||||
@@ -1105,6 +1123,11 @@ const identity = new IdentityStore(
|
||||
(event: { session: BrokerSession }) => {
|
||||
session = event.session;
|
||||
state.status = "connected";
|
||||
// The ORM reaches the SDK through a module-level promise of its own, resolved
|
||||
// once. Nothing it opens starts before this, so it goes here rather than beside
|
||||
// the first read - through the PACKAGE's `initNg`, which is the call an
|
||||
// application makes.
|
||||
initNg(realNg, session);
|
||||
sessionResolve(session);
|
||||
},
|
||||
true,
|
||||
|
||||
Reference in New Issue
Block a user