Persist the meeting point, and absorb the prefix the generator drops
The meeting point is the product's unit of value and had no shape at all: it lived in React state, lost on reload. The shape comes from the sibling branch rather than from my own reading of the domain -- event, host, title, optional description/place/time, and the optional inbox its own backend will want. Regenerating the bindings does what that branch documented it would: the emitted names lose the Fp prefix, because they follow each shape's IRI and those IRIs are the persisted RDF classes, not ours to rename. So the aliasing happens at the four import sites, which keeps every downstream name unchanged and stops the DOM's own Event from being shadowed. The generated files are never edited; build:orm overwrites them. I had called this blocked, as "a binding with no consumer". That was wrong and worth correcting: the shape and the bindings are the PREREQUISITE every NextGraph-flavoured backend needs, and only the RecordBinding waits for one. The RecordBindings slot stays optional until a backend can fill it. Still local-only in the data context: persisting a meeting point needs a backend to write it through, and the registry is empty.
This commit is contained in:
@@ -28,13 +28,22 @@ import { useBackend } from '../refine/RefineProvider';
|
||||
// custom vars, so a bare `process.env.FESTIPOD_MULTISTORE` throws
|
||||
// "process is not defined" in the browser harness. Guard it.
|
||||
const MULTISTORE = typeof process !== 'undefined' && process?.env?.FESTIPOD_MULTISTORE === '1';
|
||||
// `FpEventShapeType` is NOT imported here any more: events go through Refine, and
|
||||
// the resource → shape binding lives in refine/shapeTypes.ts.
|
||||
import {
|
||||
FpUserProfileShapeType,
|
||||
FpParticipationShapeType,
|
||||
} from '../shapes/orm/festipodShapes.shapeTypes';
|
||||
import type { FpEvent, FpUserProfile, FpParticipation } from '../shapes/orm/festipodShapes.typings';
|
||||
// NO ShapeType IMPORTED HERE ANY MORE: every entity reads through a Refine
|
||||
// backend, and the resource → shape binding is the backend's business.
|
||||
// The ORM generator emits BARE shape names (`Event`, `UserProfile`, …), taken from
|
||||
// each shape's IRI local name. They are aliased back to the `Fp*` spelling HERE,
|
||||
// at the import, so nothing downstream depends on the generator's naming: `Event`
|
||||
// is a DOM global, and the bare names collide with the app's own vocabulary
|
||||
// (`FpEventData` & co.). The prefix cannot be restored at the generator — the
|
||||
// emitted name follows the shape IRI, and those IRIs are the persisted RDF
|
||||
// classes, not ours to rename. Never edit the generated files; `build:orm`
|
||||
// overwrites them.
|
||||
import type {
|
||||
Event as FpEvent,
|
||||
MeetingPoint as FpMeetingPoint,
|
||||
Participation as FpParticipation,
|
||||
UserProfile as FpUserProfile,
|
||||
} from '../shapes/orm/festipodShapes.typings';
|
||||
import { bootstrapWallet, type BootstrapResult } from '../utils/ngBootstrap';
|
||||
import { autoSeedEnabled, shouldAutoSeed } from '../utils/autoSeed';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { Schema } from "@ng-org/shex-orm";
|
||||
* festipodShapesSchema: Schema for festipodShapes
|
||||
* =============================================================================
|
||||
*/
|
||||
export const festipodShapesSchema: Schema = {
|
||||
export const festipodShapesSchema = {
|
||||
"http://festipod.org/Event": {
|
||||
iri: "http://festipod.org/Event",
|
||||
predicates: [
|
||||
@@ -22,63 +22,99 @@ export const festipodShapesSchema: Schema = {
|
||||
readablePredicate: "@type",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/title",
|
||||
readablePredicate: "title",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/description",
|
||||
readablePredicate: "description",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/date",
|
||||
readablePredicate: "date",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/location",
|
||||
readablePredicate: "location",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "number" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "number",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/distance",
|
||||
readablePredicate: "distance",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "number" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "number",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/participantCount",
|
||||
readablePredicate: "participantCount",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/coverImage",
|
||||
readablePredicate: "coverImage",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/hostName",
|
||||
readablePredicate: "hostName",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/hostInitials",
|
||||
@@ -102,35 +138,55 @@ export const festipodShapesSchema: Schema = {
|
||||
readablePredicate: "@type",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/name",
|
||||
readablePredicate: "name",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/initials",
|
||||
readablePredicate: "initials",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/username",
|
||||
readablePredicate: "username",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "string" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/role",
|
||||
readablePredicate: "role",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "boolean" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "boolean",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/isPublic",
|
||||
@@ -154,21 +210,33 @@ export const festipodShapesSchema: Schema = {
|
||||
readablePredicate: "@type",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "iri" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/event",
|
||||
readablePredicate: "event",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "iri" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/user",
|
||||
readablePredicate: "user",
|
||||
},
|
||||
{
|
||||
dataTypes: [{ valType: "boolean" }],
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "boolean",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/isConfirmed",
|
||||
@@ -176,4 +244,98 @@ export const festipodShapesSchema: Schema = {
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
"http://festipod.org/MeetingPoint": {
|
||||
iri: "http://festipod.org/MeetingPoint",
|
||||
predicates: [
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
literals: ["http://festipod.org/MeetingPoint"],
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
||||
readablePredicate: "@type",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/event",
|
||||
readablePredicate: "event",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "iri",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/host",
|
||||
readablePredicate: "host",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 1,
|
||||
iri: "http://festipod.org/title",
|
||||
readablePredicate: "title",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/description",
|
||||
readablePredicate: "description",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/place",
|
||||
readablePredicate: "place",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/time",
|
||||
readablePredicate: "time",
|
||||
},
|
||||
{
|
||||
dataTypes: [
|
||||
{
|
||||
valType: "string",
|
||||
},
|
||||
],
|
||||
maxCardinality: 1,
|
||||
minCardinality: 0,
|
||||
iri: "http://festipod.org/inbox",
|
||||
readablePredicate: "inbox",
|
||||
},
|
||||
],
|
||||
},
|
||||
} as const satisfies Schema;
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
import type { ShapeType } from "@ng-org/shex-orm";
|
||||
import { festipodShapesSchema } from "./festipodShapes.schema";
|
||||
import type { FpEvent, FpUserProfile, FpParticipation } from "./festipodShapes.typings";
|
||||
import { festipodShapesSchema } from "./festipodShapes.schema.ts";
|
||||
import type {
|
||||
Event,
|
||||
UserProfile,
|
||||
Participation,
|
||||
MeetingPoint,
|
||||
} from "./festipodShapes.typings.ts";
|
||||
|
||||
// ShapeTypes for festipodShapes
|
||||
export const FpEventShapeType: ShapeType<FpEvent> = {
|
||||
|
||||
export const EventShapeType: ShapeType<Event> = {
|
||||
schema: festipodShapesSchema,
|
||||
shape: "http://festipod.org/Event",
|
||||
};
|
||||
export const FpUserProfileShapeType: ShapeType<FpUserProfile> = {
|
||||
|
||||
export const UserProfileShapeType: ShapeType<UserProfile> = {
|
||||
schema: festipodShapesSchema,
|
||||
shape: "http://festipod.org/UserProfile",
|
||||
};
|
||||
export const FpParticipationShapeType: ShapeType<FpParticipation> = {
|
||||
|
||||
export const ParticipationShapeType: ShapeType<Participation> = {
|
||||
schema: festipodShapesSchema,
|
||||
shape: "http://festipod.org/Participation",
|
||||
};
|
||||
|
||||
export const MeetingPointShapeType: ShapeType<MeetingPoint> = {
|
||||
schema: festipodShapesSchema,
|
||||
shape: "http://festipod.org/MeetingPoint",
|
||||
};
|
||||
|
||||
@@ -9,9 +9,9 @@ export type IRI = string;
|
||||
/**
|
||||
* Event Type
|
||||
*/
|
||||
export interface FpEvent {
|
||||
export interface Event {
|
||||
/**
|
||||
* The graph IRI.
|
||||
* The graph NURI.
|
||||
*/
|
||||
readonly "@graph": IRI;
|
||||
/**
|
||||
@@ -81,9 +81,9 @@ export interface FpEvent {
|
||||
/**
|
||||
* UserProfile Type
|
||||
*/
|
||||
export interface FpUserProfile {
|
||||
export interface UserProfile {
|
||||
/**
|
||||
* The graph IRI.
|
||||
* The graph NURI.
|
||||
*/
|
||||
readonly "@graph": IRI;
|
||||
/**
|
||||
@@ -129,9 +129,9 @@ export interface FpUserProfile {
|
||||
/**
|
||||
* Participation Type
|
||||
*/
|
||||
export interface FpParticipation {
|
||||
export interface Participation {
|
||||
/**
|
||||
* The graph IRI.
|
||||
* The graph NURI.
|
||||
*/
|
||||
readonly "@graph": IRI;
|
||||
/**
|
||||
@@ -161,3 +161,63 @@ export interface FpParticipation {
|
||||
*/
|
||||
isConfirmed: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* MeetingPoint Type
|
||||
*/
|
||||
export interface MeetingPoint {
|
||||
/**
|
||||
* The graph NURI.
|
||||
*/
|
||||
readonly "@graph": IRI;
|
||||
/**
|
||||
* The subject IRI.
|
||||
*/
|
||||
readonly "@id": IRI;
|
||||
/**
|
||||
* Original IRI: http://www.w3.org/1999/02/22-rdf-syntax-ns#type
|
||||
*/
|
||||
"@type": "http://festipod.org/MeetingPoint";
|
||||
/**
|
||||
* Reference to the public event this meeting point is anchored to
|
||||
*
|
||||
* Original IRI: http://festipod.org/event
|
||||
*/
|
||||
event: IRI;
|
||||
/**
|
||||
* Reference to the user hosting the meeting point
|
||||
*
|
||||
* Original IRI: http://festipod.org/host
|
||||
*/
|
||||
host: IRI;
|
||||
/**
|
||||
* The title of the meeting point
|
||||
*
|
||||
* Original IRI: http://festipod.org/title
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* A description of the meeting point
|
||||
*
|
||||
* Original IRI: http://festipod.org/description
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* Where participants gather (e.g. 'Entrée principale, sous l'horloge')
|
||||
*
|
||||
* Original IRI: http://festipod.org/place
|
||||
*/
|
||||
place?: string;
|
||||
/**
|
||||
* When participants gather (display string)
|
||||
*
|
||||
* Original IRI: http://festipod.org/time
|
||||
*/
|
||||
time?: string;
|
||||
/**
|
||||
* NURI of the meeting point's inbox (wired in T02.b/c)
|
||||
*
|
||||
* Original IRI: http://festipod.org/inbox
|
||||
*/
|
||||
inbox?: string;
|
||||
}
|
||||
|
||||
@@ -47,3 +47,21 @@ fp:Participation {
|
||||
fp:isConfirmed xsd:boolean
|
||||
// rdfs:comment "Whether the participation is confirmed" ;
|
||||
}
|
||||
|
||||
fp:MeetingPoint {
|
||||
a [fp:MeetingPoint] ;
|
||||
fp:event IRI
|
||||
// rdfs:comment "Reference to the public event this meeting point is anchored to" ;
|
||||
fp:host IRI
|
||||
// rdfs:comment "Reference to the user hosting the meeting point" ;
|
||||
fp:title xsd:string
|
||||
// rdfs:comment "The title of the meeting point" ;
|
||||
fp:description xsd:string ?
|
||||
// rdfs:comment "A description of the meeting point" ;
|
||||
fp:place xsd:string ?
|
||||
// rdfs:comment "Where participants gather (e.g. 'Entrée principale, sous l'horloge')" ;
|
||||
fp:time xsd:string ?
|
||||
// rdfs:comment "When participants gather (display string)" ;
|
||||
fp:inbox xsd:string ?
|
||||
// rdfs:comment "NURI of the meeting point's inbox (wired in T02.b/c)" ;
|
||||
}
|
||||
|
||||
@@ -17,11 +17,16 @@ import { useShapeSet, useShapeSubscription } from '../hooks/useShapeSet';
|
||||
import { ng } from '@ng-org/web';
|
||||
import type { DeepSignalSet } from '@ng-org/alien-deepsignals';
|
||||
import {
|
||||
FpEventShapeType,
|
||||
FpUserProfileShapeType,
|
||||
FpParticipationShapeType,
|
||||
EventShapeType as FpEventShapeType,
|
||||
ParticipationShapeType as FpParticipationShapeType,
|
||||
UserProfileShapeType as FpUserProfileShapeType,
|
||||
} from '../shapes/orm/festipodShapes.shapeTypes';
|
||||
import type { FpEvent, FpUserProfile, FpParticipation } from '../shapes/orm/festipodShapes.typings';
|
||||
import type {
|
||||
Event as FpEvent,
|
||||
MeetingPoint as FpMeetingPoint,
|
||||
Participation as FpParticipation,
|
||||
UserProfile as FpUserProfile,
|
||||
} from '../shapes/orm/festipodShapes.typings';
|
||||
import { seedEvents, seedUsers, seedParticipations } from '../data/seedData';
|
||||
import { ensureGraphNuri } from '../utils/ngGraph';
|
||||
|
||||
|
||||
@@ -12,7 +12,12 @@ import React, { useEffect, useRef } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { deepSignal } from '@ng-org/alien-deepsignals';
|
||||
import type { DeepSignalSet } from '@ng-org/alien-deepsignals';
|
||||
import type { FpEvent, FpUserProfile, FpParticipation } from '../shapes/orm/festipodShapes.typings';
|
||||
import type {
|
||||
Event as FpEvent,
|
||||
MeetingPoint as FpMeetingPoint,
|
||||
Participation as FpParticipation,
|
||||
UserProfile as FpUserProfile,
|
||||
} from '../shapes/orm/festipodShapes.typings';
|
||||
|
||||
// ============================================================================
|
||||
// Seed data — same events/users as the app's seedData.ts
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
* module runs outside the component tree.
|
||||
*/
|
||||
|
||||
import type { FpEvent, FpUserProfile } from '../shapes/orm/festipodShapes.typings';
|
||||
import type {
|
||||
Event as FpEvent,
|
||||
UserProfile as FpUserProfile,
|
||||
} from '../shapes/orm/festipodShapes.typings';
|
||||
import type { FpEventData, FpUserData } from '../data/types';
|
||||
import { seedEvents, seedUsers } from '../data/seedData';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user