feat!: useShapeQuery lit par la requete de forme du SDK

This commit is contained in:
Sylvain Duchesne
2026-09-21 11:41:31 +02:00
parent a5e553e65b
commit 77e78ec81d
29 changed files with 1190 additions and 971 deletions
+37 -5
View File
@@ -37,6 +37,7 @@ import {
readUnion,
storeRegistry,
subscribeDoc,
initNg as initNgSignals,
useShapeQuery,
type Nuri,
type ShapeObservable,
@@ -44,6 +45,10 @@ import {
configure,
} from "@ng-eventually/polyfill";
import { ng as realNg, init as realInit } from "@ng-org/web";
// The SDK's shape query, which `useShapeQuery` reads through since `1.0.0-dev.6`, and
// the call that hands the ORM its session. Both are handed to `configure` below, the
// same way the `ng` is: this package never imports the SDK itself.
import { initNg as ormInitNg, RdfOrmSubscription } from "@ng-org/orm";
// --- the domain, such as it is ---------------------------------------------
@@ -91,6 +96,23 @@ const NoteShape = {
maxCardinality: 1,
dataTypes: [{ literals: [NOTE], valType: "iri" }],
},
// The two fields a note actually carries. A shape declares what comes BACK as
// well as what matches: a predicate the shape does not name is not projected onto
// the object, so leaving these out would return notes with no title and no body.
{
iri: TITLE,
readablePredicate: "title",
minCardinality: 1,
maxCardinality: 1,
dataTypes: [{ valType: "string" }],
},
{
iri: BODY,
readablePredicate: "body",
minCardinality: 1,
maxCardinality: 1,
dataTypes: [{ valType: "string" }],
},
],
},
},
@@ -104,8 +126,10 @@ const NoteShape = {
configure({
ng: realNg,
useShape: (() => {}) as never, // `useShapeQuery` and `readUnion` do not go through the ORM hook
useShape: (() => {}) as never, // this app reads through `useShapeQuery`, never the hook
ormSubscription: RdfOrmSubscription.getOrCreate,
init: realInit,
initNg: ormInitNg,
sharedWallet: {
fileUrl: "/shared-wallet.ngw",
password: (globalThis as { __NOTEBOOK_WALLET_PASSWORD__?: string }).__NOTEBOOK_WALLET_PASSWORD__ ?? "",
@@ -125,7 +149,13 @@ configure({
// is only what this app itself reads.
const sessionReady = new Promise<{ session_id: string }>((resolve) => {
init((event: { status: string; session?: { session_id: string } }) => {
if (event.status === "loggedin" && event.session) resolve(event.session);
if (event.status === "loggedin" && event.session) {
// The ORM reaches the SDK through a module-level promise of its own; nothing it
// opens starts before this. Through the library's `initNg`, which is the SDK-shaped
// call and survives migration.
initNgSignals(realNg, event.session);
resolve(event.session);
}
}, true, []);
});
@@ -185,9 +215,11 @@ function currentNotes(): Note[] {
return noteQuery()
.getSnapshot()
.data.map((s) => ({
doc: s.graph,
title: s.props[TITLE]?.[0] ?? "(sans titre)",
body: s.props[BODY]?.[0] ?? "",
// The read hands back the SHAPE's own objects now, not property bags: `@graph` is
// the document a note lives in, and each field is the predicate's readable name.
doc: s["@graph"] as Nuri,
title: typeof s.title === "string" ? s.title : "(sans titre)",
body: typeof s.body === "string" ? s.body : "",
}));
}
+2 -1
View File
@@ -5,6 +5,7 @@
"description": "A minimal application written against @ng-eventually/polyfill \u2014 the library's usage example, and what the e2e suite drives.",
"dependencies": {
"@ng-eventually/polyfill": "workspace:*",
"@ng-org/web": "0.1.2-alpha.13"
"@ng-org/orm": "0.1.2-alpha.21",
"@ng-org/web": "0.1.2-alpha.14"
}
}