@_linked/core 2.33.0 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +26 -0
- package/lib/esm/index.d.ts +2 -1
- package/lib/esm/index.js +2 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/live/LiveQueryStore.d.ts +22 -0
- package/lib/esm/live/LiveQueryStore.js +86 -19
- package/lib/esm/live/LiveQueryStore.js.map +1 -1
- package/lib/esm/live/changes.d.ts +9 -1
- package/lib/esm/live/changes.js +7 -2
- package/lib/esm/live/changes.js.map +1 -1
- package/lib/esm/live/keys.d.ts +6 -0
- package/lib/esm/live/keys.js +10 -1
- package/lib/esm/live/keys.js.map +1 -1
- package/lib/esm/live/matcher.d.ts +4 -1
- package/lib/esm/live/matcher.js +10 -5
- package/lib/esm/live/matcher.js.map +1 -1
- package/lib/esm/queries/AskBuilder.d.ts +6 -0
- package/lib/esm/queries/AskBuilder.js +14 -0
- package/lib/esm/queries/AskBuilder.js.map +1 -1
- package/lib/esm/queries/CountBuilder.d.ts +6 -0
- package/lib/esm/queries/CountBuilder.js +14 -0
- package/lib/esm/queries/CountBuilder.js.map +1 -1
- package/lib/esm/queries/CreateBuilder.d.ts +4 -0
- package/lib/esm/queries/CreateBuilder.js +15 -1
- package/lib/esm/queries/CreateBuilder.js.map +1 -1
- package/lib/esm/queries/DeleteBuilder.d.ts +4 -0
- package/lib/esm/queries/DeleteBuilder.js +15 -1
- package/lib/esm/queries/DeleteBuilder.js.map +1 -1
- package/lib/esm/queries/FieldSet.d.ts +10 -0
- package/lib/esm/queries/FieldSet.js +85 -18
- package/lib/esm/queries/FieldSet.js.map +1 -1
- package/lib/esm/queries/IRLower.js +3 -2
- package/lib/esm/queries/IRLower.js.map +1 -1
- package/lib/esm/queries/IRMutation.js +15 -14
- package/lib/esm/queries/IRMutation.js.map +1 -1
- package/lib/esm/queries/MutationSerialization.js +2 -2
- package/lib/esm/queries/MutationSerialization.js.map +1 -1
- package/lib/esm/queries/PropertyPath.js +2 -2
- package/lib/esm/queries/PropertyPath.js.map +1 -1
- package/lib/esm/queries/QueryBuilder.d.ts +7 -0
- package/lib/esm/queries/QueryBuilder.js +40 -3
- package/lib/esm/queries/QueryBuilder.js.map +1 -1
- package/lib/esm/queries/SelectQuery.js +2 -2
- package/lib/esm/queries/SelectQuery.js.map +1 -1
- package/lib/esm/queries/UpdateBuilder.d.ts +4 -0
- package/lib/esm/queries/UpdateBuilder.js +15 -1
- package/lib/esm/queries/UpdateBuilder.js.map +1 -1
- package/lib/esm/queries/fromJSON.d.ts +12 -1
- package/lib/esm/queries/fromJSON.js +5 -1
- package/lib/esm/queries/fromJSON.js.map +1 -1
- package/lib/esm/queries/lower.js +12 -5
- package/lib/esm/queries/lower.js.map +1 -1
- package/lib/esm/queries/queryDependencies.js +14 -10
- package/lib/esm/queries/queryDependencies.js.map +1 -1
- package/lib/esm/queries/resolveShape.js +14 -2
- package/lib/esm/queries/resolveShape.js.map +1 -1
- package/lib/esm/shapes/Shape.js +2 -1
- package/lib/esm/shapes/Shape.js.map +1 -1
- package/lib/esm/shapes/nodeShapeData.js +7 -10
- package/lib/esm/shapes/nodeShapeData.js.map +1 -1
- package/lib/esm/shapes/registerRuntimeShape.js +3 -1
- package/lib/esm/shapes/registerRuntimeShape.js.map +1 -1
- package/lib/esm/shapes/syncShapes.d.ts +6 -2
- package/lib/esm/shapes/syncShapes.js +16 -9
- package/lib/esm/shapes/syncShapes.js.map +1 -1
- package/lib/esm/shapes/validation.js +2 -2
- package/lib/esm/shapes/validation.js.map +1 -1
- package/lib/esm/sparql/irToAlgebra.js +117 -52
- package/lib/esm/sparql/irToAlgebra.js.map +1 -1
- package/lib/esm/sparql/ownedLinkCheck.js +6 -1
- package/lib/esm/sparql/ownedLinkCheck.js.map +1 -1
- package/lib/esm/utils/LinkedStorage.d.ts +7 -0
- package/lib/esm/utils/LinkedStorage.js +39 -12
- package/lib/esm/utils/LinkedStorage.js.map +1 -1
- package/lib/esm/utils/ShapeCatalog.d.ts +57 -0
- package/lib/esm/utils/ShapeCatalog.js +86 -0
- package/lib/esm/utils/ShapeCatalog.js.map +1 -0
- package/lib/esm/utils/ShapeClass.d.ts +73 -8
- package/lib/esm/utils/ShapeClass.js +245 -66
- package/lib/esm/utils/ShapeClass.js.map +1 -1
- package/lib/esm/utils/loadStores.d.ts +4 -0
- package/lib/esm/utils/loadStores.js +24 -1
- package/lib/esm/utils/loadStores.js.map +1 -1
- package/lib/esm/utils/registryCache.d.ts +15 -0
- package/lib/esm/utils/registryCache.js +50 -0
- package/lib/esm/utils/registryCache.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncShapes.js","sourceRoot":"","sources":["../../../src/shapes/syncShapes.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport {getAllShapeClasses, getShapeClass} from '../utils/ShapeClass.js';\nimport {NodeShape} from './SHACL.js';\nimport {\n getUniquePropertyShapes,\n type NodeShapeData,\n type PropertyShapeData,\n} from './nodeShapeData.js';\nimport {Shape} from './Shape.js';\nimport {DeleteBuilder} from '../queries/DeleteBuilder.js';\nimport type {IDataset} from '../interfaces/IDataset.js';\nimport {rdfList} from './List.js';\nimport {serializePathToNodeData} from './serializePathToNodeData.js';\nimport {buildSingleOwnerConstraints} from './singleOwnerConstraint.js';\nimport {QueryBuilder} from '../queries/QueryBuilder.js';\nimport {sha256Hex} from '../utils/sha256.js';\n\n/**\n * The npm scope of framework shapes (NodeShape/PropertyShape/List/PathNode/Shape) that\n * describe the meta-model itself and must never be synced as user data.\n */\nconst FRAMEWORK_PACKAGE = '@_linked/core';\n\n/**\n * Build the create-pipeline data object for a single PropertyShape (flattened under shapeIri).\n *\n * @internal Exported for tests only — not part of the public API.\n */\nexport function buildPropertyShapeData(ps: PropertyShapeData, shapeIri: string): Record<string, unknown> {\n const psIri = `${shapeIri}/${ps.label}`;\n const d: Record<string, unknown> = {\n __id: psIri,\n path: serializePathToNodeData(ps.path),\n };\n // `rdfs:label` — the DSL label, i.e. the accessor name the property is reached\n // by in code (`person.memberships`). It is NOT `sh:name`, written below, which\n // is a human-readable display string.\n //\n // Without this the label is only ever implied by `psIri`, and a reader has to\n // re-derive one from the path's local part. That works right up until the two\n // differ — `@_linked/org` declares `memberships` on the path `org:hasMembership`\n // — at which point the catalog reports `hasMembership`, the query proxy indexes\n // the shape with it, and the class (which only knows `memberships`) throws.\n // Readers already prefer a stored label and fall back to the path, so writing it\n // is the whole fix; old catalogs keep working via that fallback.\n if (ps.label) d.label = ps.label;\n if (ps.nodeKind) d.nodeKind = ps.nodeKind;\n if (ps.datatype) d.datatype = ps.datatype;\n if (typeof ps.minCount === 'number') d.minCount = ps.minCount;\n if (typeof ps.maxCount === 'number') d.maxCount = ps.maxCount;\n if (ps.name) d.name = ps.name;\n if (ps.description) d.description = ps.description;\n if (typeof ps.order === 'number') d.order = ps.order;\n if (ps.group) d.group = ps.group;\n if (typeof ps.displayRank === 'number') d.displayRank = ps.displayRank;\n if (ps.displayHidden !== undefined) d.displayHidden = ps.displayHidden;\n if (ps.class) d.class = ps.class;\n if (ps.in) d.in = rdfList(ps.in, {base: `${psIri}/in`});\n if (ps.equalsConstraint) d.equalsConstraint = ps.equalsConstraint;\n if (ps.disjoint) d.disjoint = ps.disjoint;\n if (ps.lessThan) d.lessThan = ps.lessThan;\n if (ps.lessThanOrEquals) d.lessThanOrEquals = ps.lessThanOrEquals;\n if (ps.minInclusive !== undefined) d.minInclusive = ps.minInclusive;\n if (ps.maxInclusive !== undefined) d.maxInclusive = ps.maxInclusive;\n if (ps.minExclusive !== undefined) d.minExclusive = ps.minExclusive;\n if (ps.maxExclusive !== undefined) d.maxExclusive = ps.maxExclusive;\n if (typeof ps.minLength === 'number') d.minLength = ps.minLength;\n if (typeof ps.maxLength === 'number') d.maxLength = ps.maxLength;\n // sh:pattern is serialized as its regex source string.\n if (ps.pattern) d.pattern = ps.pattern.source;\n if (ps.hasValueConstraint !== undefined) d.hasValue = ps.hasValueConstraint;\n if (ps.valueShape) d.valueShape = ps.valueShape;\n if (ps.contains) d.contains = true;\n return d;\n}\n\n/** Build the create-pipeline data object for a NodeShape and its (flattened) property shapes. */\nfunction buildNodeShapeData(nodeShape: NodeShapeData, shapeIri: string): Record<string, unknown> {\n const d: Record<string, unknown> = {};\n if (nodeShape.targetClass) d.targetClass = nodeShape.targetClass;\n if (nodeShape.description) d.description = nodeShape.description;\n if (nodeShape.extends) d.extends = nodeShape.extends;\n if (nodeShape.dependent) d.dependent = true;\n if (nodeShape.closed !== undefined) d.closed = nodeShape.closed;\n if (nodeShape.ignoredProperties && nodeShape.ignoredProperties.length) {\n d.ignoredProperties = nodeShape.ignoredProperties;\n }\n // Flatten: emit own + inherited property shapes (deduped by label) under this shape.\n d.properties = getUniquePropertyShapes(nodeShape).map((ps) =>\n buildPropertyShapeData(ps, shapeIri),\n );\n // The single-owner constraints of the shape's own `contains` properties, owned through\n // `core:generatedShape` and written nested in the same create with their fixed IRIs.\n const generated = buildSingleOwnerConstraints(nodeShape, shapeIri);\n if (generated.length > 0) {\n d.generatedShapes = generated.map(({iri, data}) => ({__id: iri, ...data}));\n }\n return d;\n}\n\n/**\n * Version of the {@link shapeSyncHash} input. Bump it whenever core changes the SHACL it writes\n * for a shape (a serialization change that the create data itself does not show), so every stored\n * shape is rewritten once by the next sync. Without a bump, stores keep the old triples: their\n * stored hashes still match, so the sync skips them.\n *\n * Enforced by `shape-sync-output-equivalence.test.ts`: its golden SHACL output is recorded in\n * `SHAPE_HASH_LEDGER` with the version it was generated for, and regenerating the golden without\n * bumping this constant fails that test. To change the output: bump this by one, update the\n * golden, and append `{version, goldenDigest}` to the ledger (never edit an existing entry).\n *\n * @internal Exported for tests only — not part of the public API.\n */\nexport const SHAPE_HASH_VERSION = 1;\n\n/**\n * A canonical string for create-pipeline data: equal for equal data, independent of object key\n * order and of the order of array values.\n *\n * Arrays are sorted because in create data an array is always a multi-valued property (a set of\n * RDF values: `properties`, `generatedShapes`, `targetObjectsOf`, …). Ordered `rdf:List`s\n * (`sh:in`, sequence and alternative paths, `sh:or`) are nested `first`/`rest` objects, so their\n * order is kept by the structure. A shape class value (`shape: List`) is written as its NodeShape\n * IRI. Values without ids (blank nodes once written) are compared by structure, so no blank-node\n * label is ever part of the input.\n */\nfunction canonicalize(value: unknown): string {\n if (value === null || value === undefined) return 'null';\n switch (typeof value) {\n case 'string':\n return JSON.stringify(value);\n case 'number':\n return `n:${Object.is(value, -0) ? '0' : String(value)}`;\n case 'boolean':\n return `b:${value}`;\n case 'bigint':\n return `i:${value.toString()}`;\n case 'function': {\n const shapeId = (value as {shape?: {id?: string}}).shape?.id;\n return `c:${JSON.stringify(shapeId ?? (value as {name?: string}).name ?? '')}`;\n }\n }\n if (Array.isArray(value)) {\n return `[${value.map(canonicalize).sort().join(',')}]`;\n }\n if (value instanceof Date) return `d:${value.toISOString()}`;\n if (value instanceof RegExp) return `r:${JSON.stringify(value.source)}/${value.flags}`;\n const record = value as Record<string, unknown>;\n const keys = Object.keys(record)\n .filter((k) => record[k] !== undefined)\n .sort();\n return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalize(record[k])}`).join(',')}}`;\n}\n\n/**\n * The content hash shape sync stores on a NodeShape as `core:shapeHash`: SHA-256 (hex) of the\n * canonical form of the shape IRI and the exact create data the sync writes for it — the\n * NodeShape, its flattened own + inherited property shapes, their `sh:in` lists and paths, and\n * the generated single-owner shapes it owns (whose owner classes come from the registered\n * sub-shapes, so registering a new sub-shape changes the hash of the declaring shape).\n *\n * Deterministic across processes, runtimes and Node versions: no blank-node labels, no object key\n * order, no array order (see {@link canonicalize}).\n *\n * @internal Exported for tests only — not part of the public API.\n */\nexport function shapeSyncHash(data: Record<string, unknown>, shapeIri: string): string {\n return sha256Hex(`linked-shape-sync/${SHAPE_HASH_VERSION}\\n${canonicalize({iri: shapeIri, data})}`);\n}\n\n/** The create data and its content hash for one shape, as the sync writes it. */\nfunction buildSyncData(\n nodeShape: NodeShapeData,\n iri: string,\n): {data: Record<string, unknown>; hash: string} {\n const data = buildNodeShapeData(nodeShape, iri);\n return {data, hash: shapeSyncHash(data, iri)};\n}\n\n/**\n * The stored `core:shapeHash` of each of `iris` that exists as a NodeShape, in one select. A shape\n * that is absent, or stored without a hash (written before hashes existed), is missing from the\n * map. `ds` targets an explicit dataset, as for the writes.\n */\nasync function readStoredHashes(iris: string[], ds?: IDataset): Promise<Map<string, string>> {\n const stored = new Map<string, string>();\n if (iris.length === 0) return stored;\n const rows = (await (QueryBuilder.from(NodeShape).select(['shapeHash']).forAll(iris) as unknown as {\n exec: (target?: IDataset) => Promise<Array<{id: string; shapeHash?: unknown}> | null>;\n }).exec(ds)) ?? [];\n for (const row of rows) {\n if (row && typeof row.shapeHash === 'string') stored.set(row.id, row.shapeHash);\n }\n return stored;\n}\n\n/**\n * The per-shape `delete → create` thunk shared by `syncShapes()` and `syncShape()`: exactly two\n * requests. The delete cascade-cleans the shape's old property-shape / list / path subtrees; the\n * create rebuilds them, and stores the content hash (`core:shapeHash`) of what it wrote on the\n * NodeShape so a later sync can skip the shape while it is unchanged.\n *\n * The single-owner constraints generated from the shape's own `contains` properties\n * (`${iri}/${label}.singleOwner`, see `singleOwnerConstraint.ts`) are owned by the shape through\n * `core:generatedShape` (a `contains` property with value shape NodeShape). The delete removes\n * them and their property shapes through the owned walk, and their blank path and qualified-shape\n * nodes through the blank-node cascade; the create writes the current ones nested, in the same request\n * as the shape. A removed or renamed accessor therefore loses its constraint on the next sync,\n * and a NodeShape the shape does not own is never touched.\n *\n * `ds` (optional) targets an explicit dataset — both requests run against it instead of the\n * global router. Omitted → today's global behavior.\n */\nfunction buildSyncThunk(nodeShape: NodeShapeData, iri: string, ds?: IDataset): () => Promise<void> {\n // `writeShape` builds the data fresh on each invocation, so every run writes from the current\n // shape metadata, and the hash stored with it always describes what was written.\n return () => writeShape(nodeShape, iri, ds);\n}\n\n/** Delete (cascade) then create one shape, storing the hash of the written data. */\nasync function writeShape(nodeShape: NodeShapeData, iri: string, ds?: IDataset): Promise<void> {\n const {data, hash} = buildSyncData(nodeShape, iri);\n await DeleteBuilder.from(NodeShape, {id: iri}).exec(ds);\n await (NodeShape.create({...data, shapeHash: hash} as never).withId(iri) as unknown as {\n exec: (target?: IDataset) => Promise<unknown>;\n }).exec(ds);\n}\n\n/** The generated single-owner shape IRIs a code shape writes. */\nfunction generatedIrisOf(nodeShape: NodeShapeData, iri: string): string[] {\n return buildSingleOwnerConstraints(nodeShape, iri).map((c) => c.iri);\n}\n\n/** Throw when a registered shape IRI equals one of a shape's generated single-owner IRIs. */\nfunction assertNoGeneratedIriCollision(\n nodeShape: NodeShapeData,\n iri: string,\n isRegistered: (iri: string) => boolean,\n): void {\n for (const generated of generatedIrisOf(nodeShape, iri)) {\n if (isRegistered(generated)) {\n throw new Error(`Shape IRI ${generated} collides with a generated single-owner shape`);\n }\n }\n}\n\n/** Options controlling how {@link syncShapes} treats store shapes that are not in code. */\nexport interface SyncShapesOptions {\n /**\n * How to treat NodeShapes present in the store but not in the current process's code:\n * - `'none'` (default) — never prune; purely additive (delete→recreate the code shapes, touch\n * nothing else). The only mode that is safe when the process has loaded a *subset* of the\n * shapes in the dataset, or when the dataset has more than one writer.\n * - `'all'` — prune every store-only shape as an orphan. Only correct when this process has\n * loaded **every** shape the dataset should hold and is its **only** writer; \"not registered\n * here\" is then taken to mean \"deleted from code\".\n * - `'ownedNamespaces'` — prune a store-only shape ONLY if its IRI falls within a namespace\n * this process actually writes (the package-namespace of one of its code-registered shapes,\n * i.e. the IRI prefix up to the last `/` or `#`). Protects other writers' packages (arch-04:\n * one app-data dataset, several writers), but NOT the rest of a package the process only\n * partially loaded — the namespace is the whole package, so a deep import of one shape file\n * still claims all of it.\n *\n * `'all'` and `'ownedNamespaces'` are destructive and must be requested explicitly.\n */\n orphanScope?: 'all' | 'ownedNamespaces' | 'none';\n /**\n * Rewrite every code shape, even one whose stored `core:shapeHash` matches. Default `false`:\n * a shape is rewritten only when its hash differs or is missing. Use it to repair a shape\n * whose stored subtree was edited or partly deleted outside shape sync (the hash describes\n * what sync last wrote, not what is in the store now).\n */\n force?: boolean;\n}\n\n/** Options for {@link syncShape}. */\nexport interface SyncShapeOptions {\n /** Rewrite the shape even when its stored `core:shapeHash` matches. See {@link SyncShapesOptions.force}. */\n force?: boolean;\n}\n\n/** The owning namespace of a shape IRI — everything up to and including the last `/` or `#`. */\nfunction shapeNamespace(iri: string): string {\n const cut = Math.max(iri.lastIndexOf('/'), iri.lastIndexOf('#'));\n return cut >= 0 ? iri.slice(0, cut + 1) : iri;\n}\n\n/**\n * Plan an idempotent sync of all code-registered (non-framework) NodeShapes into the store as\n * SHACL data — the forward (code → graph) materialization of arch-05 \"code is canonical\".\n *\n * Returns built-but-unexecuted thunks; the caller controls execution and batching:\n * ```ts\n * await Promise.all((await syncShapes()).map((run) => run()));\n * ```\n * Each in-code shape's thunk runs `delete → create` in order (the delete cascade-cleans the old\n * property shapes / list / path subtrees via the containment cascade, the create rebuilds them).\n *\n * **Unchanged shapes are skipped.** The create stores a content hash of everything it writes for\n * the shape on the NodeShape (`core:shapeHash`, see {@link shapeSyncHash}). The plan reads the\n * stored hashes of all code shapes in one select and builds a thunk only for a shape whose hash\n * is missing (never synced, or synced before hashes existed) or differs. Syncing an unchanged\n * app therefore returns no write thunks, and the length of the plan is the number of shapes\n * actually written plus the pruned orphans. The hash records what sync last wrote, not what the\n * store holds now: a subtree edited or partly deleted by another writer while the NodeShape and\n * its hash survive is not detected. `options.force` rewrites every code shape.\n *\n * **Shapes in the store but not registered in this process are left alone by default**\n * (`orphanScope: 'none'`). The registry only holds what this process happened to import, and\n * that is routinely a subset of what the dataset holds: shapes are deep-importable one file at a\n * time, and an app-data dataset also holds shapes other writers materialized (CN's\n * `bindShape` / `enableCapability`). \"Not registered here\" therefore does not mean \"deleted from\n * code\". Measured against a dataset holding the 36 `@_linked/schema` shapes: a process that\n * imported only `@_linked/schema/shapes/Thing` (11 shapes registered) deleted the other 25 under\n * both `'all'` and `'ownedNamespaces'`, and a process that imported no shapes deleted all 36.\n *\n * Pruning is opt-in via `options.orphanScope` (see {@link SyncShapesOptions}): pass `'all'` only\n * from a process that has loaded every shape the dataset should hold and is its sole writer, and\n * `'ownedNamespaces'` only when it has loaded every shape of each package it registers. Pruned\n * orphans are deleted with their owned subtree. Pruning reads the existing shape IRIs first;\n * with `'none'` no read is made.\n *\n * `ds` (optional) targets an explicit dataset instead of the global router. It is a **plan-time**\n * parameter: it feeds the stored-hash read and the orphan-detection read (so both are computed\n * against the same store they'll be written to) and every delete/create thunk. Omitted → the global router;\n * the returned thunks stay nullary either way.\n */\nexport async function syncShapes(\n ds?: IDataset,\n options?: SyncShapesOptions,\n): Promise<Array<() => Promise<void>>> {\n const orphanScope = options?.orphanScope ?? 'none';\n // 1. Enumerate code-registered user shapes (exclude framework/meta shapes).\n const userShapes: Array<{iri: string; nodeShape: NodeShapeData}> = [];\n for (const [iri, shapeClass] of getAllShapeClasses()) {\n if (!shapeClass?.shape) continue;\n const pkg = (shapeClass as {packageName?: string}).packageName;\n // Skip framework/meta shapes: the core package, and the base `Shape` which is registered\n // directly (no applyLinkedShape) and therefore carries no packageName.\n if (!pkg || pkg === FRAMEWORK_PACKAGE) continue;\n userShapes.push({iri, nodeShape: shapeClass.shape});\n }\n const localShapeIris = new Set(userShapes.map((s) => s.iri));\n for (const {iri, nodeShape} of userShapes) {\n assertNoGeneratedIriCollision(nodeShape, iri, (id) => localShapeIris.has(id));\n }\n // The generated single-owner shapes of in-code shapes are written by the same thunks, so they\n // are never orphans. Derived in memory from the same function that builds them; a stale\n // generated shape (removed accessor or shape) is not protected and goes with its owner's\n // delete, through the `core:generatedShape` cascade.\n for (const {iri, nodeShape} of userShapes) {\n for (const generated of generatedIrisOf(nodeShape, iri)) localShapeIris.add(generated);\n }\n // Namespaces this process actually writes — the ownership scope for `'ownedNamespaces'` pruning.\n const ownedNamespaces = new Set(userShapes.map((s) => shapeNamespace(s.iri)));\n\n const thunks: Array<() => Promise<void>> = [];\n\n // 2. Per in-code shape whose stored content hash is missing or differs: delete (cascade) then\n // recreate. An unchanged shape gets no thunk, so syncing an unchanged app writes nothing.\n // The stored hashes are read in one select, against the same `ds` the thunks target.\n const storedHashes = options?.force\n ? new Map<string, string>()\n : await readStoredHashes(userShapes.map((s) => s.iri), ds);\n for (const {iri, nodeShape} of userShapes) {\n if (!options?.force && storedHashes.get(iri) === buildSyncData(nodeShape, iri).hash) continue;\n thunks.push(buildSyncThunk(nodeShape, iri, ds));\n }\n\n // 3. Orphan sweep (unless disabled). Identity-read existing NodeShape IRIs (ids only). Must hit\n // the same `ds` the thunks target, or orphans get computed against the wrong store.\n if (orphanScope !== 'none') {\n const existingRows = (await (NodeShape as unknown as {\n select: () => {exec: (target?: IDataset) => Promise<Array<{id: string}>>};\n }).select().exec(ds)) as Array<{id: string}>;\n\n // Orphan shapes (in store, not in code) → delete (cascade cleans their owned subtree). In\n // `'ownedNamespaces'` mode, only shapes within a namespace this process writes are eligible —\n // other writers' shapes (different package namespace) are left untouched.\n for (const {id: iri} of existingRows) {\n if (localShapeIris.has(iri)) continue;\n if (orphanScope === 'ownedNamespaces' && !ownedNamespaces.has(shapeNamespace(iri))) {\n continue;\n }\n thunks.push(() =>\n (DeleteBuilder.from(NodeShape, {id: iri}).exec(ds) as Promise<unknown>).then(\n () => undefined,\n ),\n );\n }\n }\n\n return thunks;\n}\n\n/**\n * Plan an idempotent sync of ONE code-registered NodeShape into the store as SHACL data.\n *\n * Scoped counterpart to {@link syncShapes}: materializes a single shape (delete → recreate, so the\n * delete cascade-cleans the old property-shape / list / path subtrees and the create rebuilds them)\n * and does NOT run the store-wide orphan sweep — other shapes in the store are untouched.\n *\n * @param target a shape class (e.g. `Person`) or its NodeShape IRI string. An IRI is resolved to\n * its registered class via `getShapeClass`; the shape must be code-registered.\n * @param ds optional explicit dataset to materialize into (a store or a router) — both the delete\n * and the create run against it instead of the global router. Omitted → global behavior.\n * @param options `force: true` rewrites the shape even when its stored hash matches.\n * @returns a single unexecuted thunk (consistent with {@link syncShapes}), so callers can batch\n * several together — e.g. a shape plus its referenced object-property shapes:\n * `await Promise.all([syncShape(Person), syncShape(Address)].map((run) => run()))`.\n * Unless `force` is set, the thunk first reads the shape's stored `core:shapeHash` and writes\n * nothing when it equals the hash of what it would write (see {@link syncShapes}).\n * @throws if `target` is a framework/meta shape, is not registered, or has no `.shape`.\n */\nexport function syncShape(\n target: typeof Shape | string,\n ds?: IDataset,\n options?: SyncShapeOptions,\n): () => Promise<void> {\n // Normalize target → its registered shape class.\n const cls =\n typeof target === 'string' ? getShapeClass(target) : (target as typeof Shape);\n if (typeof target === 'string' && !cls) {\n throw new Error(`syncShape: no registered shape for IRI ${target}`);\n }\n const nodeShape = cls?.shape;\n if (!nodeShape) {\n throw new Error(\n typeof target === 'string'\n ? `syncShape: no registered shape for IRI ${target}`\n : `syncShape: shape class has no static .shape`,\n );\n }\n const iri = nodeShape.id;\n\n // Never materialize a framework/meta shape as user data — same invariant syncShapes() enforces\n // by skipping (the base Shape carries no packageName).\n const pkg = (cls as {packageName?: string}).packageName;\n if (!pkg || pkg === FRAMEWORK_PACKAGE) {\n throw new Error(`syncShape: refusing to sync framework/meta shape ${iri}`);\n }\n\n assertNoGeneratedIriCollision(nodeShape, iri, (id) => !!getShapeClass(id));\n if (options?.force) return buildSyncThunk(nodeShape, iri, ds);\n return async () => {\n const stored = await readStoredHashes([iri], ds);\n if (stored.get(iri) === buildSyncData(nodeShape, iri).hash) return;\n await writeShape(nodeShape, iri, ds);\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"syncShapes.js","sourceRoot":"","sources":["../../../src/shapes/syncShapes.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\nimport {getAllShapeClasses, getShapeClass} from '../utils/ShapeClass.js';\nimport {NodeShape} from './SHACL.js';\nimport {\n getUniquePropertyShapes,\n type NodeShapeData,\n type PropertyShapeData,\n} from './nodeShapeData.js';\nimport {Shape} from './Shape.js';\nimport {DeleteBuilder} from '../queries/DeleteBuilder.js';\nimport type {IDataset} from '../interfaces/IDataset.js';\nimport {rdfList} from './List.js';\nimport {serializePathToNodeData} from './serializePathToNodeData.js';\nimport {buildSingleOwnerConstraints} from './singleOwnerConstraint.js';\nimport {QueryBuilder} from '../queries/QueryBuilder.js';\nimport {sha256Hex} from '../utils/sha256.js';\nimport {builtInShapeIris} from '../utils/ShapeCatalog.js';\n\n/**\n * The npm scope of core's shapes. Only its six built-ins (`builtInShapeIris`) are synced; any\n * other shape declared with core's own `linkedShape` (core's test fixtures) is not.\n */\nconst FRAMEWORK_PACKAGE = '@_linked/core';\n\n/**\n * Build the create-pipeline data object for a single PropertyShape (flattened under shapeIri).\n *\n * @internal Exported for tests only — not part of the public API.\n */\nexport function buildPropertyShapeData(ps: PropertyShapeData, shapeIri: string): Record<string, unknown> {\n const psIri = `${shapeIri}/${ps.label}`;\n const d: Record<string, unknown> = {\n __id: psIri,\n path: serializePathToNodeData(ps.path),\n };\n // `rdfs:label` — the DSL label, i.e. the accessor name the property is reached\n // by in code (`person.memberships`). It is NOT `sh:name`, written below, which\n // is a human-readable display string.\n //\n // Without this the label is only ever implied by `psIri`, and a reader has to\n // re-derive one from the path's local part. That works right up until the two\n // differ — `@_linked/org` declares `memberships` on the path `org:hasMembership`\n // — at which point the catalog reports `hasMembership`, the query proxy indexes\n // the shape with it, and the class (which only knows `memberships`) throws.\n // Readers already prefer a stored label and fall back to the path, so writing it\n // is the whole fix; old catalogs keep working via that fallback.\n if (ps.label) d.label = ps.label;\n if (ps.nodeKind) d.nodeKind = ps.nodeKind;\n if (ps.datatype) d.datatype = ps.datatype;\n if (typeof ps.minCount === 'number') d.minCount = ps.minCount;\n if (typeof ps.maxCount === 'number') d.maxCount = ps.maxCount;\n if (ps.name) d.name = ps.name;\n if (ps.description) d.description = ps.description;\n if (typeof ps.order === 'number') d.order = ps.order;\n if (ps.group) d.group = ps.group;\n if (typeof ps.displayRank === 'number') d.displayRank = ps.displayRank;\n if (ps.displayHidden !== undefined) d.displayHidden = ps.displayHidden;\n if (ps.class) d.class = ps.class;\n if (ps.in) d.in = rdfList(ps.in, {base: `${psIri}/in`});\n if (ps.equalsConstraint) d.equalsConstraint = ps.equalsConstraint;\n if (ps.disjoint) d.disjoint = ps.disjoint;\n if (ps.lessThan) d.lessThan = ps.lessThan;\n if (ps.lessThanOrEquals) d.lessThanOrEquals = ps.lessThanOrEquals;\n if (ps.minInclusive !== undefined) d.minInclusive = ps.minInclusive;\n if (ps.maxInclusive !== undefined) d.maxInclusive = ps.maxInclusive;\n if (ps.minExclusive !== undefined) d.minExclusive = ps.minExclusive;\n if (ps.maxExclusive !== undefined) d.maxExclusive = ps.maxExclusive;\n if (typeof ps.minLength === 'number') d.minLength = ps.minLength;\n if (typeof ps.maxLength === 'number') d.maxLength = ps.maxLength;\n // sh:pattern is serialized as its regex source string.\n if (ps.pattern) d.pattern = ps.pattern.source;\n if (ps.hasValueConstraint !== undefined) d.hasValue = ps.hasValueConstraint;\n if (ps.valueShape) d.valueShape = ps.valueShape;\n if (ps.contains) d.contains = true;\n return d;\n}\n\n/** Build the create-pipeline data object for a NodeShape and its (flattened) property shapes. */\nfunction buildNodeShapeData(nodeShape: NodeShapeData, shapeIri: string): Record<string, unknown> {\n const d: Record<string, unknown> = {};\n if (nodeShape.targetClass) d.targetClass = nodeShape.targetClass;\n if (nodeShape.description) d.description = nodeShape.description;\n if (nodeShape.extends) d.extends = nodeShape.extends;\n if (nodeShape.dependent) d.dependent = true;\n if (nodeShape.closed !== undefined) d.closed = nodeShape.closed;\n if (nodeShape.ignoredProperties && nodeShape.ignoredProperties.length) {\n d.ignoredProperties = nodeShape.ignoredProperties;\n }\n // Flatten: emit own + inherited property shapes (deduped by label) under this shape.\n d.properties = getUniquePropertyShapes(nodeShape).map((ps) =>\n buildPropertyShapeData(ps, shapeIri),\n );\n // The single-owner constraints of the shape's own `contains` properties, owned through\n // `core:generatedShape` and written nested in the same create with their fixed IRIs.\n const generated = buildSingleOwnerConstraints(nodeShape, shapeIri);\n if (generated.length > 0) {\n d.generatedShapes = generated.map(({iri, data}) => ({__id: iri, ...data}));\n }\n return d;\n}\n\n/**\n * Version of the {@link shapeSyncHash} input. Bump it whenever core changes the SHACL it writes\n * for a shape (a serialization change that the create data itself does not show), so every stored\n * shape is rewritten once by the next sync. Without a bump, stores keep the old triples: their\n * stored hashes still match, so the sync skips them.\n *\n * Enforced by `shape-sync-output-equivalence.test.ts`: its golden SHACL output is recorded in\n * `SHAPE_HASH_LEDGER` with the version it was generated for, and regenerating the golden without\n * bumping this constant fails that test. To change the output: bump this by one, update the\n * golden, and append `{version, goldenDigest}` to the ledger (never edit an existing entry).\n *\n * @internal Exported for tests only — not part of the public API.\n */\nexport const SHAPE_HASH_VERSION = 1;\n\n/**\n * A canonical string for create-pipeline data: equal for equal data, independent of object key\n * order and of the order of array values.\n *\n * Arrays are sorted because in create data an array is always a multi-valued property (a set of\n * RDF values: `properties`, `generatedShapes`, `targetObjectsOf`, …). Ordered `rdf:List`s\n * (`sh:in`, sequence and alternative paths, `sh:or`) are nested `first`/`rest` objects, so their\n * order is kept by the structure. A shape class value (`shape: List`) is written as its NodeShape\n * IRI. Values without ids (blank nodes once written) are compared by structure, so no blank-node\n * label is ever part of the input.\n */\nfunction canonicalize(value: unknown): string {\n if (value === null || value === undefined) return 'null';\n switch (typeof value) {\n case 'string':\n return JSON.stringify(value);\n case 'number':\n return `n:${Object.is(value, -0) ? '0' : String(value)}`;\n case 'boolean':\n return `b:${value}`;\n case 'bigint':\n return `i:${value.toString()}`;\n case 'function': {\n const shapeId = (value as {shape?: {id?: string}}).shape?.id;\n return `c:${JSON.stringify(shapeId ?? (value as {name?: string}).name ?? '')}`;\n }\n }\n if (Array.isArray(value)) {\n return `[${value.map(canonicalize).sort().join(',')}]`;\n }\n if (value instanceof Date) return `d:${value.toISOString()}`;\n if (value instanceof RegExp) return `r:${JSON.stringify(value.source)}/${value.flags}`;\n const record = value as Record<string, unknown>;\n const keys = Object.keys(record)\n .filter((k) => record[k] !== undefined)\n .sort();\n return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalize(record[k])}`).join(',')}}`;\n}\n\n/**\n * The content hash shape sync stores on a NodeShape as `core:shapeHash`: SHA-256 (hex) of the\n * canonical form of the shape IRI and the exact create data the sync writes for it — the\n * NodeShape, its flattened own + inherited property shapes, their `sh:in` lists and paths, and\n * the generated single-owner shapes it owns (whose owner classes come from the registered\n * sub-shapes, so registering a new sub-shape changes the hash of the declaring shape).\n *\n * Deterministic across processes, runtimes and Node versions: no blank-node labels, no object key\n * order, no array order (see {@link canonicalize}).\n *\n * @internal Exported for tests only — not part of the public API.\n */\nexport function shapeSyncHash(data: Record<string, unknown>, shapeIri: string): string {\n return sha256Hex(`linked-shape-sync/${SHAPE_HASH_VERSION}\\n${canonicalize({iri: shapeIri, data})}`);\n}\n\n/** The create data and its content hash for one shape, as the sync writes it. */\nfunction buildSyncData(\n nodeShape: NodeShapeData,\n iri: string,\n): {data: Record<string, unknown>; hash: string} {\n const data = buildNodeShapeData(nodeShape, iri);\n return {data, hash: shapeSyncHash(data, iri)};\n}\n\n/**\n * The stored `core:shapeHash` of each of `iris` that exists as a NodeShape, in one select. A shape\n * that is absent, or stored without a hash (written before hashes existed), is missing from the\n * map. `ds` targets an explicit dataset, as for the writes.\n */\nasync function readStoredHashes(iris: string[], ds?: IDataset): Promise<Map<string, string>> {\n const stored = new Map<string, string>();\n if (iris.length === 0) return stored;\n const rows = (await (QueryBuilder.from(NodeShape).select(['shapeHash']).forAll(iris) as unknown as {\n exec: (target?: IDataset) => Promise<Array<{id: string; shapeHash?: unknown}> | null>;\n }).exec(ds)) ?? [];\n for (const row of rows) {\n if (row && typeof row.shapeHash === 'string') stored.set(row.id, row.shapeHash);\n }\n return stored;\n}\n\n/**\n * The per-shape `delete → create` thunk shared by `syncShapes()` and `syncShape()`: exactly two\n * requests. The delete cascade-cleans the shape's old property-shape / list / path subtrees; the\n * create rebuilds them, and stores the content hash (`core:shapeHash`) of what it wrote on the\n * NodeShape so a later sync can skip the shape while it is unchanged.\n *\n * The single-owner constraints generated from the shape's own `contains` properties\n * (`${iri}/${label}.singleOwner`, see `singleOwnerConstraint.ts`) are owned by the shape through\n * `core:generatedShape` (a `contains` property with value shape NodeShape). The delete removes\n * them and their property shapes through the owned walk, and their blank path and qualified-shape\n * nodes through the blank-node cascade; the create writes the current ones nested, in the same request\n * as the shape. A removed or renamed accessor therefore loses its constraint on the next sync,\n * and a NodeShape the shape does not own is never touched.\n *\n * `ds` (optional) targets an explicit dataset — both requests run against it instead of the\n * global router. Omitted → today's global behavior.\n */\nfunction buildSyncThunk(nodeShape: NodeShapeData, iri: string, ds?: IDataset): () => Promise<void> {\n // `writeShape` builds the data fresh on each invocation, so every run writes from the current\n // shape metadata, and the hash stored with it always describes what was written.\n return () => writeShape(nodeShape, iri, ds);\n}\n\n/** Delete (cascade) then create one shape, storing the hash of the written data. */\nasync function writeShape(nodeShape: NodeShapeData, iri: string, ds?: IDataset): Promise<void> {\n const {data, hash} = buildSyncData(nodeShape, iri);\n await DeleteBuilder.from(NodeShape, {id: iri}).exec(ds);\n await (NodeShape.create({...data, shapeHash: hash} as never).withId(iri) as unknown as {\n exec: (target?: IDataset) => Promise<unknown>;\n }).exec(ds);\n}\n\n/** The generated single-owner shape IRIs a code shape writes. */\nfunction generatedIrisOf(nodeShape: NodeShapeData, iri: string): string[] {\n return buildSingleOwnerConstraints(nodeShape, iri).map((c) => c.iri);\n}\n\n/** Throw when a registered shape IRI equals one of a shape's generated single-owner IRIs. */\nfunction assertNoGeneratedIriCollision(\n nodeShape: NodeShapeData,\n iri: string,\n isRegistered: (iri: string) => boolean,\n): void {\n for (const generated of generatedIrisOf(nodeShape, iri)) {\n if (isRegistered(generated)) {\n throw new Error(`Shape IRI ${generated} collides with a generated single-owner shape`);\n }\n }\n}\n\n/** Options controlling how {@link syncShapes} treats store shapes that are not in code. */\nexport interface SyncShapesOptions {\n /**\n * How to treat NodeShapes present in the store but not in the current process's code:\n * - `'none'` (default) — never prune; purely additive (delete→recreate the code shapes, touch\n * nothing else). The only mode that is safe when the process has loaded a *subset* of the\n * shapes in the dataset, or when the dataset has more than one writer.\n * - `'all'` — prune every store-only shape as an orphan. Only correct when this process has\n * loaded **every** shape the dataset should hold and is its **only** writer; \"not registered\n * here\" is then taken to mean \"deleted from code\".\n * - `'ownedNamespaces'` — prune a store-only shape ONLY if its IRI falls within a namespace\n * this process actually writes (the package-namespace of one of its code-registered shapes,\n * i.e. the IRI prefix up to the last `/` or `#`). Protects other writers' packages (arch-04:\n * one app-data dataset, several writers), but NOT the rest of a package the process only\n * partially loaded — the namespace is the whole package, so a deep import of one shape file\n * still claims all of it.\n *\n * `'all'` and `'ownedNamespaces'` are destructive and must be requested explicitly.\n */\n orphanScope?: 'all' | 'ownedNamespaces' | 'none';\n /**\n * Rewrite every code shape, even one whose stored `core:shapeHash` matches. Default `false`:\n * a shape is rewritten only when its hash differs or is missing. Use it to repair a shape\n * whose stored subtree was edited or partly deleted outside shape sync (the hash describes\n * what sync last wrote, not what is in the store now).\n */\n force?: boolean;\n}\n\n/** Options for {@link syncShape}. */\nexport interface SyncShapeOptions {\n /** Rewrite the shape even when its stored `core:shapeHash` matches. See {@link SyncShapesOptions.force}. */\n force?: boolean;\n}\n\n/** The owning namespace of a shape IRI — everything up to and including the last `/` or `#`. */\nfunction shapeNamespace(iri: string): string {\n const cut = Math.max(iri.lastIndexOf('/'), iri.lastIndexOf('#'));\n return cut >= 0 ? iri.slice(0, cut + 1) : iri;\n}\n\n/**\n * Plan an idempotent sync of all code-registered NodeShapes into the store as SHACL data — the\n * forward (code → graph) materialization of arch-05 \"code is canonical\". Core's six built-in\n * shapes are included, like any package's; other shapes in the core package are not.\n *\n * Returns built-but-unexecuted thunks; the caller controls execution and batching:\n * ```ts\n * await Promise.all((await syncShapes()).map((run) => run()));\n * ```\n * Each in-code shape's thunk runs `delete → create` in order (the delete cascade-cleans the old\n * property shapes / list / path subtrees via the containment cascade, the create rebuilds them).\n *\n * **Unchanged shapes are skipped.** The create stores a content hash of everything it writes for\n * the shape on the NodeShape (`core:shapeHash`, see {@link shapeSyncHash}). The plan reads the\n * stored hashes of all code shapes in one select and builds a thunk only for a shape whose hash\n * is missing (never synced, or synced before hashes existed) or differs. Syncing an unchanged\n * app therefore returns no write thunks, and the length of the plan is the number of shapes\n * actually written plus the pruned orphans. The hash records what sync last wrote, not what the\n * store holds now: a subtree edited or partly deleted by another writer while the NodeShape and\n * its hash survive is not detected. `options.force` rewrites every code shape.\n *\n * **Shapes in the store but not registered in this process are left alone by default**\n * (`orphanScope: 'none'`). The registry only holds what this process happened to import, and\n * that is routinely a subset of what the dataset holds: shapes are deep-importable one file at a\n * time, and an app-data dataset also holds shapes other writers materialized (CN's\n * `bindShape` / `enableCapability`). \"Not registered here\" therefore does not mean \"deleted from\n * code\". Measured against a dataset holding the 36 `@_linked/schema` shapes: a process that\n * imported only `@_linked/schema/shapes/Thing` (11 shapes registered) deleted the other 25 under\n * both `'all'` and `'ownedNamespaces'`, and a process that imported no shapes deleted all 36.\n *\n * Pruning is opt-in via `options.orphanScope` (see {@link SyncShapesOptions}): pass `'all'` only\n * from a process that has loaded every shape the dataset should hold and is its sole writer, and\n * `'ownedNamespaces'` only when it has loaded every shape of each package it registers. Pruned\n * orphans are deleted with their owned subtree. Pruning reads the existing shape IRIs first;\n * with `'none'` no read is made.\n *\n * `ds` (optional) targets an explicit dataset instead of the global router. It is a **plan-time**\n * parameter: it feeds the stored-hash read and the orphan-detection read (so both are computed\n * against the same store they'll be written to) and every delete/create thunk. Omitted → the global router;\n * the returned thunks stay nullary either way.\n *\n * It enumerates the globally registered classes, so it must run outside any `withShapeCatalog`\n * scope: inside one it would see only core's built-ins, which it skips.\n */\nexport async function syncShapes(\n ds?: IDataset,\n options?: SyncShapesOptions,\n): Promise<Array<() => Promise<void>>> {\n const orphanScope = options?.orphanScope ?? 'none';\n // 1. Enumerate code-registered shapes: every package's, and core's six built-ins (`Shape`,\n // `NodeShape`, `PropertyShape`, `List`, `PathNode`, `PathList`), so a dataset is a complete\n // shape catalog on its own. Other core-package shapes and classes with no package are skipped.\n const builtIns = new Set(builtInShapeIris());\n const userShapes: Array<{iri: string; nodeShape: NodeShapeData}> = [];\n for (const [iri, shapeClass] of getAllShapeClasses()) {\n if (!shapeClass?.shape) continue;\n const pkg = (shapeClass as {packageName?: string}).packageName;\n if (!builtIns.has(iri) && (!pkg || pkg === FRAMEWORK_PACKAGE)) continue;\n userShapes.push({iri, nodeShape: shapeClass.shape});\n }\n const localShapeIris = new Set(userShapes.map((s) => s.iri));\n for (const {iri, nodeShape} of userShapes) {\n assertNoGeneratedIriCollision(nodeShape, iri, (id) => localShapeIris.has(id));\n }\n // The generated single-owner shapes of in-code shapes are written by the same thunks, so they\n // are never orphans. Derived in memory from the same function that builds them; a stale\n // generated shape (removed accessor or shape) is not protected and goes with its owner's\n // delete, through the `core:generatedShape` cascade.\n for (const {iri, nodeShape} of userShapes) {\n for (const generated of generatedIrisOf(nodeShape, iri)) localShapeIris.add(generated);\n }\n // Namespaces this process actually writes — the ownership scope for `'ownedNamespaces'` pruning.\n // Core's namespace is never one: every app writes the built-ins, and no app owns core's shapes.\n const ownedNamespaces = new Set(\n userShapes.filter((s) => !builtIns.has(s.iri)).map((s) => shapeNamespace(s.iri)),\n );\n\n const thunks: Array<() => Promise<void>> = [];\n\n // 2. Per in-code shape whose stored content hash is missing or differs: delete (cascade) then\n // recreate. An unchanged shape gets no thunk, so syncing an unchanged app writes nothing.\n // The stored hashes are read in one select, against the same `ds` the thunks target.\n const storedHashes = options?.force\n ? new Map<string, string>()\n : await readStoredHashes(userShapes.map((s) => s.iri), ds);\n for (const {iri, nodeShape} of userShapes) {\n if (!options?.force && storedHashes.get(iri) === buildSyncData(nodeShape, iri).hash) continue;\n thunks.push(buildSyncThunk(nodeShape, iri, ds));\n }\n\n // 3. Orphan sweep (unless disabled). Identity-read existing NodeShape IRIs (ids only). Must hit\n // the same `ds` the thunks target, or orphans get computed against the wrong store.\n if (orphanScope !== 'none') {\n const existingRows = (await (NodeShape as unknown as {\n select: () => {exec: (target?: IDataset) => Promise<Array<{id: string}>>};\n }).select().exec(ds)) as Array<{id: string}>;\n\n // Orphan shapes (in store, not in code) → delete (cascade cleans their owned subtree). In\n // `'ownedNamespaces'` mode, only shapes within a namespace this process writes are eligible —\n // other writers' shapes (different package namespace) are left untouched.\n for (const {id: iri} of existingRows) {\n if (localShapeIris.has(iri)) continue;\n if (orphanScope === 'ownedNamespaces' && !ownedNamespaces.has(shapeNamespace(iri))) {\n continue;\n }\n thunks.push(() =>\n (DeleteBuilder.from(NodeShape, {id: iri}).exec(ds) as Promise<unknown>).then(\n () => undefined,\n ),\n );\n }\n }\n\n return thunks;\n}\n\n/**\n * Plan an idempotent sync of ONE code-registered NodeShape into the store as SHACL data.\n *\n * Scoped counterpart to {@link syncShapes}: materializes a single shape (delete → recreate, so the\n * delete cascade-cleans the old property-shape / list / path subtrees and the create rebuilds them)\n * and does NOT run the store-wide orphan sweep — other shapes in the store are untouched.\n *\n * @param target a shape class (e.g. `Person`) or its NodeShape IRI string. An IRI is resolved to\n * its registered class via `getShapeClass`; the shape must be code-registered.\n * @param ds optional explicit dataset to materialize into (a store or a router) — both the delete\n * and the create run against it instead of the global router. Omitted → global behavior.\n * @param options `force: true` rewrites the shape even when its stored hash matches.\n * @returns a single unexecuted thunk (consistent with {@link syncShapes}), so callers can batch\n * several together — e.g. a shape plus its referenced object-property shapes:\n * `await Promise.all([syncShape(Person), syncShape(Address)].map((run) => run()))`.\n * Unless `force` is set, the thunk first reads the shape's stored `core:shapeHash` and writes\n * nothing when it equals the hash of what it would write (see {@link syncShapes}).\n * @throws if `target` is a framework/meta shape, is not registered, or has no `.shape`.\n */\nexport function syncShape(\n target: typeof Shape | string,\n ds?: IDataset,\n options?: SyncShapeOptions,\n): () => Promise<void> {\n // Normalize target → its registered shape class.\n const cls =\n typeof target === 'string' ? getShapeClass(target) : (target as typeof Shape);\n if (typeof target === 'string' && !cls) {\n throw new Error(`syncShape: no registered shape for IRI ${target}`);\n }\n const nodeShape = cls?.shape;\n if (!nodeShape) {\n throw new Error(\n typeof target === 'string'\n ? `syncShape: no registered shape for IRI ${target}`\n : `syncShape: shape class has no static .shape`,\n );\n }\n const iri = nodeShape.id;\n\n // Never materialize a framework/meta shape as user data — same invariant syncShapes() enforces\n // by skipping (the base Shape carries no packageName).\n const pkg = (cls as {packageName?: string}).packageName;\n if (!pkg || pkg === FRAMEWORK_PACKAGE) {\n throw new Error(`syncShape: refusing to sync framework/meta shape ${iri}`);\n }\n\n assertNoGeneratedIriCollision(nodeShape, iri, (id) => !!getShapeClass(id));\n if (options?.force) return buildSyncThunk(nodeShape, iri, ds);\n return async () => {\n const stored = await readStoredHashes([iri], ds);\n if (stored.get(iri) === buildSyncData(nodeShape, iri).hash) return;\n await writeShape(nodeShape, iri, ds);\n };\n}\n"]}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* Not covered: `sh:languageIn` / `sh:uniqueLang` (skipped at serialization time
|
|
38
38
|
* too, so there is no metadata to check against) and `sh:hasValue`.
|
|
39
39
|
*/
|
|
40
|
-
import { getShapeRegistryInstanceCount } from '../utils/ShapeClass.js';
|
|
40
|
+
import { getShapeRegistryInstanceCount, getQueryShapeClass } from '../utils/ShapeClass.js';
|
|
41
41
|
import { shacl } from '../ontologies/shacl.js';
|
|
42
42
|
import { xsd } from '../ontologies/xsd.js';
|
|
43
43
|
import { isNodeReferenceValue } from '../utils/NodeReference.js';
|
|
@@ -664,7 +664,7 @@ function resolveValueShape(ps, value) {
|
|
|
664
664
|
const own = (_a = value.shape) === null || _a === void 0 ? void 0 : _a.shape;
|
|
665
665
|
if (!ps.valueShape)
|
|
666
666
|
return own;
|
|
667
|
-
const declared = (_b =
|
|
667
|
+
const declared = (_b = getQueryShapeClass(ps.valueShape)) === null || _b === void 0 ? void 0 : _b.shape;
|
|
668
668
|
// A value naming a subclass of the declared shape is validated as that subclass.
|
|
669
669
|
if (own && declared && isSubShapeOf(own, declared))
|
|
670
670
|
return own;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/shapes/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\n/**\n * SHACL-aligned validation of plain data objects against a node shape.\n *\n * One entry point — {@link validate} — used by the create and update pipelines\n * (via `MutationQueryFactory.describe()`) and directly by callers that want to\n * know how well an object fits a shape without building a mutation.\n *\n * **Shape of the output.** This library has no triple/Turtle layer and this\n * module does not add one: a {@link ValidationReport} is plain JavaScript. It is\n * however 1-1 with the SHACL vocabulary — one key per SHACL property, named\n * after it, holding a value the mutation pipeline accepts (a literal, or a\n * `{id}` node reference for IRI-valued properties). So a report can be\n * materialized by an ordinary create query as soon as shape classes for\n * `sh:ValidationReport` / `sh:ValidationResult` exist, with no transform step:\n *\n * ```ts\n * const report = validate(Slide, data);\n * await ValidationReport.create(report); // once those shape classes exist\n * ```\n *\n * Two deliberate departures, both documented on the types: `results` is plural\n * where SHACL's repeated property is `sh:result`, and `propertyPath` is a\n * non-SHACL locator. Both map cleanly — a shape class chooses its own labels for\n * SHACL paths, and an extension property is legal on a SHACL report.\n *\n * **Coverage.** Cardinality (`sh:minCount` / `sh:maxCount`), node kind (literal\n * vs relation), undeclared properties (as `sh:closed`), `sh:datatype`, the four\n * `sh:min/maxInclusive/Exclusive` bounds, `sh:min/maxLength`, `sh:pattern` and\n * `sh:in`. Each is one entry in {@link CARDINALITY_CONSTRAINTS} or\n * {@link VALUE_CONSTRAINTS}, so adding another is one function and one test.\n *\n * Not covered: `sh:languageIn` / `sh:uniqueLang` (skipped at serialization time\n * too, so there is no metadata to check against) and `sh:hasValue`.\n */\nimport {getShapeRegistryInstanceCount} from '../utils/ShapeClass.js';\nimport {shacl} from '../ontologies/shacl.js';\nimport {xsd} from '../ontologies/xsd.js';\nimport {isNodeReferenceValue, type NodeReferenceValue} from '../utils/NodeReference.js';\nimport {getUniquePropertyShapes} from './nodeShapeData.js';\nimport type {NodeShapeData, PropertyShapeData} from './nodeShapeData.js';\nimport {getNodeShape, getShapeClass, isSubShapeOf} from '../utils/ShapeClass.js';\nimport {isExpressionNode} from '../expressions/ExpressionNode.js';\nimport {asContextRef} from '../queries/QueryContext.js';\n\n/**\n * Which constraints apply to the data being validated.\n *\n * - `complete` — the object describes a whole node (a create, or a standalone\n * object being checked for fit). Properties absent from the data are genuinely\n * absent, so `sh:minCount` presence is checkable.\n * - `partial` — the object describes a change to an existing node (an update).\n * The store holds whatever the payload does not mention, so presence is\n * unknowable; only the values actually provided are checked.\n */\nexport type ValidationMode = 'complete' | 'partial';\n\n/**\n * A single constraint violation — an `sh:ValidationResult`.\n *\n * Every key is the local name of the SHACL property it carries, and every value\n * is in a form the create pipeline accepts (a literal, or a `{id}` node\n * reference for IRI-valued properties). A shape class declaring these\n * properties therefore materializes a result with no transform step:\n * `ValidationResult.create(result)`. The one non-SHACL key is `propertyPath`;\n * see {@link ValidationReport}.\n */\nexport interface ValidationResult {\n /** `sh:focusNode` — the node the violation is about, when its id is known. */\n focusNode?: NodeReferenceValue;\n /** `sh:resultPath` — the IRI of the property the violation is about. */\n resultPath?: NodeReferenceValue;\n /**\n * `sh:value` — the offending value, present only when it is an RDF term (a\n * literal or a node reference). Cardinality violations are about the property\n * rather than any one value, so they carry none.\n */\n value?: LiteralTerm | NodeReferenceValue;\n /** `sh:sourceShape` — the node or property shape carrying the constraint. */\n sourceShape?: NodeReferenceValue;\n /** `sh:sourceConstraintComponent` — which SHACL constraint failed. */\n sourceConstraintComponent: NodeReferenceValue;\n /** `sh:resultSeverity` — `sh:Violation`, `sh:Warning` or `sh:Info`. */\n resultSeverity: NodeReferenceValue;\n /** `sh:resultMessage` — human-readable explanation. */\n resultMessage: string;\n /**\n * **Not SHACL.** The property's label, dot-joined through nested shapes\n * (`author.fullName`) — the locator a caller needs to point at a field in the\n * object they passed in, which `sh:resultPath` alone cannot give (it names the\n * property, not where the nesting reached it). Materializes like any other\n * property once a shape class declares it; drop it for a pure-SHACL result.\n */\n propertyPath?: string;\n}\n\n/**\n * The outcome of a validation run — an `sh:ValidationReport`.\n *\n * Plain objects, 1-1 with the SHACL vocabulary, so a report can later be\n * materialized through an ordinary create query against shape classes for\n * `sh:ValidationReport` / `sh:ValidationResult` — whether or not this library\n * ever ships those classes. `results` is the sole plural rename (SHACL's\n * property is `sh:result`, repeated); a shape class maps it with\n * `@objectProperty({path: shacl.result, …}) get results()`.\n */\nexport interface ValidationReport {\n /** `sh:conforms` — true when there are no `sh:Violation`-severity results. */\n conforms: boolean;\n /** `sh:result` — every violation found, in deterministic order. */\n results: ValidationResult[];\n}\n\n/** The literal types the mutation pipeline accepts as a value. */\ntype LiteralTerm = string | number | boolean | Date;\n\nexport interface ValidateOptions {\n /** Defaults to `complete`. */\n mode?: ValidationMode;\n /** How deep to descend into nested node descriptions. Defaults to 10. */\n maxDepth?: number;\n}\n\n/** Thrown by {@link assertValid} — carries the full report, not just the first violation. */\nexport class ShapeValidationError extends Error {\n readonly report: ValidationReport;\n constructor(report: ValidationReport) {\n super(report.results.map((r) => r.resultMessage).join('\\n'));\n this.name = 'ShapeValidationError';\n this.report = report;\n }\n}\n\n/**\n * Keys that carry metadata about the node rather than a property value: `id` /\n * `__id` name it, and `shape` names the shape of a nested value when the\n * property shape itself doesn't declare one (see `convertUpdateValue`).\n */\nconst RESERVED_KEYS = new Set(['id', '__id', 'shape']);\n\n/**\n * The message for an undeclared property key. Shared with the normalization path\n * in `MutationQuery`, which needs the same guard to build a field at all.\n */\nexport function undeclaredPropertyMessage(key: string, shape: NodeShapeData): string {\n const shapeName = shape.label || shape.id?.split('/').pop();\n const base =\n `Invalid property key: ${key}. The shape ${shapeName} does not have a registered ` +\n `property with this name. Make sure the get/set method exists, and that it uses a ` +\n `@objectProperty or @literalProperty decorator.`;\n\n // If more than one copy of the shape registry module has evaluated, this message is\n // very probably lying: the property IS declared, on a copy this code cannot see.\n // Saying so here is the whole point — the previous version of this error accused\n // correct application code, and finding the real cause took a day of eliminating\n // innocent suspects. See docs/reports/043-module-identity-in-the-backend.md.\n const copies = getShapeRegistryInstanceCount();\n if (copies > 1) {\n return (\n `${base}\\n\\n` +\n `NOTE: ${copies} copies of the shape registry have loaded in this process. If this ` +\n `property is declared, it almost certainly registered on a different copy than the ` +\n `one validating here, and the declaration is not the problem. This happens when part ` +\n `of the app resolves a framework package to its source and part to its built output.`\n );\n }\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Constraint components\n// ---------------------------------------------------------------------------\n\n/** What a constraint check needs to know about the property it is checking. */\ninterface PropertyContext {\n shape: NodeShapeData;\n propertyShape: PropertyShapeData;\n /** Dot-joined label path from the root of the validated object. */\n property: string;\n focusNode?: string;\n mode: ValidationMode;\n}\n\n/**\n * A constraint check. Receives the property's values already normalized to an\n * array (a single value becomes a one-element array) and returns any violations.\n */\ntype ConstraintCheck = (values: unknown[], ctx: PropertyContext) => ValidationResult[];\n\n/**\n * `sh:value` must be an RDF term. A literal or a node reference is one; a plain\n * object, array or function is not, so it is left off rather than emitted as\n * something no store could materialize — the message still names it.\n */\nfunction asTerm(value: unknown): LiteralTerm | NodeReferenceValue | undefined {\n if (isScalarValue(value)) return value as LiteralTerm;\n if (isNodeReference(value)) return {id: (value as NodeReferenceValue).id};\n return undefined;\n}\n\n/**\n * A violation about the node itself rather than one of its property shapes —\n * `sh:sourceShape` is the node shape, and there is no `sh:resultPath` (an\n * undeclared key has no property IRI to point at).\n */\nfunction nodeViolation(\n shape: NodeShapeData,\n ctx: {focusNode?: string},\n component: NodeReferenceValue,\n message: string,\n propertyPath?: string,\n value?: unknown,\n): ValidationResult {\n const result: ValidationResult = {\n sourceConstraintComponent: component,\n resultSeverity: shacl.Violation,\n resultMessage: message,\n };\n if (ctx.focusNode) result.focusNode = {id: ctx.focusNode};\n if (propertyPath) result.propertyPath = propertyPath;\n const term = asTerm(value);\n if (term !== undefined) result.value = term;\n if (shape.id) result.sourceShape = {id: shape.id};\n return result;\n}\n\n/**\n * Build a result, omitting absent keys entirely — an `undefined` value is not a\n * property the create pipeline should see.\n */\nfunction violation(\n ctx: PropertyContext,\n component: NodeReferenceValue,\n message: string,\n value?: unknown,\n): ValidationResult {\n const result: ValidationResult = {\n sourceConstraintComponent: component,\n resultSeverity: shacl.Violation,\n resultMessage: message,\n };\n if (ctx.focusNode) result.focusNode = {id: ctx.focusNode};\n const path = ctx.propertyShape.path as NodeReferenceValue | undefined;\n if (path?.id) result.resultPath = {id: path.id};\n if (ctx.property) result.propertyPath = ctx.property;\n const term = asTerm(value);\n if (term !== undefined) result.value = term;\n const sourceShape = ctx.propertyShape.id || ctx.shape.id;\n if (sourceShape) result.sourceShape = {id: sourceShape};\n return result;\n}\n\n/** The label used in messages — the property's own label, not its nested path. */\nfunction labelOf(ps: PropertyShapeData): string {\n return ps.label || ps.id;\n}\n\n/** `sh:maxCount` — no more values than the shape allows. */\nconst maxCountCheck: ConstraintCheck = (values, ctx) => {\n const {maxCount} = ctx.propertyShape;\n if (typeof maxCount !== 'number' || values.length <= maxCount) return [];\n return [\n violation(\n ctx,\n shacl.MaxCountConstraintComponent,\n `Property '${labelOf(ctx.propertyShape)}' allows at most ${maxCount} value(s), but ${values.length} were provided.`,\n ),\n ];\n};\n\n/** `sh:minCount` — at least as many values as the shape requires. */\nconst minCountCheck: ConstraintCheck = (values, ctx) => {\n const {minCount} = ctx.propertyShape;\n if (typeof minCount !== 'number' || minCount <= 0 || values.length >= minCount) return [];\n return [\n violation(\n ctx,\n shacl.MinCountConstraintComponent,\n `Property '${labelOf(ctx.propertyShape)}' requires at least ${minCount} value(s), but ${values.length} were provided.`,\n ),\n ];\n};\n\n/** True when the property clearly accepts only literal values. */\nfunction expectsLiteral(ps: PropertyShapeData): boolean {\n if (ps.nodeKind) return ps.nodeKind.id === shacl.Literal.id;\n return !!ps.datatype && !ps.valueShape && !ps.class;\n}\n\n/**\n * True when the property clearly accepts only nodes (IRIs/blank nodes). `sh:class` counts\n * as much as `sh:node`: a value that is an instance of a class is a node, whether or not\n * the property names a shape for it.\n */\nfunction expectsNode(ps: PropertyShapeData): boolean {\n if (ps.nodeKind) {\n return (\n ps.nodeKind.id === shacl.IRI.id ||\n ps.nodeKind.id === shacl.BlankNode.id ||\n ps.nodeKind.id === shacl.BlankNodeOrIRI.id\n );\n }\n return !!(ps.valueShape || ps.class);\n}\n\nfunction isScalarValue(value: unknown): boolean {\n return (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value instanceof Date\n );\n}\n\n/**\n * `sh:nodeKind` — literal properties reject nodes/objects, relation properties\n * reject bare scalars. Ambiguous kinds (`sh:IRIOrLiteral`, or no `nodeKind` and\n * no `datatype`/`valueShape`/`class` to infer from) are not enforced.\n */\nconst nodeKindCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n const literalExpected = expectsLiteral(ps);\n const nodeExpected = expectsNode(ps);\n if (!literalExpected && !nodeExpected) return [];\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n if (!isCheckableElement(el)) continue;\n const scalar = isScalarValue(el);\n if (literalExpected && !scalar) {\n results.push(\n violation(\n ctx,\n shacl.NodeKindConstraintComponent,\n `Property '${labelOf(ps)}' is a literal property but was given a ${typeof el === 'object' ? 'node/object' : typeof el} value.`,\n el,\n ),\n );\n } else if (nodeExpected && scalar) {\n results.push(\n violation(\n ctx,\n shacl.NodeKindConstraintComponent,\n `Property '${labelOf(ps)}' is a relation (object) property but was given a literal (${typeof el}). Provide a {id} reference or a nested object.`,\n el,\n ),\n );\n }\n }\n return results;\n};\n\n/**\n * An element worth checking: a concrete value rather than something whose final\n * form is decided elsewhere (an expression, a context ref, an absent value).\n */\nfunction isCheckableElement(el: unknown): boolean {\n return el !== null && el !== undefined && !isExpressionNode(el) && !asContextRef(el);\n}\n\nconst XSD_BASE = xsd.string.id.slice(0, -'string'.length);\n\n/** `xsd:integer` rather than the full IRI, when the datatype is an XSD one. */\nfunction datatypeLabel(datatype: NodeReferenceValue): string {\n return datatype.id.startsWith(XSD_BASE)\n ? `xsd:${datatype.id.slice(XSD_BASE.length)}`\n : datatype.id;\n}\n\n/** How a value reads in a message — its JS kind, which is what went wrong. */\nfunction describeValue(value: unknown): string {\n if (value instanceof Date) return 'a Date';\n if (Array.isArray(value)) return 'an array';\n if (typeof value === 'number') return Number.isInteger(value) ? 'a whole number' : 'a decimal number';\n if (typeof value === 'object') return 'a node/object';\n return `a ${typeof value}`;\n}\n\nconst isFiniteNumber = (v: unknown) => typeof v === 'number' && Number.isFinite(v);\n\n/**\n * What each XSD datatype accepts as a JavaScript value.\n *\n * This matters more than a normal type check: mutation literals are typed from\n * the *JavaScript* type when they reach SPARQL (`irToAlgebra`), not from the\n * declared datatype — a number becomes `xsd:integer`/`xsd:double`, a boolean\n * `xsd:boolean`, a `Date` `xsd:dateTime`, and a string an untyped literal. So a\n * string handed to an `xsd:integer` property does not merely skip a check, it\n * writes the wrong RDF term. Rejecting it is a correctness fix.\n *\n * `xsd:date` and `xsd:dateTime` take a `Date` and nothing else — one representation for a point\n * in time, rather than a JS object and a hand-written lexical string that behave differently.\n * The serializer derives the right lexical form from the declared datatype\n * (`irToAlgebra.dateToTerm`), so an `xsd:date` property gets `\"2020-06-15\"^^xsd:date` from the\n * same `Date` an `xsd:dateTime` property gets a full timestamp from.\n *\n * `xsd:time` is the exception, and takes a STRING. A `Date` cannot express a time of day without\n * inventing a date to carry it: the date half is meaningless, has to be discarded on\n * serialization, and makes two identical clock times on different days compare unequal. JS has\n * no time-only type — `Temporal.PlainTime` is the right answer and is not available yet — so the\n * lexical form is the honest representation. It is pattern-checked here, and `irToAlgebra` types\n * it from the declared datatype so it is written `\"10:30:00\"^^xsd:time` rather than as a plain\n * literal.\n *\n * Datatypes with no obvious JS counterpart (`xsd:duration`, `xsd:gYear`,\n * `xsd:Bytes`) are not checked.\n */\n/**\n * `HH:MM:SS` with optional milliseconds and optional timezone.\n *\n * Ranges are enforced by the pattern rather than parsed: hours 00-23, minutes and seconds 00-59,\n * so \"25:00:00\" is rejected where a looser `\\d{2}` would let it through and write a malformed\n * literal. The optional `Z`/offset is included because it is valid `xsd:time` — rejecting\n * \"14:30:00Z\" would make this stricter than the datatype it validates.\n */\nconst XSD_TIME_PATTERN = /^([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d{1,3})?(Z|[+-]([01]\\d|2[0-3]):[0-5]\\d)?$/;\n\nconst DATATYPE_RULES: Record<string, {accepts: (v: unknown) => boolean; expected: string}> = {\n [xsd.string.id]: {accepts: (v) => typeof v === 'string', expected: 'a string'},\n [xsd.boolean.id]: {accepts: (v) => typeof v === 'boolean', expected: 'a boolean'},\n [xsd.integer.id]: {accepts: (v) => isFiniteNumber(v) && Number.isInteger(v), expected: 'a whole number'},\n [xsd.long.id]: {accepts: (v) => isFiniteNumber(v) && Number.isInteger(v), expected: 'a whole number'},\n [xsd.decimal.id]: {accepts: isFiniteNumber, expected: 'a number'},\n [xsd.float.id]: {accepts: isFiniteNumber, expected: 'a number'},\n [xsd.double.id]: {accepts: isFiniteNumber, expected: 'a number'},\n [xsd.date.id]: {accepts: (v) => v instanceof Date, expected: 'a Date'},\n [xsd.dateTime.id]: {accepts: (v) => v instanceof Date, expected: 'a Date'},\n [xsd.time.id]: {\n accepts: (v) => typeof v === 'string' && XSD_TIME_PATTERN.test(v),\n expected: 'a time string like \"14:30:00\", \"14:30:00.250\" or \"14:30:00Z\"',\n },\n};\n\n/** `sh:datatype` — the value's JavaScript type must match the declared datatype. */\nconst datatypeCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n if (!ps.datatype) return [];\n const rule = DATATYPE_RULES[ps.datatype.id];\n if (!rule) return [];\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n // A node reference is a node-kind problem, not a datatype one — one\n // violation per mistake, reported by the check that owns it.\n if (!isCheckableElement(el) || isNodeReference(el) || rule.accepts(el)) continue;\n results.push(\n violation(\n ctx,\n shacl.DatatypeConstraintComponent,\n `Property '${labelOf(ps)}' expects ${datatypeLabel(ps.datatype)} (${rule.expected}), but was given ${describeValue(el)}.`,\n el,\n ),\n );\n }\n return results;\n};\n\n/** The four `sh:min/maxInclusive/Exclusive` range constraints, on numbers. */\nconst rangeCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n const bounds: {\n limit: unknown;\n component: NodeReferenceValue;\n ok: (v: number, limit: number) => boolean;\n phrase: string;\n }[] = [\n {limit: ps.minInclusive, component: shacl.MinInclusiveConstraintComponent, ok: (v, l) => v >= l, phrase: 'at least'},\n {limit: ps.maxInclusive, component: shacl.MaxInclusiveConstraintComponent, ok: (v, l) => v <= l, phrase: 'at most'},\n {limit: ps.minExclusive, component: shacl.MinExclusiveConstraintComponent, ok: (v, l) => v > l, phrase: 'greater than'},\n {limit: ps.maxExclusive, component: shacl.MaxExclusiveConstraintComponent, ok: (v, l) => v < l, phrase: 'less than'},\n ];\n const active = bounds.filter((b) => typeof b.limit === 'number');\n if (!active.length) return [];\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n // Non-numbers are the datatype check's business.\n if (!isCheckableElement(el) || typeof el !== 'number') continue;\n for (const bound of active) {\n if (bound.ok(el, bound.limit as number)) continue;\n results.push(\n violation(\n ctx,\n bound.component,\n `Property '${labelOf(ps)}' must be ${bound.phrase} ${bound.limit}, but was given ${el}.`,\n el,\n ),\n );\n }\n }\n return results;\n};\n\n/** `sh:minLength` / `sh:maxLength`, on strings. */\nconst lengthCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n if (typeof ps.minLength !== 'number' && typeof ps.maxLength !== 'number') return [];\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n if (!isCheckableElement(el) || typeof el !== 'string') continue;\n if (typeof ps.minLength === 'number' && el.length < ps.minLength) {\n results.push(\n violation(\n ctx,\n shacl.MinLengthConstraintComponent,\n `Property '${labelOf(ps)}' must be at least ${ps.minLength} character(s), but was given ${el.length}.`,\n el,\n ),\n );\n }\n if (typeof ps.maxLength === 'number' && el.length > ps.maxLength) {\n results.push(\n violation(\n ctx,\n shacl.MaxLengthConstraintComponent,\n `Property '${labelOf(ps)}' must be at most ${ps.maxLength} character(s), but was given ${el.length}.`,\n el,\n ),\n );\n }\n }\n return results;\n};\n\n/** `sh:pattern` — the string form of the value must match the shape's regex. */\nconst patternCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n if (!ps.pattern) return [];\n // Rebuild without `g`/`y`: those carry `lastIndex` between calls, so a shared\n // shape regex would match every other value.\n const regex = new RegExp(ps.pattern.source, ps.pattern.flags.replace(/[gy]/g, ''));\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n if (!isCheckableElement(el) || typeof el !== 'string') continue;\n if (regex.test(el)) continue;\n results.push(\n violation(\n ctx,\n shacl.PatternConstraintComponent,\n `Property '${labelOf(ps)}' must match ${String(ps.pattern)}, but was given \"${el}\".`,\n el,\n ),\n );\n }\n return results;\n};\n\n/** `sh:in` — the value must be one of the shape's allowed values. */\nconst inCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n if (!ps.in?.length) return [];\n const allowed = ps.in;\n const matches = (el: unknown) =>\n allowed.some((a) =>\n isNodeReferenceValue(a)\n ? isNodeReference(el) && (el as NodeReferenceValue).id === a.id\n : a === el,\n );\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n if (!isCheckableElement(el) || matches(el)) continue;\n const rendered = allowed\n .map((a) => (isNodeReferenceValue(a) ? a.id : JSON.stringify(a)))\n .join(', ');\n results.push(\n violation(\n ctx,\n shacl.InConstraintComponent,\n `Property '${labelOf(ps)}' must be one of [${rendered}].`,\n el,\n ),\n );\n }\n return results;\n};\n\n/**\n * The registry. Every property-level constraint the library enforces lives here;\n * adding another SHACL component is one more entry plus its test.\n *\n * Split by what each kind of check needs to see. **Cardinality** needs the\n * property's whole value set, so it cannot run against a set modification —\n * `{add: […]}` changes a count that lives in the store. **Value** checks need\n * only the value in hand, so they run everywhere a concrete value appears,\n * including inside `add`.\n *\n * Cardinality runs first when it runs at all: a count problem explains itself\n * better than the per-value violations that would follow it.\n */\nconst CARDINALITY_CONSTRAINTS: ConstraintCheck[] = [maxCountCheck, minCountCheck];\n\nconst VALUE_CONSTRAINTS: ConstraintCheck[] = [\n nodeKindCheck,\n datatypeCheck,\n rangeCheck,\n lengthCheck,\n patternCheck,\n inCheck,\n];\n\nconst PROPERTY_CONSTRAINTS: ConstraintCheck[] = [\n ...CARDINALITY_CONSTRAINTS,\n ...VALUE_CONSTRAINTS,\n];\n\n// ---------------------------------------------------------------------------\n// Value classification\n// ---------------------------------------------------------------------------\n\n/**\n * A `{add, remove}` set modification. The resulting value count depends on the\n * node's current state, so cardinality and kind are unknowable here.\n */\nfunction isSetModification(value: unknown): boolean {\n if (typeof value !== 'object' || value === null) return false;\n const obj = value as Record<string, unknown>;\n const expected = (obj.add ? 1 : 0) + (obj.remove ? 1 : 0);\n return expected > 0 && Object.getOwnPropertyNames(obj).length === expected;\n}\n\n/** An object carrying only an `id` — a reference to an existing node, not a description. */\nfunction isNodeReference(value: unknown): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n Object.keys(value).length === 1\n );\n}\n\n/**\n * A value that stands for something resolved later — an expression, a query\n * context reference, a callback, or nothing at all.\n *\n * Must be ruled out *before* anything reads properties off the value: a resolved\n * context ref is a query proxy that throws on any undecorated key, so probing it\n * for `.add` is not a safe way to ask what it is.\n */\nfunction isDeferredValue(value: unknown): boolean {\n return (\n value === undefined ||\n typeof value === 'function' ||\n isExpressionNode(value) ||\n !!asContextRef(value)\n );\n}\n\n/** Values whose final shape isn't knowable without the store or a lowering pass. */\nfunction isOpaqueValue(value: unknown): boolean {\n return isDeferredValue(value) || isSetModification(value);\n}\n\n/** A nested node description — an object to descend into, rather than a leaf value. */\nfunction isNodeDescription(value: unknown): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !isNodeReference(value) &&\n !isOpaqueValue(value)\n );\n}\n\n// ---------------------------------------------------------------------------\n// Entry points\n// ---------------------------------------------------------------------------\n\n/**\n * What can be validated against: a shape class (`Person`) or the plain\n * `NodeShapeData` the decorators generate (`Person.shape`, or the same object\n * obtained anywhere else). The two are interchangeable — the class is unwrapped\n * to its `shape` and nothing else about it is read.\n */\nexport type ValidatableShape = NodeShapeData | {shape: NodeShapeData};\n\nfunction resolveShapeData(shape: ValidatableShape): NodeShapeData {\n const resolved = 'propertyShapes' in shape ? shape : (shape as {shape: NodeShapeData}).shape;\n if (!resolved) {\n throw new Error(\n 'validate() requires a node shape or a shape class with a static `shape`. ' +\n 'Did you pass an unregistered class (missing @linkedShape)?',\n );\n }\n return resolved as NodeShapeData;\n}\n\n/**\n * Validate a plain data object against a node shape.\n *\n * Never throws for invalid *data* — a violation is a result, not an exception.\n * (It does throw when the *shape* argument itself is unusable.)\n *\n * ```ts\n * const report = validate(Person, {name: ['a', 'b']});\n * report.conforms; // false\n * report.results[0].sourceConstraintComponent.id; // …shacl#MaxCountConstraintComponent\n * ```\n *\n * **A shape class is optional.** The plain `NodeShapeData` the decorators\n * generate validates identically, so a caller that only ever holds shape\n * objects needs no class reference:\n *\n * ```ts\n * validate(Person, data); // ≡\n * validate(Person.shape, data); // same report\n * ```\n *\n * That holds even though a shape object carries neither its inherited property\n * shapes (a subclass's `propertyShapes` holds only its own) nor its nested\n * shapes (`valueShape` is a bare `{id}`): both are resolved through the shape\n * registry by id. A shape whose id is not registered therefore cannot be fully\n * checked, and says so — see {@link unresolvedValueShapeMessage} and the\n * inherited-properties check in `validateNode` — rather than reporting a node\n * as conforming on the strength of a branch it could not look at.\n */\nexport function validate(\n shape: ValidatableShape,\n data: unknown,\n options: ValidateOptions = {},\n): ValidationReport {\n const {mode = 'complete', maxDepth = 10} = options;\n const results = validateNode(resolveShapeData(shape), data, {\n mode,\n maxDepth,\n depth: 0,\n prefix: '',\n });\n return {\n conforms: !results.some((r) => r.resultSeverity.id === shacl.Violation.id),\n results,\n };\n}\n\n/** {@link validate}, but throws a {@link ShapeValidationError} when the data doesn't conform. */\nexport function assertValid(\n shape: ValidatableShape,\n data: unknown,\n options: ValidateOptions = {},\n): void {\n const report = validate(shape, data, options);\n if (!report.conforms) throw new ShapeValidationError(report);\n}\n\n// ---------------------------------------------------------------------------\n// Walk\n// ---------------------------------------------------------------------------\n\ninterface WalkContext {\n mode: ValidationMode;\n maxDepth: number;\n depth: number;\n /** Dot-joined label path of the node being validated (`''` at the root). */\n prefix: string;\n focusNode?: string;\n}\n\nfunction validateNode(\n shape: NodeShapeData,\n data: unknown,\n ctx: WalkContext,\n): ValidationResult[] {\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n return [\n nodeViolation(\n shape,\n ctx,\n shacl.NodeConstraintComponent,\n `Expected an object describing '${shape.label || shape.id}', but got ${data === null ? 'null' : typeof data}.`,\n ctx.prefix,\n data,\n ),\n ];\n }\n\n const obj = data as Record<string, unknown>;\n const propertyShapes = getUniquePropertyShapes(shape);\n const byLabel = new Map(propertyShapes.map((ps) => [ps.label, ps]));\n const focusNode =\n typeof obj.__id === 'string'\n ? obj.__id\n : typeof obj.id === 'string'\n ? obj.id\n : ctx.focusNode;\n const results: ValidationResult[] = [];\n\n // A shape declaring a superclass carries only its *own* property shapes; the\n // inherited ones are resolved through the registry by id. If this shape's id\n // is not registered, that resolution quietly yields half a shape — required\n // inherited properties go unchecked, and any that *are* supplied look\n // undeclared. Report it rather than let a partial shape pass as a clean bill.\n //\n // \"Registered\" means present in EITHER registry. Checking only for a class rejected\n // exactly the shapes the metamodel work exists to support: a data-only child is\n // registered, its parent resolves, and its inherited properties are checked — it simply\n // has no class, which is not a defect.\n if (shape.extends?.id && !getShapeClass(shape.id) && !getNodeShape(shape.id)) {\n results.push(\n nodeViolation(\n shape,\n {focusNode},\n shacl.NodeConstraintComponent,\n `Cannot resolve the properties '${shape.label || shape.id}' inherits from '${shape.extends.id}': shape '${shape.id}' is not registered, so only its own properties could be checked.`,\n ctx.prefix,\n ),\n );\n }\n\n // Presence of required properties — only decidable for a complete description.\n if (ctx.mode === 'complete') {\n for (const ps of propertyShapes) {\n if (typeof ps.minCount !== 'number' || ps.minCount <= 0) continue;\n if (ps.label in obj) continue;\n results.push(\n violation(\n {shape, propertyShape: ps, property: join(ctx.prefix, ps.label), focusNode, mode: ctx.mode},\n shacl.MinCountConstraintComponent,\n `Property '${labelOf(ps)}' requires at least ${ps.minCount} value(s), but none were provided.`,\n ),\n );\n }\n }\n\n // The values actually provided.\n for (const [key, value] of Object.entries(obj)) {\n if (RESERVED_KEYS.has(key)) continue;\n const propertyShape = byLabel.get(key);\n if (!propertyShape) {\n results.push(\n nodeViolation(\n shape,\n {...ctx, focusNode},\n shacl.ClosedConstraintComponent,\n undeclaredPropertyMessage(key, shape),\n join(ctx.prefix, key),\n value,\n ),\n );\n continue;\n }\n results.push(\n ...validateProperty(value, {\n shape,\n propertyShape,\n property: join(ctx.prefix, key),\n focusNode,\n mode: ctx.mode,\n }, ctx),\n );\n }\n\n return results;\n}\n\nfunction validateProperty(\n value: unknown,\n propCtx: PropertyContext,\n walk: WalkContext,\n): ValidationResult[] {\n const ps = propCtx.propertyShape;\n\n // `null` clears the property — the same as providing zero values, so clearing\n // a required one is a cardinality violation (both spellings behave alike).\n if (value === null) {\n if (typeof ps.minCount === 'number' && ps.minCount > 0) {\n return [\n violation(\n propCtx,\n shacl.MinCountConstraintComponent,\n `Property '${labelOf(ps)}' requires at least ${ps.minCount} value(s) and cannot be cleared.`,\n ),\n ];\n }\n return [];\n }\n\n // Ruled out first: reading `.add` off a resolved context proxy would throw.\n if (isDeferredValue(value)) return [];\n\n // A set modification adds to and removes from what the store already holds,\n // so the resulting *count* is unknowable here — but each added value is as\n // checkable as any other, and skipping them let mistyped literals through the\n // one door the rest of this module closes. `remove` takes `{id}` references\n // only, which normalization enforces on its own.\n if (isSetModification(value)) {\n const {add} = value as {add?: unknown};\n if (add === undefined) return [];\n return runChecks(VALUE_CONSTRAINTS, toValues(add), propCtx, walk);\n }\n\n return runChecks(PROPERTY_CONSTRAINTS, toValues(value), propCtx, walk);\n}\n\n/** A property's value(s) as an array — a single value becomes a one-element one. */\nfunction toValues(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [value];\n}\n\n/**\n * Run a set of constraint checks over a property's values, then descend into any\n * nested node descriptions among them (`sh:node`-style recursion). A bare `{id}`\n * is a reference to an existing node and has nothing to validate; an object with\n * an id *and* data is a nested create with a predefined id.\n */\nfunction runChecks(\n checks: ConstraintCheck[],\n values: unknown[],\n propCtx: PropertyContext,\n walk: WalkContext,\n): ValidationResult[] {\n const results: ValidationResult[] = [];\n for (const check of checks) {\n results.push(...check(values, propCtx));\n }\n\n if (walk.depth < walk.maxDepth) {\n for (const el of values) {\n if (!isNodeDescription(el)) continue;\n const nestedShape = resolveValueShape(propCtx.propertyShape, el);\n if (!nestedShape) {\n // The value is a node description we have no shape for, so nothing about\n // it can be checked. Silently skipping would report the whole node as\n // conforming on the strength of a branch never looked at.\n results.push(\n violation(\n propCtx,\n shacl.NodeConstraintComponent,\n unresolvedValueShapeMessage(propCtx.propertyShape),\n ),\n );\n continue;\n }\n results.push(\n ...validateNode(nestedShape, el, {\n ...walk,\n depth: walk.depth + 1,\n prefix: propCtx.property,\n focusNode: undefined,\n }),\n );\n }\n }\n\n return results;\n}\n\n/**\n * Why a nested value could not be resolved to a shape — the property named one\n * that is not registered, or named none and the value did not carry one either.\n * Both are actionable, and they are fixed differently.\n */\nfunction unresolvedValueShapeMessage(ps: PropertyShapeData): string {\n const label = labelOf(ps);\n return ps.valueShape\n ? `Cannot validate the value of '${label}': its shape '${ps.valueShape.id}' is not registered.`\n : `Cannot validate the value of '${label}': the property declares no shape for its values. ` +\n `Add a 'shape' to its @objectProperty decorator, or give the value a 'shape' key.`;\n}\n\n/**\n * The shape a nested value should be validated against: the shape class carried\n * in the value's reserved `shape` key when the property declares no `valueShape`\n * or the key names a subclass of it, otherwise the declared `valueShape`. Mirrors\n * `convertUpdateValue`; returns undefined when neither is available.\n */\nfunction resolveValueShape(\n ps: PropertyShapeData,\n value: unknown,\n): NodeShapeData | undefined {\n const own = (value as {shape?: {shape?: NodeShapeData}}).shape?.shape;\n if (!ps.valueShape) return own;\n const declared = getShapeClass(ps.valueShape)?.shape;\n // A value naming a subclass of the declared shape is validated as that subclass.\n if (own && declared && isSubShapeOf(own, declared)) return own;\n return declared;\n}\n\nfunction join(prefix: string, label: string): string {\n return prefix ? `${prefix}.${label}` : label;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/shapes/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\n/**\n * SHACL-aligned validation of plain data objects against a node shape.\n *\n * One entry point — {@link validate} — used by the create and update pipelines\n * (via `MutationQueryFactory.describe()`) and directly by callers that want to\n * know how well an object fits a shape without building a mutation.\n *\n * **Shape of the output.** This library has no triple/Turtle layer and this\n * module does not add one: a {@link ValidationReport} is plain JavaScript. It is\n * however 1-1 with the SHACL vocabulary — one key per SHACL property, named\n * after it, holding a value the mutation pipeline accepts (a literal, or a\n * `{id}` node reference for IRI-valued properties). So a report can be\n * materialized by an ordinary create query as soon as shape classes for\n * `sh:ValidationReport` / `sh:ValidationResult` exist, with no transform step:\n *\n * ```ts\n * const report = validate(Slide, data);\n * await ValidationReport.create(report); // once those shape classes exist\n * ```\n *\n * Two deliberate departures, both documented on the types: `results` is plural\n * where SHACL's repeated property is `sh:result`, and `propertyPath` is a\n * non-SHACL locator. Both map cleanly — a shape class chooses its own labels for\n * SHACL paths, and an extension property is legal on a SHACL report.\n *\n * **Coverage.** Cardinality (`sh:minCount` / `sh:maxCount`), node kind (literal\n * vs relation), undeclared properties (as `sh:closed`), `sh:datatype`, the four\n * `sh:min/maxInclusive/Exclusive` bounds, `sh:min/maxLength`, `sh:pattern` and\n * `sh:in`. Each is one entry in {@link CARDINALITY_CONSTRAINTS} or\n * {@link VALUE_CONSTRAINTS}, so adding another is one function and one test.\n *\n * Not covered: `sh:languageIn` / `sh:uniqueLang` (skipped at serialization time\n * too, so there is no metadata to check against) and `sh:hasValue`.\n */\nimport {getShapeRegistryInstanceCount, getQueryShapeClass} from '../utils/ShapeClass.js';\nimport {shacl} from '../ontologies/shacl.js';\nimport {xsd} from '../ontologies/xsd.js';\nimport {isNodeReferenceValue, type NodeReferenceValue} from '../utils/NodeReference.js';\nimport {getUniquePropertyShapes} from './nodeShapeData.js';\nimport type {NodeShapeData, PropertyShapeData} from './nodeShapeData.js';\nimport {getNodeShape, getShapeClass, isSubShapeOf} from '../utils/ShapeClass.js';\nimport {isExpressionNode} from '../expressions/ExpressionNode.js';\nimport {asContextRef} from '../queries/QueryContext.js';\n\n/**\n * Which constraints apply to the data being validated.\n *\n * - `complete` — the object describes a whole node (a create, or a standalone\n * object being checked for fit). Properties absent from the data are genuinely\n * absent, so `sh:minCount` presence is checkable.\n * - `partial` — the object describes a change to an existing node (an update).\n * The store holds whatever the payload does not mention, so presence is\n * unknowable; only the values actually provided are checked.\n */\nexport type ValidationMode = 'complete' | 'partial';\n\n/**\n * A single constraint violation — an `sh:ValidationResult`.\n *\n * Every key is the local name of the SHACL property it carries, and every value\n * is in a form the create pipeline accepts (a literal, or a `{id}` node\n * reference for IRI-valued properties). A shape class declaring these\n * properties therefore materializes a result with no transform step:\n * `ValidationResult.create(result)`. The one non-SHACL key is `propertyPath`;\n * see {@link ValidationReport}.\n */\nexport interface ValidationResult {\n /** `sh:focusNode` — the node the violation is about, when its id is known. */\n focusNode?: NodeReferenceValue;\n /** `sh:resultPath` — the IRI of the property the violation is about. */\n resultPath?: NodeReferenceValue;\n /**\n * `sh:value` — the offending value, present only when it is an RDF term (a\n * literal or a node reference). Cardinality violations are about the property\n * rather than any one value, so they carry none.\n */\n value?: LiteralTerm | NodeReferenceValue;\n /** `sh:sourceShape` — the node or property shape carrying the constraint. */\n sourceShape?: NodeReferenceValue;\n /** `sh:sourceConstraintComponent` — which SHACL constraint failed. */\n sourceConstraintComponent: NodeReferenceValue;\n /** `sh:resultSeverity` — `sh:Violation`, `sh:Warning` or `sh:Info`. */\n resultSeverity: NodeReferenceValue;\n /** `sh:resultMessage` — human-readable explanation. */\n resultMessage: string;\n /**\n * **Not SHACL.** The property's label, dot-joined through nested shapes\n * (`author.fullName`) — the locator a caller needs to point at a field in the\n * object they passed in, which `sh:resultPath` alone cannot give (it names the\n * property, not where the nesting reached it). Materializes like any other\n * property once a shape class declares it; drop it for a pure-SHACL result.\n */\n propertyPath?: string;\n}\n\n/**\n * The outcome of a validation run — an `sh:ValidationReport`.\n *\n * Plain objects, 1-1 with the SHACL vocabulary, so a report can later be\n * materialized through an ordinary create query against shape classes for\n * `sh:ValidationReport` / `sh:ValidationResult` — whether or not this library\n * ever ships those classes. `results` is the sole plural rename (SHACL's\n * property is `sh:result`, repeated); a shape class maps it with\n * `@objectProperty({path: shacl.result, …}) get results()`.\n */\nexport interface ValidationReport {\n /** `sh:conforms` — true when there are no `sh:Violation`-severity results. */\n conforms: boolean;\n /** `sh:result` — every violation found, in deterministic order. */\n results: ValidationResult[];\n}\n\n/** The literal types the mutation pipeline accepts as a value. */\ntype LiteralTerm = string | number | boolean | Date;\n\nexport interface ValidateOptions {\n /** Defaults to `complete`. */\n mode?: ValidationMode;\n /** How deep to descend into nested node descriptions. Defaults to 10. */\n maxDepth?: number;\n}\n\n/** Thrown by {@link assertValid} — carries the full report, not just the first violation. */\nexport class ShapeValidationError extends Error {\n readonly report: ValidationReport;\n constructor(report: ValidationReport) {\n super(report.results.map((r) => r.resultMessage).join('\\n'));\n this.name = 'ShapeValidationError';\n this.report = report;\n }\n}\n\n/**\n * Keys that carry metadata about the node rather than a property value: `id` /\n * `__id` name it, and `shape` names the shape of a nested value when the\n * property shape itself doesn't declare one (see `convertUpdateValue`).\n */\nconst RESERVED_KEYS = new Set(['id', '__id', 'shape']);\n\n/**\n * The message for an undeclared property key. Shared with the normalization path\n * in `MutationQuery`, which needs the same guard to build a field at all.\n */\nexport function undeclaredPropertyMessage(key: string, shape: NodeShapeData): string {\n const shapeName = shape.label || shape.id?.split('/').pop();\n const base =\n `Invalid property key: ${key}. The shape ${shapeName} does not have a registered ` +\n `property with this name. Make sure the get/set method exists, and that it uses a ` +\n `@objectProperty or @literalProperty decorator.`;\n\n // If more than one copy of the shape registry module has evaluated, this message is\n // very probably lying: the property IS declared, on a copy this code cannot see.\n // Saying so here is the whole point — the previous version of this error accused\n // correct application code, and finding the real cause took a day of eliminating\n // innocent suspects. See docs/reports/043-module-identity-in-the-backend.md.\n const copies = getShapeRegistryInstanceCount();\n if (copies > 1) {\n return (\n `${base}\\n\\n` +\n `NOTE: ${copies} copies of the shape registry have loaded in this process. If this ` +\n `property is declared, it almost certainly registered on a different copy than the ` +\n `one validating here, and the declaration is not the problem. This happens when part ` +\n `of the app resolves a framework package to its source and part to its built output.`\n );\n }\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Constraint components\n// ---------------------------------------------------------------------------\n\n/** What a constraint check needs to know about the property it is checking. */\ninterface PropertyContext {\n shape: NodeShapeData;\n propertyShape: PropertyShapeData;\n /** Dot-joined label path from the root of the validated object. */\n property: string;\n focusNode?: string;\n mode: ValidationMode;\n}\n\n/**\n * A constraint check. Receives the property's values already normalized to an\n * array (a single value becomes a one-element array) and returns any violations.\n */\ntype ConstraintCheck = (values: unknown[], ctx: PropertyContext) => ValidationResult[];\n\n/**\n * `sh:value` must be an RDF term. A literal or a node reference is one; a plain\n * object, array or function is not, so it is left off rather than emitted as\n * something no store could materialize — the message still names it.\n */\nfunction asTerm(value: unknown): LiteralTerm | NodeReferenceValue | undefined {\n if (isScalarValue(value)) return value as LiteralTerm;\n if (isNodeReference(value)) return {id: (value as NodeReferenceValue).id};\n return undefined;\n}\n\n/**\n * A violation about the node itself rather than one of its property shapes —\n * `sh:sourceShape` is the node shape, and there is no `sh:resultPath` (an\n * undeclared key has no property IRI to point at).\n */\nfunction nodeViolation(\n shape: NodeShapeData,\n ctx: {focusNode?: string},\n component: NodeReferenceValue,\n message: string,\n propertyPath?: string,\n value?: unknown,\n): ValidationResult {\n const result: ValidationResult = {\n sourceConstraintComponent: component,\n resultSeverity: shacl.Violation,\n resultMessage: message,\n };\n if (ctx.focusNode) result.focusNode = {id: ctx.focusNode};\n if (propertyPath) result.propertyPath = propertyPath;\n const term = asTerm(value);\n if (term !== undefined) result.value = term;\n if (shape.id) result.sourceShape = {id: shape.id};\n return result;\n}\n\n/**\n * Build a result, omitting absent keys entirely — an `undefined` value is not a\n * property the create pipeline should see.\n */\nfunction violation(\n ctx: PropertyContext,\n component: NodeReferenceValue,\n message: string,\n value?: unknown,\n): ValidationResult {\n const result: ValidationResult = {\n sourceConstraintComponent: component,\n resultSeverity: shacl.Violation,\n resultMessage: message,\n };\n if (ctx.focusNode) result.focusNode = {id: ctx.focusNode};\n const path = ctx.propertyShape.path as NodeReferenceValue | undefined;\n if (path?.id) result.resultPath = {id: path.id};\n if (ctx.property) result.propertyPath = ctx.property;\n const term = asTerm(value);\n if (term !== undefined) result.value = term;\n const sourceShape = ctx.propertyShape.id || ctx.shape.id;\n if (sourceShape) result.sourceShape = {id: sourceShape};\n return result;\n}\n\n/** The label used in messages — the property's own label, not its nested path. */\nfunction labelOf(ps: PropertyShapeData): string {\n return ps.label || ps.id;\n}\n\n/** `sh:maxCount` — no more values than the shape allows. */\nconst maxCountCheck: ConstraintCheck = (values, ctx) => {\n const {maxCount} = ctx.propertyShape;\n if (typeof maxCount !== 'number' || values.length <= maxCount) return [];\n return [\n violation(\n ctx,\n shacl.MaxCountConstraintComponent,\n `Property '${labelOf(ctx.propertyShape)}' allows at most ${maxCount} value(s), but ${values.length} were provided.`,\n ),\n ];\n};\n\n/** `sh:minCount` — at least as many values as the shape requires. */\nconst minCountCheck: ConstraintCheck = (values, ctx) => {\n const {minCount} = ctx.propertyShape;\n if (typeof minCount !== 'number' || minCount <= 0 || values.length >= minCount) return [];\n return [\n violation(\n ctx,\n shacl.MinCountConstraintComponent,\n `Property '${labelOf(ctx.propertyShape)}' requires at least ${minCount} value(s), but ${values.length} were provided.`,\n ),\n ];\n};\n\n/** True when the property clearly accepts only literal values. */\nfunction expectsLiteral(ps: PropertyShapeData): boolean {\n if (ps.nodeKind) return ps.nodeKind.id === shacl.Literal.id;\n return !!ps.datatype && !ps.valueShape && !ps.class;\n}\n\n/**\n * True when the property clearly accepts only nodes (IRIs/blank nodes). `sh:class` counts\n * as much as `sh:node`: a value that is an instance of a class is a node, whether or not\n * the property names a shape for it.\n */\nfunction expectsNode(ps: PropertyShapeData): boolean {\n if (ps.nodeKind) {\n return (\n ps.nodeKind.id === shacl.IRI.id ||\n ps.nodeKind.id === shacl.BlankNode.id ||\n ps.nodeKind.id === shacl.BlankNodeOrIRI.id\n );\n }\n return !!(ps.valueShape || ps.class);\n}\n\nfunction isScalarValue(value: unknown): boolean {\n return (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value instanceof Date\n );\n}\n\n/**\n * `sh:nodeKind` — literal properties reject nodes/objects, relation properties\n * reject bare scalars. Ambiguous kinds (`sh:IRIOrLiteral`, or no `nodeKind` and\n * no `datatype`/`valueShape`/`class` to infer from) are not enforced.\n */\nconst nodeKindCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n const literalExpected = expectsLiteral(ps);\n const nodeExpected = expectsNode(ps);\n if (!literalExpected && !nodeExpected) return [];\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n if (!isCheckableElement(el)) continue;\n const scalar = isScalarValue(el);\n if (literalExpected && !scalar) {\n results.push(\n violation(\n ctx,\n shacl.NodeKindConstraintComponent,\n `Property '${labelOf(ps)}' is a literal property but was given a ${typeof el === 'object' ? 'node/object' : typeof el} value.`,\n el,\n ),\n );\n } else if (nodeExpected && scalar) {\n results.push(\n violation(\n ctx,\n shacl.NodeKindConstraintComponent,\n `Property '${labelOf(ps)}' is a relation (object) property but was given a literal (${typeof el}). Provide a {id} reference or a nested object.`,\n el,\n ),\n );\n }\n }\n return results;\n};\n\n/**\n * An element worth checking: a concrete value rather than something whose final\n * form is decided elsewhere (an expression, a context ref, an absent value).\n */\nfunction isCheckableElement(el: unknown): boolean {\n return el !== null && el !== undefined && !isExpressionNode(el) && !asContextRef(el);\n}\n\nconst XSD_BASE = xsd.string.id.slice(0, -'string'.length);\n\n/** `xsd:integer` rather than the full IRI, when the datatype is an XSD one. */\nfunction datatypeLabel(datatype: NodeReferenceValue): string {\n return datatype.id.startsWith(XSD_BASE)\n ? `xsd:${datatype.id.slice(XSD_BASE.length)}`\n : datatype.id;\n}\n\n/** How a value reads in a message — its JS kind, which is what went wrong. */\nfunction describeValue(value: unknown): string {\n if (value instanceof Date) return 'a Date';\n if (Array.isArray(value)) return 'an array';\n if (typeof value === 'number') return Number.isInteger(value) ? 'a whole number' : 'a decimal number';\n if (typeof value === 'object') return 'a node/object';\n return `a ${typeof value}`;\n}\n\nconst isFiniteNumber = (v: unknown) => typeof v === 'number' && Number.isFinite(v);\n\n/**\n * What each XSD datatype accepts as a JavaScript value.\n *\n * This matters more than a normal type check: mutation literals are typed from\n * the *JavaScript* type when they reach SPARQL (`irToAlgebra`), not from the\n * declared datatype — a number becomes `xsd:integer`/`xsd:double`, a boolean\n * `xsd:boolean`, a `Date` `xsd:dateTime`, and a string an untyped literal. So a\n * string handed to an `xsd:integer` property does not merely skip a check, it\n * writes the wrong RDF term. Rejecting it is a correctness fix.\n *\n * `xsd:date` and `xsd:dateTime` take a `Date` and nothing else — one representation for a point\n * in time, rather than a JS object and a hand-written lexical string that behave differently.\n * The serializer derives the right lexical form from the declared datatype\n * (`irToAlgebra.dateToTerm`), so an `xsd:date` property gets `\"2020-06-15\"^^xsd:date` from the\n * same `Date` an `xsd:dateTime` property gets a full timestamp from.\n *\n * `xsd:time` is the exception, and takes a STRING. A `Date` cannot express a time of day without\n * inventing a date to carry it: the date half is meaningless, has to be discarded on\n * serialization, and makes two identical clock times on different days compare unequal. JS has\n * no time-only type — `Temporal.PlainTime` is the right answer and is not available yet — so the\n * lexical form is the honest representation. It is pattern-checked here, and `irToAlgebra` types\n * it from the declared datatype so it is written `\"10:30:00\"^^xsd:time` rather than as a plain\n * literal.\n *\n * Datatypes with no obvious JS counterpart (`xsd:duration`, `xsd:gYear`,\n * `xsd:Bytes`) are not checked.\n */\n/**\n * `HH:MM:SS` with optional milliseconds and optional timezone.\n *\n * Ranges are enforced by the pattern rather than parsed: hours 00-23, minutes and seconds 00-59,\n * so \"25:00:00\" is rejected where a looser `\\d{2}` would let it through and write a malformed\n * literal. The optional `Z`/offset is included because it is valid `xsd:time` — rejecting\n * \"14:30:00Z\" would make this stricter than the datatype it validates.\n */\nconst XSD_TIME_PATTERN = /^([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d{1,3})?(Z|[+-]([01]\\d|2[0-3]):[0-5]\\d)?$/;\n\nconst DATATYPE_RULES: Record<string, {accepts: (v: unknown) => boolean; expected: string}> = {\n [xsd.string.id]: {accepts: (v) => typeof v === 'string', expected: 'a string'},\n [xsd.boolean.id]: {accepts: (v) => typeof v === 'boolean', expected: 'a boolean'},\n [xsd.integer.id]: {accepts: (v) => isFiniteNumber(v) && Number.isInteger(v), expected: 'a whole number'},\n [xsd.long.id]: {accepts: (v) => isFiniteNumber(v) && Number.isInteger(v), expected: 'a whole number'},\n [xsd.decimal.id]: {accepts: isFiniteNumber, expected: 'a number'},\n [xsd.float.id]: {accepts: isFiniteNumber, expected: 'a number'},\n [xsd.double.id]: {accepts: isFiniteNumber, expected: 'a number'},\n [xsd.date.id]: {accepts: (v) => v instanceof Date, expected: 'a Date'},\n [xsd.dateTime.id]: {accepts: (v) => v instanceof Date, expected: 'a Date'},\n [xsd.time.id]: {\n accepts: (v) => typeof v === 'string' && XSD_TIME_PATTERN.test(v),\n expected: 'a time string like \"14:30:00\", \"14:30:00.250\" or \"14:30:00Z\"',\n },\n};\n\n/** `sh:datatype` — the value's JavaScript type must match the declared datatype. */\nconst datatypeCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n if (!ps.datatype) return [];\n const rule = DATATYPE_RULES[ps.datatype.id];\n if (!rule) return [];\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n // A node reference is a node-kind problem, not a datatype one — one\n // violation per mistake, reported by the check that owns it.\n if (!isCheckableElement(el) || isNodeReference(el) || rule.accepts(el)) continue;\n results.push(\n violation(\n ctx,\n shacl.DatatypeConstraintComponent,\n `Property '${labelOf(ps)}' expects ${datatypeLabel(ps.datatype)} (${rule.expected}), but was given ${describeValue(el)}.`,\n el,\n ),\n );\n }\n return results;\n};\n\n/** The four `sh:min/maxInclusive/Exclusive` range constraints, on numbers. */\nconst rangeCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n const bounds: {\n limit: unknown;\n component: NodeReferenceValue;\n ok: (v: number, limit: number) => boolean;\n phrase: string;\n }[] = [\n {limit: ps.minInclusive, component: shacl.MinInclusiveConstraintComponent, ok: (v, l) => v >= l, phrase: 'at least'},\n {limit: ps.maxInclusive, component: shacl.MaxInclusiveConstraintComponent, ok: (v, l) => v <= l, phrase: 'at most'},\n {limit: ps.minExclusive, component: shacl.MinExclusiveConstraintComponent, ok: (v, l) => v > l, phrase: 'greater than'},\n {limit: ps.maxExclusive, component: shacl.MaxExclusiveConstraintComponent, ok: (v, l) => v < l, phrase: 'less than'},\n ];\n const active = bounds.filter((b) => typeof b.limit === 'number');\n if (!active.length) return [];\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n // Non-numbers are the datatype check's business.\n if (!isCheckableElement(el) || typeof el !== 'number') continue;\n for (const bound of active) {\n if (bound.ok(el, bound.limit as number)) continue;\n results.push(\n violation(\n ctx,\n bound.component,\n `Property '${labelOf(ps)}' must be ${bound.phrase} ${bound.limit}, but was given ${el}.`,\n el,\n ),\n );\n }\n }\n return results;\n};\n\n/** `sh:minLength` / `sh:maxLength`, on strings. */\nconst lengthCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n if (typeof ps.minLength !== 'number' && typeof ps.maxLength !== 'number') return [];\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n if (!isCheckableElement(el) || typeof el !== 'string') continue;\n if (typeof ps.minLength === 'number' && el.length < ps.minLength) {\n results.push(\n violation(\n ctx,\n shacl.MinLengthConstraintComponent,\n `Property '${labelOf(ps)}' must be at least ${ps.minLength} character(s), but was given ${el.length}.`,\n el,\n ),\n );\n }\n if (typeof ps.maxLength === 'number' && el.length > ps.maxLength) {\n results.push(\n violation(\n ctx,\n shacl.MaxLengthConstraintComponent,\n `Property '${labelOf(ps)}' must be at most ${ps.maxLength} character(s), but was given ${el.length}.`,\n el,\n ),\n );\n }\n }\n return results;\n};\n\n/** `sh:pattern` — the string form of the value must match the shape's regex. */\nconst patternCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n if (!ps.pattern) return [];\n // Rebuild without `g`/`y`: those carry `lastIndex` between calls, so a shared\n // shape regex would match every other value.\n const regex = new RegExp(ps.pattern.source, ps.pattern.flags.replace(/[gy]/g, ''));\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n if (!isCheckableElement(el) || typeof el !== 'string') continue;\n if (regex.test(el)) continue;\n results.push(\n violation(\n ctx,\n shacl.PatternConstraintComponent,\n `Property '${labelOf(ps)}' must match ${String(ps.pattern)}, but was given \"${el}\".`,\n el,\n ),\n );\n }\n return results;\n};\n\n/** `sh:in` — the value must be one of the shape's allowed values. */\nconst inCheck: ConstraintCheck = (values, ctx) => {\n const ps = ctx.propertyShape;\n if (!ps.in?.length) return [];\n const allowed = ps.in;\n const matches = (el: unknown) =>\n allowed.some((a) =>\n isNodeReferenceValue(a)\n ? isNodeReference(el) && (el as NodeReferenceValue).id === a.id\n : a === el,\n );\n\n const results: ValidationResult[] = [];\n for (const el of values) {\n if (!isCheckableElement(el) || matches(el)) continue;\n const rendered = allowed\n .map((a) => (isNodeReferenceValue(a) ? a.id : JSON.stringify(a)))\n .join(', ');\n results.push(\n violation(\n ctx,\n shacl.InConstraintComponent,\n `Property '${labelOf(ps)}' must be one of [${rendered}].`,\n el,\n ),\n );\n }\n return results;\n};\n\n/**\n * The registry. Every property-level constraint the library enforces lives here;\n * adding another SHACL component is one more entry plus its test.\n *\n * Split by what each kind of check needs to see. **Cardinality** needs the\n * property's whole value set, so it cannot run against a set modification —\n * `{add: […]}` changes a count that lives in the store. **Value** checks need\n * only the value in hand, so they run everywhere a concrete value appears,\n * including inside `add`.\n *\n * Cardinality runs first when it runs at all: a count problem explains itself\n * better than the per-value violations that would follow it.\n */\nconst CARDINALITY_CONSTRAINTS: ConstraintCheck[] = [maxCountCheck, minCountCheck];\n\nconst VALUE_CONSTRAINTS: ConstraintCheck[] = [\n nodeKindCheck,\n datatypeCheck,\n rangeCheck,\n lengthCheck,\n patternCheck,\n inCheck,\n];\n\nconst PROPERTY_CONSTRAINTS: ConstraintCheck[] = [\n ...CARDINALITY_CONSTRAINTS,\n ...VALUE_CONSTRAINTS,\n];\n\n// ---------------------------------------------------------------------------\n// Value classification\n// ---------------------------------------------------------------------------\n\n/**\n * A `{add, remove}` set modification. The resulting value count depends on the\n * node's current state, so cardinality and kind are unknowable here.\n */\nfunction isSetModification(value: unknown): boolean {\n if (typeof value !== 'object' || value === null) return false;\n const obj = value as Record<string, unknown>;\n const expected = (obj.add ? 1 : 0) + (obj.remove ? 1 : 0);\n return expected > 0 && Object.getOwnPropertyNames(obj).length === expected;\n}\n\n/** An object carrying only an `id` — a reference to an existing node, not a description. */\nfunction isNodeReference(value: unknown): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n Object.keys(value).length === 1\n );\n}\n\n/**\n * A value that stands for something resolved later — an expression, a query\n * context reference, a callback, or nothing at all.\n *\n * Must be ruled out *before* anything reads properties off the value: a resolved\n * context ref is a query proxy that throws on any undecorated key, so probing it\n * for `.add` is not a safe way to ask what it is.\n */\nfunction isDeferredValue(value: unknown): boolean {\n return (\n value === undefined ||\n typeof value === 'function' ||\n isExpressionNode(value) ||\n !!asContextRef(value)\n );\n}\n\n/** Values whose final shape isn't knowable without the store or a lowering pass. */\nfunction isOpaqueValue(value: unknown): boolean {\n return isDeferredValue(value) || isSetModification(value);\n}\n\n/** A nested node description — an object to descend into, rather than a leaf value. */\nfunction isNodeDescription(value: unknown): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !isNodeReference(value) &&\n !isOpaqueValue(value)\n );\n}\n\n// ---------------------------------------------------------------------------\n// Entry points\n// ---------------------------------------------------------------------------\n\n/**\n * What can be validated against: a shape class (`Person`) or the plain\n * `NodeShapeData` the decorators generate (`Person.shape`, or the same object\n * obtained anywhere else). The two are interchangeable — the class is unwrapped\n * to its `shape` and nothing else about it is read.\n */\nexport type ValidatableShape = NodeShapeData | {shape: NodeShapeData};\n\nfunction resolveShapeData(shape: ValidatableShape): NodeShapeData {\n const resolved = 'propertyShapes' in shape ? shape : (shape as {shape: NodeShapeData}).shape;\n if (!resolved) {\n throw new Error(\n 'validate() requires a node shape or a shape class with a static `shape`. ' +\n 'Did you pass an unregistered class (missing @linkedShape)?',\n );\n }\n return resolved as NodeShapeData;\n}\n\n/**\n * Validate a plain data object against a node shape.\n *\n * Never throws for invalid *data* — a violation is a result, not an exception.\n * (It does throw when the *shape* argument itself is unusable.)\n *\n * ```ts\n * const report = validate(Person, {name: ['a', 'b']});\n * report.conforms; // false\n * report.results[0].sourceConstraintComponent.id; // …shacl#MaxCountConstraintComponent\n * ```\n *\n * **A shape class is optional.** The plain `NodeShapeData` the decorators\n * generate validates identically, so a caller that only ever holds shape\n * objects needs no class reference:\n *\n * ```ts\n * validate(Person, data); // ≡\n * validate(Person.shape, data); // same report\n * ```\n *\n * That holds even though a shape object carries neither its inherited property\n * shapes (a subclass's `propertyShapes` holds only its own) nor its nested\n * shapes (`valueShape` is a bare `{id}`): both are resolved through the shape\n * registry by id. A shape whose id is not registered therefore cannot be fully\n * checked, and says so — see {@link unresolvedValueShapeMessage} and the\n * inherited-properties check in `validateNode` — rather than reporting a node\n * as conforming on the strength of a branch it could not look at.\n */\nexport function validate(\n shape: ValidatableShape,\n data: unknown,\n options: ValidateOptions = {},\n): ValidationReport {\n const {mode = 'complete', maxDepth = 10} = options;\n const results = validateNode(resolveShapeData(shape), data, {\n mode,\n maxDepth,\n depth: 0,\n prefix: '',\n });\n return {\n conforms: !results.some((r) => r.resultSeverity.id === shacl.Violation.id),\n results,\n };\n}\n\n/** {@link validate}, but throws a {@link ShapeValidationError} when the data doesn't conform. */\nexport function assertValid(\n shape: ValidatableShape,\n data: unknown,\n options: ValidateOptions = {},\n): void {\n const report = validate(shape, data, options);\n if (!report.conforms) throw new ShapeValidationError(report);\n}\n\n// ---------------------------------------------------------------------------\n// Walk\n// ---------------------------------------------------------------------------\n\ninterface WalkContext {\n mode: ValidationMode;\n maxDepth: number;\n depth: number;\n /** Dot-joined label path of the node being validated (`''` at the root). */\n prefix: string;\n focusNode?: string;\n}\n\nfunction validateNode(\n shape: NodeShapeData,\n data: unknown,\n ctx: WalkContext,\n): ValidationResult[] {\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n return [\n nodeViolation(\n shape,\n ctx,\n shacl.NodeConstraintComponent,\n `Expected an object describing '${shape.label || shape.id}', but got ${data === null ? 'null' : typeof data}.`,\n ctx.prefix,\n data,\n ),\n ];\n }\n\n const obj = data as Record<string, unknown>;\n const propertyShapes = getUniquePropertyShapes(shape);\n const byLabel = new Map(propertyShapes.map((ps) => [ps.label, ps]));\n const focusNode =\n typeof obj.__id === 'string'\n ? obj.__id\n : typeof obj.id === 'string'\n ? obj.id\n : ctx.focusNode;\n const results: ValidationResult[] = [];\n\n // A shape declaring a superclass carries only its *own* property shapes; the\n // inherited ones are resolved through the registry by id. If this shape's id\n // is not registered, that resolution quietly yields half a shape — required\n // inherited properties go unchecked, and any that *are* supplied look\n // undeclared. Report it rather than let a partial shape pass as a clean bill.\n //\n // \"Registered\" means present in EITHER registry. Checking only for a class rejected\n // exactly the shapes the metamodel work exists to support: a data-only child is\n // registered, its parent resolves, and its inherited properties are checked — it simply\n // has no class, which is not a defect.\n if (shape.extends?.id && !getShapeClass(shape.id) && !getNodeShape(shape.id)) {\n results.push(\n nodeViolation(\n shape,\n {focusNode},\n shacl.NodeConstraintComponent,\n `Cannot resolve the properties '${shape.label || shape.id}' inherits from '${shape.extends.id}': shape '${shape.id}' is not registered, so only its own properties could be checked.`,\n ctx.prefix,\n ),\n );\n }\n\n // Presence of required properties — only decidable for a complete description.\n if (ctx.mode === 'complete') {\n for (const ps of propertyShapes) {\n if (typeof ps.minCount !== 'number' || ps.minCount <= 0) continue;\n if (ps.label in obj) continue;\n results.push(\n violation(\n {shape, propertyShape: ps, property: join(ctx.prefix, ps.label), focusNode, mode: ctx.mode},\n shacl.MinCountConstraintComponent,\n `Property '${labelOf(ps)}' requires at least ${ps.minCount} value(s), but none were provided.`,\n ),\n );\n }\n }\n\n // The values actually provided.\n for (const [key, value] of Object.entries(obj)) {\n if (RESERVED_KEYS.has(key)) continue;\n const propertyShape = byLabel.get(key);\n if (!propertyShape) {\n results.push(\n nodeViolation(\n shape,\n {...ctx, focusNode},\n shacl.ClosedConstraintComponent,\n undeclaredPropertyMessage(key, shape),\n join(ctx.prefix, key),\n value,\n ),\n );\n continue;\n }\n results.push(\n ...validateProperty(value, {\n shape,\n propertyShape,\n property: join(ctx.prefix, key),\n focusNode,\n mode: ctx.mode,\n }, ctx),\n );\n }\n\n return results;\n}\n\nfunction validateProperty(\n value: unknown,\n propCtx: PropertyContext,\n walk: WalkContext,\n): ValidationResult[] {\n const ps = propCtx.propertyShape;\n\n // `null` clears the property — the same as providing zero values, so clearing\n // a required one is a cardinality violation (both spellings behave alike).\n if (value === null) {\n if (typeof ps.minCount === 'number' && ps.minCount > 0) {\n return [\n violation(\n propCtx,\n shacl.MinCountConstraintComponent,\n `Property '${labelOf(ps)}' requires at least ${ps.minCount} value(s) and cannot be cleared.`,\n ),\n ];\n }\n return [];\n }\n\n // Ruled out first: reading `.add` off a resolved context proxy would throw.\n if (isDeferredValue(value)) return [];\n\n // A set modification adds to and removes from what the store already holds,\n // so the resulting *count* is unknowable here — but each added value is as\n // checkable as any other, and skipping them let mistyped literals through the\n // one door the rest of this module closes. `remove` takes `{id}` references\n // only, which normalization enforces on its own.\n if (isSetModification(value)) {\n const {add} = value as {add?: unknown};\n if (add === undefined) return [];\n return runChecks(VALUE_CONSTRAINTS, toValues(add), propCtx, walk);\n }\n\n return runChecks(PROPERTY_CONSTRAINTS, toValues(value), propCtx, walk);\n}\n\n/** A property's value(s) as an array — a single value becomes a one-element one. */\nfunction toValues(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [value];\n}\n\n/**\n * Run a set of constraint checks over a property's values, then descend into any\n * nested node descriptions among them (`sh:node`-style recursion). A bare `{id}`\n * is a reference to an existing node and has nothing to validate; an object with\n * an id *and* data is a nested create with a predefined id.\n */\nfunction runChecks(\n checks: ConstraintCheck[],\n values: unknown[],\n propCtx: PropertyContext,\n walk: WalkContext,\n): ValidationResult[] {\n const results: ValidationResult[] = [];\n for (const check of checks) {\n results.push(...check(values, propCtx));\n }\n\n if (walk.depth < walk.maxDepth) {\n for (const el of values) {\n if (!isNodeDescription(el)) continue;\n const nestedShape = resolveValueShape(propCtx.propertyShape, el);\n if (!nestedShape) {\n // The value is a node description we have no shape for, so nothing about\n // it can be checked. Silently skipping would report the whole node as\n // conforming on the strength of a branch never looked at.\n results.push(\n violation(\n propCtx,\n shacl.NodeConstraintComponent,\n unresolvedValueShapeMessage(propCtx.propertyShape),\n ),\n );\n continue;\n }\n results.push(\n ...validateNode(nestedShape, el, {\n ...walk,\n depth: walk.depth + 1,\n prefix: propCtx.property,\n focusNode: undefined,\n }),\n );\n }\n }\n\n return results;\n}\n\n/**\n * Why a nested value could not be resolved to a shape — the property named one\n * that is not registered, or named none and the value did not carry one either.\n * Both are actionable, and they are fixed differently.\n */\nfunction unresolvedValueShapeMessage(ps: PropertyShapeData): string {\n const label = labelOf(ps);\n return ps.valueShape\n ? `Cannot validate the value of '${label}': its shape '${ps.valueShape.id}' is not registered.`\n : `Cannot validate the value of '${label}': the property declares no shape for its values. ` +\n `Add a 'shape' to its @objectProperty decorator, or give the value a 'shape' key.`;\n}\n\n/**\n * The shape a nested value should be validated against: the shape class carried\n * in the value's reserved `shape` key when the property declares no `valueShape`\n * or the key names a subclass of it, otherwise the declared `valueShape`. Mirrors\n * `convertUpdateValue`; returns undefined when neither is available.\n */\nfunction resolveValueShape(\n ps: PropertyShapeData,\n value: unknown,\n): NodeShapeData | undefined {\n const own = (value as {shape?: {shape?: NodeShapeData}}).shape?.shape;\n if (!ps.valueShape) return own;\n const declared = getQueryShapeClass(ps.valueShape)?.shape;\n // A value naming a subclass of the declared shape is validated as that subclass.\n if (own && declared && isSubShapeOf(own, declared)) return own;\n return declared;\n}\n\nfunction join(prefix: string, label: string): string {\n return prefix ? `${prefix}.${label}` : label;\n}\n"]}
|