@_linked/core 2.30.0 → 2.31.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 +54 -0
- package/README.md +54 -7
- package/lib/esm/queries/IRMutation.js +1 -1
- package/lib/esm/queries/IRMutation.js.map +1 -1
- package/lib/esm/queries/IntermediateRepresentation.d.ts +0 -5
- package/lib/esm/queries/IntermediateRepresentation.js.map +1 -1
- package/lib/esm/queries/MutationQuery.js +9 -19
- package/lib/esm/queries/MutationQuery.js.map +1 -1
- package/lib/esm/queries/MutationSerialization.d.ts +6 -5
- package/lib/esm/queries/MutationSerialization.js +30 -13
- package/lib/esm/queries/MutationSerialization.js.map +1 -1
- package/lib/esm/queries/QueryFactory.d.ts +0 -6
- package/lib/esm/queries/QueryFactory.js.map +1 -1
- package/lib/esm/queries/lowerMutationJSON.js +1 -6
- package/lib/esm/queries/lowerMutationJSON.js.map +1 -1
- package/lib/esm/shapes/List.d.ts +0 -1
- package/lib/esm/shapes/List.js.map +1 -1
- package/lib/esm/shapes/PathList.d.ts +27 -0
- package/lib/esm/shapes/PathList.js +63 -0
- package/lib/esm/shapes/PathList.js.map +1 -0
- package/lib/esm/shapes/PathNode.d.ts +10 -9
- package/lib/esm/shapes/PathNode.js +21 -13
- package/lib/esm/shapes/PathNode.js.map +1 -1
- package/lib/esm/shapes/index.d.ts +1 -0
- package/lib/esm/shapes/index.js +1 -0
- package/lib/esm/shapes/index.js.map +1 -1
- package/lib/esm/shapes/serializePathToNodeData.d.ts +12 -11
- package/lib/esm/shapes/serializePathToNodeData.js +12 -11
- package/lib/esm/shapes/serializePathToNodeData.js.map +1 -1
- package/lib/esm/shapes/validation.js +16 -12
- package/lib/esm/shapes/validation.js.map +1 -1
- package/lib/esm/sparql/irToAlgebra.d.ts +7 -2
- package/lib/esm/sparql/irToAlgebra.js +415 -181
- package/lib/esm/sparql/irToAlgebra.js.map +1 -1
- package/lib/esm/utils/Package.js +6 -3
- package/lib/esm/utils/Package.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MutationSerialization.js","sourceRoot":"","sources":["../../../src/queries/MutationSerialization.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/**\n * Lossless JSON (de)serialization for mutations (create / update / delete) — the\n * **IR-free wire codec**. The companion IR side (`decodeNodeData` / `lowerMutationJSON`)\n * lives in `lowerMutationJSON.ts` so this module never pulls the canonical-IR pipeline.\n *\n * The serialization unit is the normalized `NodeDescriptionValue` produced by the\n * IR-free factory base (`MutationQueryFactory.describe()`) — i.e. after `.set()` and\n * after any update-expression callback has been evaluated, but before canonical IR.\n * Property keys are serialized as **labels** (shape-relative, lightweight); decoding\n * resolves them back via the registered shape.\n *\n * Values use the DSL-JSON grammar (documentation/dsl-json.md): a bare scalar is a\n * literal; objects tag the kinds `JSON.stringify` can't represent natively\n * (`{@date}`, `{@id}`, `{@ctx}`, `{@list}`, `{@add,@remove}`, `{@unset}`); and a\n * computed value is an S-expr array via the shared `DslJsonExpression` codec —\n * so the wire carries no IR.\n */\nimport {\n type NodeDescriptionValue,\n type NodeReferenceValue,\n type PropUpdateValue,\n type SetModificationValue,\n type SinglePropertyUpdateValue,\n isSetModificationValue,\n} from './QueryFactory.js';\nimport {getPropertyShape} from '../shapes/nodeShapeData.js';\nimport {ExpressionNode, isExpressionNode} from '../expressions/ExpressionNode.js';\nimport type {WherePathJSON} from './QueryBuilderSerialization.js';\nimport type {ContextRefJSON} from './ContextRef.js';\nimport {PendingQueryContext} from './QueryContext.js';\nimport {getShapeClass} from '../utils/ShapeClass.js';\nimport type {NodeShapeData, PropertyShapeData} from '../shapes/SHACL.js';\nimport {\n encodeValueExpr,\n decodeValueExpr,\n type DslJsonValue,\n} from './DslJsonExpression.js';\n\n// =============================================================================\n// JSON types\n// =============================================================================\n\n/**\n * A mutation field value in the DSL-JSON grammar. A bare scalar is a literal; objects\n * tag the non-JSON-native kinds (`@`-sigiled); a computed value is an S-expr array (no IR); a\n * nested-node create is a bare path-keyed object ({@link MutationNodeDataJSON}),\n * disambiguated from the tagged forms by having no reserved value-key.\n */\nexport type MutationValueJSON =\n | string\n | number\n | boolean\n | null\n | {'@date': string}\n | {'@id': string}\n | {'@ctx': string}\n | {'@list': MutationValueJSON[]}\n | {'@add'?: MutationValueJSON[]; '@remove'?: string[]}\n | {'@unset': true}\n | MutationNodeDataJSON // nested-node create (bare, path-keyed)\n | DslJsonValue; // computed expression (S-expr) / {@path}\n\n/**\n * A node description in **path-keyed** form: `label → value`, plus three reserved\n * keys — `__id` (a fixed/predefined id), `__blank` (`true`: a nested node written as\n * a blank node) and `__shape` (the concrete shape IRI, emitted only when it differs\n * from the shape inferred from context, e.g. a subclass instance under a\n * superclass-typed relation).\n */\nexport type MutationNodeDataJSON = {\n [key: string]: MutationValueJSON | undefined;\n};\n\n/** Reserved node-data keys (not property labels). */\nconst NODE_ID_KEY = '__id';\nconst NODE_SHAPE_KEY = '__shape';\n/** Marks a nested node written as a blank node (`NodeDescriptionValue.__blank`). */\nconst NODE_BLANK_KEY = '__blank';\n\nexport type CreateMutationJSON = {\n v?: string;\n op: 'create';\n shape: string;\n data: MutationNodeDataJSON;\n};\n\nexport type UpdateMutationJSON = {\n v?: string;\n op: 'update';\n shape: string;\n mode: 'for' | 'forAll' | 'where';\n /** A node id, or a `{@ctx: name}` context reference resolved at lowering. */\n targetId?: string | ContextRefJSON;\n where?: WherePathJSON;\n data: MutationNodeDataJSON;\n};\n\n/**\n * Create-or-replace against a known id.\n *\n * A distinct `op` rather than `op: 'update'` with a new `mode`. An unaware consumer that\n * received `{op: 'update', mode: 'upsert'}` would fall past its `mode === 'for'` and\n * `mode === 'where'` branches into the update-where path with no where clause — an update\n * applied to *every instance of the shape*. A distinct op instead hits `fromJSON`'s\n * existing `default:` and throws \"Unknown query op\": loud, and safe.\n */\nexport type UpsertMutationJSON = {\n v?: string;\n op: 'upsert';\n shape: string;\n /** Upsert targets one known id; there is no `forAll`/`where` form. */\n mode: 'for';\n /** A node id, or a `{@ctx: name}` context reference resolved at lowering. */\n targetId?: string | ContextRefJSON;\n data: MutationNodeDataJSON;\n};\n\nexport type DeleteMutationJSON =\n | {v?: string; op: 'delete'; shape: string; mode: 'ids'; ids: (string | ContextRefJSON)[]}\n | {v?: string; op: 'delete'; shape: string; mode: 'all'}\n | {v?: string; op: 'delete'; shape: string; mode: 'where'; where: WherePathJSON};\n\nexport type MutationJSON =\n | CreateMutationJSON\n | UpdateMutationJSON\n | UpsertMutationJSON\n | DeleteMutationJSON;\n\n// =============================================================================\n// Value codec\n// =============================================================================\n\n/** The shape a nested node is expected to have (a property's value shape), if resolvable. */\nexport function valueShapeOf(prop?: PropertyShapeData): NodeShapeData | undefined {\n const id = (prop as unknown as {valueShape?: {id: string}})?.valueShape?.id;\n return id ? getShapeClass(id)?.shape : undefined;\n}\n\n/** Encode a single (non-array, non-setMod) property value. `prop` gives the nested-node shape. */\nfunction encodeSingleValue(\n value: SinglePropertyUpdateValue,\n prop?: PropertyShapeData,\n): MutationValueJSON {\n if (value === undefined) return {'@unset': true};\n if (isExpressionNode(value)) {\n // A computed value is an S-expr (or {@path}) via the shared codec — no IR.\n return encodeValueExpr(value.ir, value._refs) as MutationValueJSON;\n }\n if (value instanceof Date) return {'@date': value.toISOString()};\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n if (value && typeof value === 'object') {\n // Query-context reference — carry the name, resolve at lowering (checked\n // before the generic `.id` branch since a PendingQueryContext has an `.id` getter).\n if (value instanceof PendingQueryContext) {\n return {'@ctx': value.contextName};\n }\n if ('fields' in value) {\n // Nested-node create — bare path-keyed; expected shape = the relation's value shape.\n return encodeNodeData(value as NodeDescriptionValue, valueShapeOf(prop));\n }\n if ('id' in value) return {'@id': (value as NodeReferenceValue).id};\n }\n throw new Error(`Cannot serialize mutation value: ${JSON.stringify(value)}`);\n}\n\n/** Encode any property value, including arrays and set modifications. */\nexport function encodeValue(\n value: PropUpdateValue,\n prop?: PropertyShapeData,\n): MutationValueJSON {\n if (value === undefined) return {'@unset': true};\n if (Array.isArray(value)) {\n return {'@list': value.map((v) => encodeSingleValue(v, prop))};\n }\n if (isSetModificationValue(value)) {\n const mod = value as SetModificationValue;\n const json: {'@add'?: MutationValueJSON[]; '@remove'?: string[]} = {};\n if (mod.$add) json['@add'] = mod.$add.map((v) => encodeValue(v as PropUpdateValue, prop));\n if (mod.$remove) json['@remove'] = mod.$remove.map((r) => r.id);\n return json;\n }\n return encodeSingleValue(value as SinglePropertyUpdateValue, prop);\n}\n\n/**\n * Encode a normalized node description to path-keyed form. `expectedShape` is the\n * shape inferable from context (the envelope, or the parent relation's value shape);\n * `__shape` is emitted only when the concrete shape differs (a subclass instance).\n */\nexport function encodeNodeData(\n desc: NodeDescriptionValue,\n expectedShape?: NodeShapeData,\n): MutationNodeDataJSON {\n const json: MutationNodeDataJSON = {};\n if (desc.__id) json[NODE_ID_KEY] = desc.__id;\n if (desc.__blank) json[NODE_BLANK_KEY] = true;\n if (!expectedShape || desc.shape.id !== expectedShape.id) {\n json[NODE_SHAPE_KEY] = desc.shape.id;\n }\n for (const f of desc.fields) {\n json[f.prop.label] = encodeValue(f.val, f.prop);\n }\n return json;\n}\n\n// =============================================================================\n// JSON → raw UpdatePartial (for builder rehydration / fromJSON)\n// =============================================================================\n\n// Bound the DSL-JSON decode recursion (rehydration path) against a deeply-nested\n// payload exhausting the stack. Mirrors the cap in lowerMutationJSON.\nconst MAX_DECODE_DEPTH = 128;\nlet _decodeDepth = 0;\n\n/**\n * Decode a DSL-JSON value back to a raw DSL value (the form `.set()` accepts).\n * `currentShape` resolves computed `{@path}`/S-expr; `prop` gives a nested node's shape.\n * Depth-guarded wrapper around {@link decodeValueToRawInner}.\n */\nfunction decodeValueToRaw(\n json: MutationValueJSON,\n currentShape: NodeShapeData | undefined,\n prop?: PropertyShapeData,\n): unknown {\n if (++_decodeDepth > MAX_DECODE_DEPTH) {\n _decodeDepth = 0;\n throw new Error('DSL-JSON value nested too deeply');\n }\n try {\n return decodeValueToRawInner(json, currentShape, prop);\n } finally {\n _decodeDepth--;\n }\n}\n\nfunction decodeValueToRawInner(\n json: MutationValueJSON,\n currentShape: NodeShapeData | undefined,\n prop?: PropertyShapeData,\n): unknown {\n // S-expr computed value\n if (Array.isArray(json)) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, requireShapeForExpr(currentShape));\n return new ExpressionNode(ir, refs);\n }\n if (json === null) return null;\n if (typeof json !== 'object') return json; // bare scalar literal\n const o = json as Record<string, unknown>;\n if ('@unset' in o) return undefined;\n if ('@date' in o) return new Date(o['@date'] as string);\n // Rehydration path: preserve the live reference so it re-serializes as a\n // `{@ctx}` marker and resolves at the rebuilt builder's own lowering.\n if ('@ctx' in o) return new PendingQueryContext(o['@ctx'] as string);\n if ('@id' in o) return {id: o['@id']};\n if ('@list' in o) {\n return (o['@list'] as MutationValueJSON[]).map((i) => decodeValueToRaw(i, currentShape, prop));\n }\n if ('@add' in o || '@remove' in o) {\n // Raw DSL set-modifications use `@add`/`@remove` on the wire.\n const mod: {add?: unknown[]; remove?: {id: string}[]} = {};\n if (o['@add']) mod.add = (o['@add'] as MutationValueJSON[]).map((i) => decodeValueToRaw(i, currentShape, prop));\n if (o['@remove']) mod.remove = (o['@remove'] as string[]).map((id) => ({id}));\n return mod;\n }\n // A computed-path value (`{@path}`) used as a value.\n if ('@path' in o) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, requireShapeForExpr(currentShape));\n return new ExpressionNode(ir, refs);\n }\n // Otherwise: a bare path-keyed nested-node create.\n return decodeNodeDataToRaw(o as MutationNodeDataJSON, valueShapeOf(prop) ?? currentShape);\n}\n\nfunction requireShapeForExpr(shape: NodeShapeData | undefined): NodeShapeData {\n if (!shape) {\n throw new Error('A shape is required to decode a computed mutation value');\n }\n return shape;\n}\n\n/**\n * Decode path-keyed node data into a raw object the mutation builders' `.set()` accepts.\n * `__id` becomes `id`; `__shape` (if present) overrides the inferred `shape`. Mirrors\n * {@link encodeNodeData}.\n */\nexport function decodeNodeDataToRaw(\n json: MutationNodeDataJSON,\n shape?: NodeShapeData,\n): Record<string, unknown> {\n const nodeShape =\n typeof json[NODE_SHAPE_KEY] === 'string'\n ? getShapeClass(json[NODE_SHAPE_KEY] as string)?.shape ?? shape\n : shape;\n const obj: Record<string, unknown> = {};\n if (typeof json[NODE_ID_KEY] === 'string') obj.id = json[NODE_ID_KEY];\n if (json[NODE_BLANK_KEY] === true) obj.__blank = true;\n for (const [key, val] of Object.entries(json)) {\n if (key === NODE_ID_KEY || key === NODE_SHAPE_KEY || key === NODE_BLANK_KEY) continue;\n if (val === undefined) continue;\n // Skip prototype-polluting keys from untrusted DSL-JSON input.\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n const prop = nodeShape ? getPropertyShape(nodeShape, key) : undefined;\n obj[key] = decodeValueToRaw(val as MutationValueJSON, nodeShape, prop);\n }\n return obj;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MutationSerialization.js","sourceRoot":"","sources":["../../../src/queries/MutationSerialization.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/**\n * Lossless JSON (de)serialization for mutations (create / update / delete) — the\n * **IR-free wire codec**. The companion IR side (`decodeNodeData` / `lowerMutationJSON`)\n * lives in `lowerMutationJSON.ts` so this module never pulls the canonical-IR pipeline.\n *\n * The serialization unit is the normalized `NodeDescriptionValue` produced by the\n * IR-free factory base (`MutationQueryFactory.describe()`) — i.e. after `.set()` and\n * after any update-expression callback has been evaluated, but before canonical IR.\n * Property keys are serialized as **labels** (shape-relative, lightweight); decoding\n * resolves them back via the registered shape.\n *\n * Values use the DSL-JSON grammar (documentation/dsl-json.md): a bare scalar is a\n * literal; objects tag the kinds `JSON.stringify` can't represent natively\n * (`{@date}`, `{@id}`, `{@ctx}`, `{@list}`, `{@add,@remove}`, `{@unset}`); and a\n * computed value is an S-expr array via the shared `DslJsonExpression` codec —\n * so the wire carries no IR.\n */\nimport {\n type NodeDescriptionValue,\n type NodeReferenceValue,\n type PropUpdateValue,\n type SetModificationValue,\n type SinglePropertyUpdateValue,\n isSetModificationValue,\n} from './QueryFactory.js';\nimport {getPropertyShape} from '../shapes/nodeShapeData.js';\nimport {ExpressionNode, isExpressionNode} from '../expressions/ExpressionNode.js';\nimport type {WherePathJSON} from './QueryBuilderSerialization.js';\nimport type {ContextRefJSON} from './ContextRef.js';\nimport {PendingQueryContext} from './QueryContext.js';\nimport {getShapeClass, resolveShapeConstructor} from '../utils/ShapeClass.js';\nimport type {ShapeConstructor} from '../shapes/Shape.js';\nimport type {NodeShapeData, PropertyShapeData} from '../shapes/SHACL.js';\nimport {\n encodeValueExpr,\n decodeValueExpr,\n type DslJsonValue,\n} from './DslJsonExpression.js';\n\n// =============================================================================\n// JSON types\n// =============================================================================\n\n/**\n * A mutation field value in the DSL-JSON grammar. A bare scalar is a literal; objects\n * tag the non-JSON-native kinds (`@`-sigiled); a computed value is an S-expr array (no IR); a\n * nested-node create is a bare path-keyed object ({@link MutationNodeDataJSON}),\n * disambiguated from the tagged forms by having no reserved value-key.\n */\nexport type MutationValueJSON =\n | string\n | number\n | boolean\n | null\n | {'@date': string}\n | {'@id': string}\n | {'@ctx': string}\n | {'@list': MutationValueJSON[]}\n | {'@add'?: MutationValueJSON[]; '@remove'?: string[]}\n | {'@unset': true}\n | MutationNodeDataJSON // nested-node create (bare, path-keyed)\n | DslJsonValue; // computed expression (S-expr) / {@path}\n\n/**\n * A node description in **path-keyed** form: `label → value`, plus two reserved\n * keys — `__id` (a fixed/predefined id) and `__shape` (the concrete shape IRI,\n * emitted only when it differs from the shape inferred from context, e.g. a\n * subclass instance under a superclass-typed relation). Whether a nested node is\n * written as a blank node is not on the wire: the lowering decides it from the\n * property's `sh:nodeKind`.\n */\nexport type MutationNodeDataJSON = {\n [key: string]: MutationValueJSON | undefined;\n};\n\n/** Reserved node-data keys (not property labels). */\nconst NODE_ID_KEY = '__id';\nconst NODE_SHAPE_KEY = '__shape';\n\nexport type CreateMutationJSON = {\n v?: string;\n op: 'create';\n shape: string;\n data: MutationNodeDataJSON;\n};\n\nexport type UpdateMutationJSON = {\n v?: string;\n op: 'update';\n shape: string;\n mode: 'for' | 'forAll' | 'where';\n /** A node id, or a `{@ctx: name}` context reference resolved at lowering. */\n targetId?: string | ContextRefJSON;\n where?: WherePathJSON;\n data: MutationNodeDataJSON;\n};\n\n/**\n * Create-or-replace against a known id.\n *\n * A distinct `op` rather than `op: 'update'` with a new `mode`. An unaware consumer that\n * received `{op: 'update', mode: 'upsert'}` would fall past its `mode === 'for'` and\n * `mode === 'where'` branches into the update-where path with no where clause — an update\n * applied to *every instance of the shape*. A distinct op instead hits `fromJSON`'s\n * existing `default:` and throws \"Unknown query op\": loud, and safe.\n */\nexport type UpsertMutationJSON = {\n v?: string;\n op: 'upsert';\n shape: string;\n /** Upsert targets one known id; there is no `forAll`/`where` form. */\n mode: 'for';\n /** A node id, or a `{@ctx: name}` context reference resolved at lowering. */\n targetId?: string | ContextRefJSON;\n data: MutationNodeDataJSON;\n};\n\nexport type DeleteMutationJSON =\n | {v?: string; op: 'delete'; shape: string; mode: 'ids'; ids: (string | ContextRefJSON)[]}\n | {v?: string; op: 'delete'; shape: string; mode: 'all'}\n | {v?: string; op: 'delete'; shape: string; mode: 'where'; where: WherePathJSON};\n\nexport type MutationJSON =\n | CreateMutationJSON\n | UpdateMutationJSON\n | UpsertMutationJSON\n | DeleteMutationJSON;\n\n// =============================================================================\n// Value codec\n// =============================================================================\n\n/** The shape a nested node is expected to have (a property's value shape), if resolvable. */\nexport function valueShapeOf(prop?: PropertyShapeData): NodeShapeData | undefined {\n const id = (prop as unknown as {valueShape?: {id: string}})?.valueShape?.id;\n return id ? getShapeClass(id)?.shape : undefined;\n}\n\n/** Encode a single (non-array, non-setMod) property value. `prop` gives the nested-node shape. */\nfunction encodeSingleValue(\n value: SinglePropertyUpdateValue,\n prop?: PropertyShapeData,\n): MutationValueJSON {\n if (value === undefined) return {'@unset': true};\n if (isExpressionNode(value)) {\n // A computed value is an S-expr (or {@path}) via the shared codec — no IR.\n return encodeValueExpr(value.ir, value._refs) as MutationValueJSON;\n }\n if (value instanceof Date) return {'@date': value.toISOString()};\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n if (value && typeof value === 'object') {\n // Query-context reference — carry the name, resolve at lowering (checked\n // before the generic `.id` branch since a PendingQueryContext has an `.id` getter).\n if (value instanceof PendingQueryContext) {\n return {'@ctx': value.contextName};\n }\n if ('fields' in value) {\n // Nested-node create — bare path-keyed; expected shape = the relation's value shape.\n return encodeNodeData(value as NodeDescriptionValue, valueShapeOf(prop));\n }\n if ('id' in value) return {'@id': (value as NodeReferenceValue).id};\n }\n throw new Error(`Cannot serialize mutation value: ${JSON.stringify(value)}`);\n}\n\n/** Encode any property value, including arrays and set modifications. */\nexport function encodeValue(\n value: PropUpdateValue,\n prop?: PropertyShapeData,\n): MutationValueJSON {\n if (value === undefined) return {'@unset': true};\n if (Array.isArray(value)) {\n return {'@list': value.map((v) => encodeSingleValue(v, prop))};\n }\n if (isSetModificationValue(value)) {\n const mod = value as SetModificationValue;\n const json: {'@add'?: MutationValueJSON[]; '@remove'?: string[]} = {};\n if (mod.$add) json['@add'] = mod.$add.map((v) => encodeValue(v as PropUpdateValue, prop));\n if (mod.$remove) json['@remove'] = mod.$remove.map((r) => r.id);\n return json;\n }\n return encodeSingleValue(value as SinglePropertyUpdateValue, prop);\n}\n\n/**\n * Encode a normalized node description to path-keyed form. `expectedShape` is the\n * shape inferable from context (the envelope, or the parent relation's value shape);\n * `__shape` is emitted only when the concrete shape differs (a subclass instance).\n */\nexport function encodeNodeData(\n desc: NodeDescriptionValue,\n expectedShape?: NodeShapeData,\n): MutationNodeDataJSON {\n const json: MutationNodeDataJSON = {};\n if (desc.__id) json[NODE_ID_KEY] = desc.__id;\n if (!expectedShape || desc.shape.id !== expectedShape.id) {\n json[NODE_SHAPE_KEY] = desc.shape.id;\n }\n for (const f of desc.fields) {\n json[f.prop.label] = encodeValue(f.val, f.prop);\n }\n return json;\n}\n\n// =============================================================================\n// JSON → raw UpdatePartial (for builder rehydration / fromJSON)\n// =============================================================================\n\n// Bound the DSL-JSON decode recursion (rehydration path) against a deeply-nested\n// payload exhausting the stack. Mirrors the cap in lowerMutationJSON.\nconst MAX_DECODE_DEPTH = 128;\nlet _decodeDepth = 0;\n\n/**\n * Decode a DSL-JSON value back to a raw DSL value (the form `.set()` accepts).\n * `currentShape` resolves computed `{@path}`/S-expr; `prop` gives a nested node's shape.\n * Depth-guarded wrapper around {@link decodeValueToRawInner}.\n */\nfunction decodeValueToRaw(\n json: MutationValueJSON,\n currentShape: NodeShapeData | undefined,\n prop?: PropertyShapeData,\n): unknown {\n if (++_decodeDepth > MAX_DECODE_DEPTH) {\n _decodeDepth = 0;\n throw new Error('DSL-JSON value nested too deeply');\n }\n try {\n return decodeValueToRawInner(json, currentShape, prop);\n } finally {\n _decodeDepth--;\n }\n}\n\nfunction decodeValueToRawInner(\n json: MutationValueJSON,\n currentShape: NodeShapeData | undefined,\n prop?: PropertyShapeData,\n): unknown {\n // S-expr computed value\n if (Array.isArray(json)) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, requireShapeForExpr(currentShape));\n return new ExpressionNode(ir, refs);\n }\n if (json === null) return null;\n if (typeof json !== 'object') return json; // bare scalar literal\n const o = json as Record<string, unknown>;\n if ('@unset' in o) return undefined;\n if ('@date' in o) return new Date(o['@date'] as string);\n // Rehydration path: preserve the live reference so it re-serializes as a\n // `{@ctx}` marker and resolves at the rebuilt builder's own lowering.\n if ('@ctx' in o) return new PendingQueryContext(o['@ctx'] as string);\n if ('@id' in o) return {id: o['@id']};\n if ('@list' in o) {\n return (o['@list'] as MutationValueJSON[]).map((i) => decodeValueToRaw(i, currentShape, prop));\n }\n if ('@add' in o || '@remove' in o) {\n // Raw DSL set-modifications use `@add`/`@remove` on the wire.\n const mod: {add?: unknown[]; remove?: {id: string}[]} = {};\n if (o['@add']) mod.add = (o['@add'] as MutationValueJSON[]).map((i) => decodeValueToRaw(i, currentShape, prop));\n if (o['@remove']) mod.remove = (o['@remove'] as string[]).map((id) => ({id}));\n return mod;\n }\n // A computed-path value (`{@path}`) used as a value.\n if ('@path' in o) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, requireShapeForExpr(currentShape));\n return new ExpressionNode(ir, refs);\n }\n // Otherwise: a bare path-keyed nested-node create.\n return decodeNestedNodeDataToRaw(o as MutationNodeDataJSON, valueShapeOf(prop) ?? currentShape);\n}\n\n/**\n * Decode a nested node and, when it names its concrete shape (`__shape`), carry that\n * shape as the reserved `shape` key `.set()` accepts on a nested value. Without it the\n * builders validate and lower the value against the property's declared value shape —\n * or none, for a polymorphic slot like `PropertyShape.path` — and reject the fields\n * only the concrete shape has.\n */\n/**\n * The class for a node's `__shape`. Either registry — a project-authored shape exists only\n * as metadata. Throws like `lowerMutationJSON` does, so both decode paths reject an\n * unregistered shape instead of one of them silently validating against another.\n */\nfunction requireNodeShapeClass(shapeId: string): ShapeConstructor {\n const shapeClass = resolveShapeConstructor(shapeId);\n if (!shapeClass) {\n throw new Error(\n `Shape '${shapeId}' is not registered. The receiving side must have the shape registered to decode mutation DSL-JSON.`,\n );\n }\n return shapeClass;\n}\n\nfunction decodeNestedNodeDataToRaw(\n json: MutationNodeDataJSON,\n shape: NodeShapeData | undefined,\n): Record<string, unknown> {\n const obj = decodeNodeDataToRaw(json, shape);\n const shapeId = json[NODE_SHAPE_KEY];\n if (typeof shapeId === 'string') obj.shape = requireNodeShapeClass(shapeId);\n return obj;\n}\n\nfunction requireShapeForExpr(shape: NodeShapeData | undefined): NodeShapeData {\n if (!shape) {\n throw new Error('A shape is required to decode a computed mutation value');\n }\n return shape;\n}\n\n/**\n * Decode path-keyed node data into a raw object the mutation builders' `.set()` accepts.\n * `__id` becomes `id`; `__shape` (if present) overrides the inferred `shape`. Mirrors\n * {@link encodeNodeData}.\n */\nexport function decodeNodeDataToRaw(\n json: MutationNodeDataJSON,\n shape?: NodeShapeData,\n): Record<string, unknown> {\n const nodeShape =\n typeof json[NODE_SHAPE_KEY] === 'string'\n ? requireNodeShapeClass(json[NODE_SHAPE_KEY] as string).shape\n : shape;\n const obj: Record<string, unknown> = {};\n if (typeof json[NODE_ID_KEY] === 'string') obj.id = json[NODE_ID_KEY];\n for (const [key, val] of Object.entries(json)) {\n if (key === NODE_ID_KEY || key === NODE_SHAPE_KEY || val === undefined) continue;\n // Skip prototype-polluting keys from untrusted DSL-JSON input.\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n const prop = nodeShape ? getPropertyShape(nodeShape, key) : undefined;\n obj[key] = decodeValueToRaw(val as MutationValueJSON, nodeShape, prop);\n }\n return obj;\n}\n"]}
|
|
@@ -64,12 +64,6 @@ export type NodeDescriptionValue = {
|
|
|
64
64
|
* Optional, if not provided a new id will be generated.
|
|
65
65
|
*/
|
|
66
66
|
__id?: string;
|
|
67
|
-
/**
|
|
68
|
-
* Write this nested node as a fresh blank node carrying only its field triples (no
|
|
69
|
-
* `rdf:type`). For RDF syntax structures whose meaning comes from the triple that
|
|
70
|
-
* references them, like a SHACL property path. Create-only and never with `__id`.
|
|
71
|
-
*/
|
|
72
|
-
__blank?: true;
|
|
73
67
|
};
|
|
74
68
|
export type UpdateNodePropertyValue = {
|
|
75
69
|
prop: PropertyShapeData;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryFactory.js","sourceRoot":"","sources":["../../../src/queries/QueryFactory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"QueryFactory.js","sourceRoot":"","sources":["../../../src/queries/QueryFactory.ts"],"names":[],"mappings":"AAmKA,OAAO,EAAC,eAAe,EAAC,MAAM,2BAA2B,CAAC;AAG1D,MAAM,OAAgB,YAAY;CAAG;AAErC,MAAM,UAAU,sBAAsB,CACpC,KAAU;IAEV,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE9D,IAAI,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;IAC3B,IAAI,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;IACjC,IAAI,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IACxC,mBAAmB;IACnB,OAAO,CACL,CAAC,SAAS,IAAI,YAAY,IAAI,OAAO,KAAK,CAAC,CAAC;QAC5C,CAAC,SAAS,IAAI,OAAO,KAAK,CAAC,CAAC;QAC5B,CAAC,YAAY,IAAI,OAAO,KAAK,CAAC,CAAC,CAChC,CAAC;AACJ,CAAC","sourcesContent":["import type {NodeShapeData, PropertyShapeData} from '../shapes/SHACL.js';\nimport {Shape} from '../shapes/Shape.js';\nimport {ShapeSet} from '../collections/ShapeSet.js';\nimport type {NodeReferenceValue} from '../utils/NodeReference.js';\nimport {ExpressionNode} from '../expressions/ExpressionNode.js';\n\nexport type Prettify<T> = T extends infer R\n ? {\n [K in keyof R]: R[K];\n }\n : never;\n\n/**\n * Recursively adds an id property to all objects in the object.\n * Also makes all keys optional.\n */\ntype _AddId<U> = U extends string | number | boolean | Date | null | undefined\n ? U\n : U extends Array<infer T>\n ? Array<_AddId<T>>\n : WithId<U>;\n\ntype RemoveId<U> = Omit<U, 'id'>;\n\ntype WithId<U> = U & {id: string};\n\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I,\n) => void\n ? I\n : never;\n\ntype CombineTypes<T> = {\n [K in keyof UnionToIntersection<T>]: T extends {[P in K]?: infer V}\n ? _AddId<V>\n : never;\n};\n\ntype IsPlainObject<T> = T extends object\n ? T extends any[]\n ? false\n : T extends Function\n ? false\n : T extends Date\n ? false\n : T extends RegExp\n ? false\n : T extends Error\n ? false\n : T extends null\n ? false\n : T extends undefined\n ? false\n : T extends object\n ? true\n : false\n : false;\n\ntype RecursiveTransform<T, IsCreate = false> = T extends\n | string\n | number\n | boolean\n | Date\n | null\n | undefined\n ? T\n : T extends Array<infer U>\n ? UpdatedSet<Prettify<RecursiveTransform<U>>, IsCreate>\n : IsSetModification<T> extends true\n ? ModifiedSet<T, IsCreate>\n : IsPlainObject<T> extends true\n ? // ? WithId<{ [K in keyof T]-?: Prettify<RecursiveTransform<T[K]>> }>\n WithId<{[K in keyof T]: Prettify<RecursiveTransform<T[K], IsCreate>>}>\n : T;\n\n//for update() we use {updatedTo} but for create() we actually just return the array of new values;\ntype UpdatedSet<U, IsCreate> = IsCreate extends true\n ? U[]\n : {\n updatedTo: U[];\n };\ntype IsSetModification<T> = T extends {add?: any; remove?: any} ? true : false;\ntype AddedType<T> = T extends {add: (infer U)[]}\n ? U\n : T extends {add: infer U}\n ? U\n : never;\n\ntype RemovedType<T> = T extends {remove: (infer U)[]}\n ? U\n : T extends {remove: infer U}\n ? U\n : never;\n\ntype ModifiedSet<T, IsCreate = false> = {\n added: AddId<AddedType<T>, IsCreate>[];\n removed: AddId<RemovedType<T>, IsCreate>[];\n};\n\nexport type AddId<T, IsCreate = false> = Prettify<\n RecursiveTransform<T, IsCreate>\n>;\n\nexport type UpdatePartial<S = Shape> =\n | UpdateNodeDescription<S>\n | NodeReferenceValue;\ntype UpdateNodeDescription<Shape> = Partial<\n Omit<\n {\n [P in KeysWithoutFunctions<Shape>]: ShapePropValueToUpdatePartial<\n Shape[P]\n >;\n },\n 'node' | 'nodeShape' | 'namedNode' | 'targetClass'\n >\n>;\ntype KeysWithoutFunctions<T> = {\n [K in keyof T]: T[K] extends Function ? never : K;\n}[keyof T];\n\ntype ShapePropValueToUpdatePartial<ShapeProperty> = ShapeProperty extends Shape\n ? UpdatePartial<ShapeProperty>\n : ShapeProperty extends ShapeSet<infer SSType>\n ? SetUpdateValue<SSType>\n : ShapeProperty | ExpressionNode;\n\ntype SetUpdateValue<SSType> = UpdatePartial<SSType>[] | SetModification<SSType>;\n\nexport type SetModification<SSType> = {\n add?: UpdatePartial<SSType>[] | UpdatePartial<SSType>;\n remove?: UpdatePartial<SSType>[] | UpdatePartial<SSType>;\n};\n\nexport type SetModificationValue = {\n $add?: UpdatePartial[];\n $remove?: NodeReferenceValue[];\n};\n\ntype UnsetValue = undefined;\nexport type LiteralUpdateValue = string | number | boolean | Date;\nexport type PropUpdateValue =\n | SinglePropertyUpdateValue\n | SinglePropertyUpdateValue[]\n | SetModificationValue;\nexport type SinglePropertyUpdateValue =\n | NodeDescriptionValue\n | NodeReferenceValue\n | LiteralUpdateValue\n | UnsetValue;\nexport type NodeDescriptionValue = {\n shape: NodeShapeData;\n fields: UpdateNodePropertyValue[];\n /**\n * The id of the node to be created.\n * Optional, if not provided a new id will be generated.\n */\n __id?: string;\n};\nexport type UpdateNodePropertyValue = {\n prop: PropertyShapeData;\n val: PropUpdateValue;\n};\nexport type ShapeReferenceValue = {id: string; shape: NodeReferenceValue};\nexport {toNodeReference} from '../utils/NodeReference.js';\nexport type {NodeReferenceValue};\n\nexport abstract class QueryFactory {}\n\nexport function isSetModificationValue(\n value: any,\n): value is SetModificationValue {\n if (value === null || typeof value !== 'object') return false;\n\n let hasAddKey = value.$add;\n let hasRemoveKey = value.$remove;\n let numKeys = Object.keys(value).length;\n //has no other keys\n return (\n (hasAddKey && hasRemoveKey && numKeys === 2) ||\n (hasAddKey && numKeys === 1) ||\n (hasRemoveKey && numKeys === 1)\n );\n}\n\n"]}
|
|
@@ -98,7 +98,7 @@ export function decodeNodeData(json, shape) {
|
|
|
98
98
|
const nodeShape = typeof json.__shape === 'string' ? requireShape(json.__shape) : shape;
|
|
99
99
|
const fields = [];
|
|
100
100
|
for (const [key, val] of Object.entries(json)) {
|
|
101
|
-
if (key === '__id' || key === '__shape' ||
|
|
101
|
+
if (key === '__id' || key === '__shape' || val === undefined)
|
|
102
102
|
continue;
|
|
103
103
|
const prop = getPropertyShape(nodeShape, key);
|
|
104
104
|
if (!prop) {
|
|
@@ -109,11 +109,6 @@ export function decodeNodeData(json, shape) {
|
|
|
109
109
|
const desc = { shape: nodeShape, fields };
|
|
110
110
|
if (typeof json.__id === 'string')
|
|
111
111
|
desc.__id = json.__id;
|
|
112
|
-
if (json.__blank !== undefined) {
|
|
113
|
-
if (json.__blank !== true)
|
|
114
|
-
throw new Error(`__blank must be true when given, got ${JSON.stringify(json.__blank)}`);
|
|
115
|
-
desc.__blank = true;
|
|
116
|
-
}
|
|
117
112
|
return desc;
|
|
118
113
|
}
|
|
119
114
|
function lowerWhere(shape, json) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lowerMutationJSON.js","sourceRoot":"","sources":["../../../src/queries/lowerMutationJSON.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/**\n * Lower mutation DSL-JSON to canonical IR.\n *\n * This is the **IR side** of mutation (de)serialization, kept deliberately\n * separate from the IR-free wire codec in `MutationSerialization.ts`. The\n * canonical-IR builders (`IRMutation` / `IRLower` / …) are reachable only from\n * here and from `lower()`, so a client that serializes mutations to JSON and\n * forwards them (without ever lowering) tree-shakes the whole IR pipeline away.\n */\nimport type {NodeShapeData} from '../shapes/SHACL.js';\nimport {getPropertyShape} from '../shapes/nodeShapeData.js';\nimport {\n type NodeDescriptionValue,\n type PropUpdateValue,\n type SetModificationValue,\n type SinglePropertyUpdateValue,\n type UpdateNodePropertyValue,\n} from './QueryFactory.js';\nimport {ExpressionNode} from '../expressions/ExpressionNode.js';\nimport {getNodeShape, getShapeClass} from '../utils/ShapeClass.js';\nimport type {IRExpression, IRGraphPattern} from './IntermediateRepresentation.js';\nimport {\n deserializeWherePath,\n type WherePathJSON,\n} from './QueryBuilderSerialization.js';\nimport {toWhere} from './IRDesugar.js';\nimport {lowerWhereToIR} from './IRLower.js';\nimport {\n buildCanonicalCreateMutationIR,\n buildCanonicalUpdateMutationIR,\n buildCanonicalUpsertMutationIR,\n buildCanonicalUpdateWhereMutationIR,\n buildCanonicalDeleteMutationIR,\n buildCanonicalDeleteAllMutationIR,\n buildCanonicalDeleteWhereMutationIR,\n} from './IRMutation.js';\nimport type {IRCreateQuery} from './CreateQuery.js';\nimport type {IRUpdateQuery} from './UpdateQuery.js';\nimport type {IRDeleteQuery} from './DeleteQuery.js';\nimport {isContextRefJSON, resolveContextId} from './ContextRef.js';\nimport {assertWireVersion} from './wireVersion.js';\nimport {\n decodeNodeDataToRaw,\n valueShapeOf,\n type MutationJSON,\n type MutationNodeDataJSON,\n type MutationValueJSON,\n} from './MutationSerialization.js';\nimport {assertValid, type ValidationMode} from '../shapes/validation.js';\nimport {decodeValueExpr, type DslJsonValue} from './DslJsonExpression.js';\nimport type {PropertyShapeData} from '../shapes/SHACL.js';\n\nfunction requireShape(shapeId: string): NodeShapeData {\n // Either registry: a project-authored shape arrives as metadata with no class, and\n // requiring a class here made every mutation against one fail at the boundary.\n const shape = getShapeClass(shapeId)?.shape ?? getNodeShape(shapeId);\n if (!shape) {\n throw new Error(\n `Shape '${shapeId}' is not registered. The receiving side must have the shape registered to lower mutation DSL-JSON.`,\n );\n }\n return shape;\n}\n\n// Bound the DSL-JSON decode recursion so a deeply-nested payload from\n// `fromJSON()` cannot exhaust the stack (RangeError DoS). Normal mutation data\n// nests only a handful of levels; 128 is far above any real query.\nconst MAX_DECODE_DEPTH = 128;\nlet _decodeDepth = 0;\n\n/**\n * Decode a DSL-JSON value to the normalized form the canonical-IR builders consume.\n * `currentShape` resolves computed `{@path}`/S-expr; `prop` gives a nested node's shape.\n * Depth-guarded wrapper around {@link decodeValueInner}.\n */\nfunction decodeValue(\n json: MutationValueJSON,\n currentShape: NodeShapeData,\n prop?: PropertyShapeData,\n): PropUpdateValue {\n if (++_decodeDepth > MAX_DECODE_DEPTH) {\n _decodeDepth = 0;\n throw new Error('DSL-JSON value nested too deeply');\n }\n try {\n return decodeValueInner(json, currentShape, prop);\n } finally {\n _decodeDepth--;\n }\n}\n\nfunction decodeValueInner(\n json: MutationValueJSON,\n currentShape: NodeShapeData,\n prop?: PropertyShapeData,\n): PropUpdateValue {\n // S-expr computed value (no IR on the wire)\n if (Array.isArray(json)) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, currentShape);\n return new ExpressionNode(ir, refs) as unknown as PropUpdateValue;\n }\n if (json === null) return null as unknown as PropUpdateValue;\n if (typeof json !== 'object') return json as PropUpdateValue; // bare scalar literal\n const o = json as Record<string, unknown>;\n if ('@unset' in o) return undefined;\n if ('@date' in o) return new Date(o['@date'] as string) as unknown as PropUpdateValue;\n if ('@ctx' in o) {\n // Lowering path: a mutation must hit a concrete node, so resolve the\n // context now and throw if it isn't set.\n const id = resolveContextId(o['@ctx'] as string, true)!;\n return {id} as PropUpdateValue;\n }\n if ('@id' in o) return {id: o['@id']} as PropUpdateValue;\n if ('@list' in o) {\n return (o['@list'] as MutationValueJSON[]).map(\n (item) => decodeValue(item, currentShape, prop) as SinglePropertyUpdateValue,\n );\n }\n if ('@add' in o || '@remove' in o) {\n const mod: SetModificationValue = {};\n if (o['@add']) {\n mod.$add = (o['@add'] as MutationValueJSON[]).map((v) =>\n decodeValue(v, currentShape, prop),\n ) as SetModificationValue['$add'];\n }\n if (o['@remove']) mod.$remove = (o['@remove'] as string[]).map((id) => ({id}));\n return mod as PropUpdateValue;\n }\n if ('@path' in o) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, currentShape);\n return new ExpressionNode(ir, refs) as unknown as PropUpdateValue;\n }\n // Otherwise: a bare path-keyed nested-node create.\n return decodeNodeData(\n o as MutationNodeDataJSON,\n valueShapeOf(prop) ?? currentShape,\n ) as unknown as PropUpdateValue;\n}\n\n/**\n * Rebuild a normalized node description from path-keyed JSON, resolving labels via the\n * shape. `shape` is the shape inferred from context; `__shape` overrides it.\n */\nexport function decodeNodeData(\n json: MutationNodeDataJSON,\n shape?: NodeShapeData,\n): NodeDescriptionValue {\n const nodeShape =\n typeof json.__shape === 'string' ? requireShape(json.__shape) : shape!;\n const fields: UpdateNodePropertyValue[] = [];\n for (const [key, val] of Object.entries(json)) {\n if (key === '__id' || key === '__shape' || key === '__blank' || val === undefined) continue;\n const prop = getPropertyShape(nodeShape, key);\n if (!prop) {\n throw new Error(\n `Property '${key}' not found on shape '${nodeShape.label || nodeShape.id}'`,\n );\n }\n fields.push({prop, val: decodeValue(val as MutationValueJSON, nodeShape, prop)} as UpdateNodePropertyValue);\n }\n const desc: NodeDescriptionValue = {shape: nodeShape, fields};\n if (typeof json.__id === 'string') desc.__id = json.__id;\n if (json.__blank !== undefined) {\n if (json.__blank !== true) throw new Error(`__blank must be true when given, got ${JSON.stringify(json.__blank)}`);\n desc.__blank = true;\n }\n return desc;\n}\n\nfunction lowerWhere(\n shape: NodeShapeData,\n json: WherePathJSON,\n): {where: IRExpression; wherePatterns: IRGraphPattern[]} {\n const wherePath = deserializeWherePath(shape, json);\n return lowerWhereToIR(toWhere(wherePath));\n}\n\n/**\n * Lower a mutation DSL-JSON envelope to the canonical IR mutation the dataset\n * expects. Mirrors the IR that `lower()` produces from the live builder.\n */\n/**\n * Validate inbound node data against its shape before it becomes IR.\n *\n * The builders validate through `describe()`, which sees raw DSL data. This path\n * never touches a builder, so without this an inbound mutation would be held to\n * a weaker standard than a locally-built one — on the *less* trusted input, at\n * that. `decodeNodeDataToRaw` produces exactly the raw form `describe()` would\n * have validated (it is what `CreateBuilder.fromJSON` feeds through `.set()`),\n * so both paths run the same checks. The second decode is the cost of validating\n * at a boundary; it happens once per inbound mutation.\n */\nfunction assertInboundDataValid(\n json: MutationNodeDataJSON,\n shape: NodeShapeData,\n mode: ValidationMode,\n): void {\n assertValid(shape, decodeNodeDataToRaw(json, shape), {mode});\n}\n\nexport function lowerMutationJSON(\n json: MutationJSON,\n): IRCreateQuery | IRUpdateQuery | IRDeleteQuery {\n assertWireVersion(json.v);\n switch (json.op) {\n case 'create': {\n const shape = requireShape(json.shape);\n assertInboundDataValid(json.data, shape, 'complete');\n return buildCanonicalCreateMutationIR({\n shape,\n description: decodeNodeData(json.data, shape),\n });\n }\n case 'upsert': {\n const shape = requireShape(json.shape);\n assertInboundDataValid(json.data, shape, 'partial');\n const updates = decodeNodeData(json.data, shape);\n const id = isContextRefJSON(json.targetId)\n ? resolveContextId(json.targetId['@ctx'], true)\n : json.targetId;\n if (!id) {\n throw new Error('upsert requires a targetId');\n }\n return buildCanonicalUpsertMutationIR({id, shape, updates});\n }\n case 'update': {\n const shape = requireShape(json.shape);\n assertInboundDataValid(json.data, shape, 'partial');\n const updates = decodeNodeData(json.data, shape);\n if (json.mode === 'for') {\n // A `{@ctx}` target resolves against the current context map; a mutation\n // must hit a concrete subject, so an unresolved context throws.\n const id = isContextRefJSON(json.targetId)\n ? resolveContextId(json.targetId['@ctx'], true)\n : json.targetId;\n if (!id) {\n throw new Error('update mode \"for\" requires a targetId');\n }\n return buildCanonicalUpdateMutationIR({id, shape, updates});\n }\n let where: IRExpression | undefined;\n let wherePatterns: IRGraphPattern[] | undefined;\n if (json.mode === 'where') {\n if (!json.where) throw new Error('update mode \"where\" requires a where clause');\n ({where, wherePatterns} = lowerWhere(shape, json.where));\n }\n return buildCanonicalUpdateWhereMutationIR({shape, updates, where, wherePatterns});\n }\n case 'delete': {\n const shape = requireShape(json.shape);\n if (json.mode === 'ids') {\n return buildCanonicalDeleteMutationIR({\n shape,\n // A `{@ctx}` id resolves against the live map; a delete must hit a\n // concrete node, so an unresolved context throws.\n ids: json.ids.map((id) =>\n isContextRefJSON(id) ? {id: resolveContextId(id['@ctx'], true)!} : {id},\n ),\n });\n }\n if (json.mode === 'all') {\n return buildCanonicalDeleteAllMutationIR({shape});\n }\n const {where, wherePatterns} = lowerWhere(shape, json.where);\n return buildCanonicalDeleteWhereMutationIR({shape, where, wherePatterns});\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"lowerMutationJSON.js","sourceRoot":"","sources":["../../../src/queries/lowerMutationJSON.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/**\n * Lower mutation DSL-JSON to canonical IR.\n *\n * This is the **IR side** of mutation (de)serialization, kept deliberately\n * separate from the IR-free wire codec in `MutationSerialization.ts`. The\n * canonical-IR builders (`IRMutation` / `IRLower` / …) are reachable only from\n * here and from `lower()`, so a client that serializes mutations to JSON and\n * forwards them (without ever lowering) tree-shakes the whole IR pipeline away.\n */\nimport type {NodeShapeData} from '../shapes/SHACL.js';\nimport {getPropertyShape} from '../shapes/nodeShapeData.js';\nimport {\n type NodeDescriptionValue,\n type PropUpdateValue,\n type SetModificationValue,\n type SinglePropertyUpdateValue,\n type UpdateNodePropertyValue,\n} from './QueryFactory.js';\nimport {ExpressionNode} from '../expressions/ExpressionNode.js';\nimport {getNodeShape, getShapeClass} from '../utils/ShapeClass.js';\nimport type {IRExpression, IRGraphPattern} from './IntermediateRepresentation.js';\nimport {\n deserializeWherePath,\n type WherePathJSON,\n} from './QueryBuilderSerialization.js';\nimport {toWhere} from './IRDesugar.js';\nimport {lowerWhereToIR} from './IRLower.js';\nimport {\n buildCanonicalCreateMutationIR,\n buildCanonicalUpdateMutationIR,\n buildCanonicalUpsertMutationIR,\n buildCanonicalUpdateWhereMutationIR,\n buildCanonicalDeleteMutationIR,\n buildCanonicalDeleteAllMutationIR,\n buildCanonicalDeleteWhereMutationIR,\n} from './IRMutation.js';\nimport type {IRCreateQuery} from './CreateQuery.js';\nimport type {IRUpdateQuery} from './UpdateQuery.js';\nimport type {IRDeleteQuery} from './DeleteQuery.js';\nimport {isContextRefJSON, resolveContextId} from './ContextRef.js';\nimport {assertWireVersion} from './wireVersion.js';\nimport {\n decodeNodeDataToRaw,\n valueShapeOf,\n type MutationJSON,\n type MutationNodeDataJSON,\n type MutationValueJSON,\n} from './MutationSerialization.js';\nimport {assertValid, type ValidationMode} from '../shapes/validation.js';\nimport {decodeValueExpr, type DslJsonValue} from './DslJsonExpression.js';\nimport type {PropertyShapeData} from '../shapes/SHACL.js';\n\nfunction requireShape(shapeId: string): NodeShapeData {\n // Either registry: a project-authored shape arrives as metadata with no class, and\n // requiring a class here made every mutation against one fail at the boundary.\n const shape = getShapeClass(shapeId)?.shape ?? getNodeShape(shapeId);\n if (!shape) {\n throw new Error(\n `Shape '${shapeId}' is not registered. The receiving side must have the shape registered to lower mutation DSL-JSON.`,\n );\n }\n return shape;\n}\n\n// Bound the DSL-JSON decode recursion so a deeply-nested payload from\n// `fromJSON()` cannot exhaust the stack (RangeError DoS). Normal mutation data\n// nests only a handful of levels; 128 is far above any real query.\nconst MAX_DECODE_DEPTH = 128;\nlet _decodeDepth = 0;\n\n/**\n * Decode a DSL-JSON value to the normalized form the canonical-IR builders consume.\n * `currentShape` resolves computed `{@path}`/S-expr; `prop` gives a nested node's shape.\n * Depth-guarded wrapper around {@link decodeValueInner}.\n */\nfunction decodeValue(\n json: MutationValueJSON,\n currentShape: NodeShapeData,\n prop?: PropertyShapeData,\n): PropUpdateValue {\n if (++_decodeDepth > MAX_DECODE_DEPTH) {\n _decodeDepth = 0;\n throw new Error('DSL-JSON value nested too deeply');\n }\n try {\n return decodeValueInner(json, currentShape, prop);\n } finally {\n _decodeDepth--;\n }\n}\n\nfunction decodeValueInner(\n json: MutationValueJSON,\n currentShape: NodeShapeData,\n prop?: PropertyShapeData,\n): PropUpdateValue {\n // S-expr computed value (no IR on the wire)\n if (Array.isArray(json)) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, currentShape);\n return new ExpressionNode(ir, refs) as unknown as PropUpdateValue;\n }\n if (json === null) return null as unknown as PropUpdateValue;\n if (typeof json !== 'object') return json as PropUpdateValue; // bare scalar literal\n const o = json as Record<string, unknown>;\n if ('@unset' in o) return undefined;\n if ('@date' in o) return new Date(o['@date'] as string) as unknown as PropUpdateValue;\n if ('@ctx' in o) {\n // Lowering path: a mutation must hit a concrete node, so resolve the\n // context now and throw if it isn't set.\n const id = resolveContextId(o['@ctx'] as string, true)!;\n return {id} as PropUpdateValue;\n }\n if ('@id' in o) return {id: o['@id']} as PropUpdateValue;\n if ('@list' in o) {\n return (o['@list'] as MutationValueJSON[]).map(\n (item) => decodeValue(item, currentShape, prop) as SinglePropertyUpdateValue,\n );\n }\n if ('@add' in o || '@remove' in o) {\n const mod: SetModificationValue = {};\n if (o['@add']) {\n mod.$add = (o['@add'] as MutationValueJSON[]).map((v) =>\n decodeValue(v, currentShape, prop),\n ) as SetModificationValue['$add'];\n }\n if (o['@remove']) mod.$remove = (o['@remove'] as string[]).map((id) => ({id}));\n return mod as PropUpdateValue;\n }\n if ('@path' in o) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, currentShape);\n return new ExpressionNode(ir, refs) as unknown as PropUpdateValue;\n }\n // Otherwise: a bare path-keyed nested-node create.\n return decodeNodeData(\n o as MutationNodeDataJSON,\n valueShapeOf(prop) ?? currentShape,\n ) as unknown as PropUpdateValue;\n}\n\n/**\n * Rebuild a normalized node description from path-keyed JSON, resolving labels via the\n * shape. `shape` is the shape inferred from context; `__shape` overrides it.\n */\nexport function decodeNodeData(\n json: MutationNodeDataJSON,\n shape?: NodeShapeData,\n): NodeDescriptionValue {\n const nodeShape =\n typeof json.__shape === 'string' ? requireShape(json.__shape) : shape!;\n const fields: UpdateNodePropertyValue[] = [];\n for (const [key, val] of Object.entries(json)) {\n if (key === '__id' || key === '__shape' || val === undefined) continue;\n const prop = getPropertyShape(nodeShape, key);\n if (!prop) {\n throw new Error(\n `Property '${key}' not found on shape '${nodeShape.label || nodeShape.id}'`,\n );\n }\n fields.push({prop, val: decodeValue(val as MutationValueJSON, nodeShape, prop)} as UpdateNodePropertyValue);\n }\n const desc: NodeDescriptionValue = {shape: nodeShape, fields};\n if (typeof json.__id === 'string') desc.__id = json.__id;\n return desc;\n}\n\nfunction lowerWhere(\n shape: NodeShapeData,\n json: WherePathJSON,\n): {where: IRExpression; wherePatterns: IRGraphPattern[]} {\n const wherePath = deserializeWherePath(shape, json);\n return lowerWhereToIR(toWhere(wherePath));\n}\n\n/**\n * Lower a mutation DSL-JSON envelope to the canonical IR mutation the dataset\n * expects. Mirrors the IR that `lower()` produces from the live builder.\n */\n/**\n * Validate inbound node data against its shape before it becomes IR.\n *\n * The builders validate through `describe()`, which sees raw DSL data. This path\n * never touches a builder, so without this an inbound mutation would be held to\n * a weaker standard than a locally-built one — on the *less* trusted input, at\n * that. `decodeNodeDataToRaw` produces exactly the raw form `describe()` would\n * have validated (it is what `CreateBuilder.fromJSON` feeds through `.set()`),\n * so both paths run the same checks. The second decode is the cost of validating\n * at a boundary; it happens once per inbound mutation.\n */\nfunction assertInboundDataValid(\n json: MutationNodeDataJSON,\n shape: NodeShapeData,\n mode: ValidationMode,\n): void {\n assertValid(shape, decodeNodeDataToRaw(json, shape), {mode});\n}\n\nexport function lowerMutationJSON(\n json: MutationJSON,\n): IRCreateQuery | IRUpdateQuery | IRDeleteQuery {\n assertWireVersion(json.v);\n switch (json.op) {\n case 'create': {\n const shape = requireShape(json.shape);\n assertInboundDataValid(json.data, shape, 'complete');\n return buildCanonicalCreateMutationIR({\n shape,\n description: decodeNodeData(json.data, shape),\n });\n }\n case 'upsert': {\n const shape = requireShape(json.shape);\n assertInboundDataValid(json.data, shape, 'partial');\n const updates = decodeNodeData(json.data, shape);\n const id = isContextRefJSON(json.targetId)\n ? resolveContextId(json.targetId['@ctx'], true)\n : json.targetId;\n if (!id) {\n throw new Error('upsert requires a targetId');\n }\n return buildCanonicalUpsertMutationIR({id, shape, updates});\n }\n case 'update': {\n const shape = requireShape(json.shape);\n assertInboundDataValid(json.data, shape, 'partial');\n const updates = decodeNodeData(json.data, shape);\n if (json.mode === 'for') {\n // A `{@ctx}` target resolves against the current context map; a mutation\n // must hit a concrete subject, so an unresolved context throws.\n const id = isContextRefJSON(json.targetId)\n ? resolveContextId(json.targetId['@ctx'], true)\n : json.targetId;\n if (!id) {\n throw new Error('update mode \"for\" requires a targetId');\n }\n return buildCanonicalUpdateMutationIR({id, shape, updates});\n }\n let where: IRExpression | undefined;\n let wherePatterns: IRGraphPattern[] | undefined;\n if (json.mode === 'where') {\n if (!json.where) throw new Error('update mode \"where\" requires a where clause');\n ({where, wherePatterns} = lowerWhere(shape, json.where));\n }\n return buildCanonicalUpdateWhereMutationIR({shape, updates, where, wherePatterns});\n }\n case 'delete': {\n const shape = requireShape(json.shape);\n if (json.mode === 'ids') {\n return buildCanonicalDeleteMutationIR({\n shape,\n // A `{@ctx}` id resolves against the live map; a delete must hit a\n // concrete node, so an unresolved context throws.\n ids: json.ids.map((id) =>\n isContextRefJSON(id) ? {id: resolveContextId(id['@ctx'], true)!} : {id},\n ),\n });\n }\n if (json.mode === 'all') {\n return buildCanonicalDeleteAllMutationIR({shape});\n }\n const {where, wherePatterns} = lowerWhere(shape, json.where);\n return buildCanonicalDeleteWhereMutationIR({shape, where, wherePatterns});\n }\n }\n}\n"]}
|
package/lib/esm/shapes/List.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"List.js","sourceRoot":"","sources":["../../../src/shapes/List.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,2FAA2F;AAC3F,yFAAyF;AACzF,wFAAwF;AACxF,OAAO,qBAAqB,CAAC;AAC7B,OAAO,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAC,GAAG,EAAC,MAAM,sBAAsB,CAAC;AAEzC,OAAO,EAAC,IAAI,EAAC,CAAC;AASd;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CACrB,KAAU,EACV,IAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,CAAC,CAAS,EAAmB,EAAE;QAC3C,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,EAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAC,CAAC;QAC1B,CAAC;QACD,MAAM,IAAI,GAAoB;YAC5B,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YACf,IAAI,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;SACnB,CAAC;QACF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC","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// Registers List (together with the rest of the SHACL metamodel), so importing this module\n// on its own is enough to make List resolvable. The class lives in List.class.ts because\n// utils/Package.ts needs it by value and cannot import this module's registration path.\nimport '../utils/Package.js';\nimport {List} from './List.class.js';\nimport {rdf} from '../ontologies/rdf.js';\n\nexport {List};\n\n/**\n * Node-data for a single cell / the `rdf:nil` terminal. Accepted by the create pipeline.\n */\nexport type RdfListNodeData =\n | {id: string}\n | {shape: typeof List; first: unknown; rest: RdfListNodeData; __id?: string
|
|
1
|
+
{"version":3,"file":"List.js","sourceRoot":"","sources":["../../../src/shapes/List.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,2FAA2F;AAC3F,yFAAyF;AACzF,wFAAwF;AACxF,OAAO,qBAAqB,CAAC;AAC7B,OAAO,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAC,GAAG,EAAC,MAAM,sBAAsB,CAAC;AAEzC,OAAO,EAAC,IAAI,EAAC,CAAC;AASd;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CACrB,KAAU,EACV,IAAsB;IAEtB,MAAM,IAAI,GAAG,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,CAAC;IACxB,MAAM,KAAK,GAAG,CAAC,CAAS,EAAmB,EAAE;QAC3C,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,EAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAC,CAAC;QAC1B,CAAC;QACD,MAAM,IAAI,GAAoB;YAC5B,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YACf,IAAI,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;SACnB,CAAC;QACF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC","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// Registers List (together with the rest of the SHACL metamodel), so importing this module\n// on its own is enough to make List resolvable. The class lives in List.class.ts because\n// utils/Package.ts needs it by value and cannot import this module's registration path.\nimport '../utils/Package.js';\nimport {List} from './List.class.js';\nimport {rdf} from '../ontologies/rdf.js';\n\nexport {List};\n\n/**\n * Node-data for a single cell / the `rdf:nil` terminal. Accepted by the create pipeline.\n */\nexport type RdfListNodeData =\n | {id: string}\n | {shape: typeof List; first: unknown; rest: RdfListNodeData; __id?: string};\n\n/**\n * Build the nested `List` node-data chain for an ordered `rdf:List`, terminating at `rdf:nil`.\n * Pass `opts.base` to mint deterministic cell ids (`{base}/0`, `{base}/1`, …); otherwise the\n * create pipeline mints ids. The empty list serializes to `rdf:nil`.\n *\n * @example Playlist.create({ tracks: rdfList([t1, t2, t3]) })\n */\nexport function rdfList<T>(\n items: T[],\n opts?: {base?: string},\n): RdfListNodeData {\n const base = opts?.base;\n const build = (i: number): RdfListNodeData => {\n if (i >= items.length) {\n return {id: rdf.nil.id};\n }\n const cell: RdfListNodeData = {\n shape: List,\n first: items[i],\n rest: build(i + 1),\n };\n if (base !== undefined) {\n cell.__id = `${base}/${i}`;\n }\n return cell;\n };\n return build(0);\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Shape } from './Shape.js';
|
|
2
|
+
/**
|
|
3
|
+
* A cell of the `rdf:List` inside a SHACL property path: the members of a sequence path, or the
|
|
4
|
+
* operand of `sh:alternativePath`.
|
|
5
|
+
*
|
|
6
|
+
* Both properties are `sh:BlankNodeOrIRI`, so a cell written without an id is a blank node, and so
|
|
7
|
+
* is an operator node (`PathNode`) held by `first`. That keeps a sequence path a blank list, which
|
|
8
|
+
* SHACL §2.3.1 needs: an IRI as the `sh:path` value is a predicate path.
|
|
9
|
+
*
|
|
10
|
+
* It is a separate shape from `List` on purpose. `List.first` also holds literals (`sh:in`), so it
|
|
11
|
+
* cannot be declared node-only, and making `List.rest` blank-capable would turn the tail cells of
|
|
12
|
+
* every list built without ids into blank nodes. Both shapes target `rdf:List`; `List` is
|
|
13
|
+
* registered first, so a lookup by `rdf:List` still returns `List`.
|
|
14
|
+
*
|
|
15
|
+
* `dependent` and the `contains` on `rest` keep removing the IRI-named, typed list cells of
|
|
16
|
+
* versions before 2.30 through the typed cascade.
|
|
17
|
+
*/
|
|
18
|
+
export declare class PathList extends Shape {
|
|
19
|
+
static targetClass: import("../utils/NodeReference.js").NodeReferenceValue;
|
|
20
|
+
/**
|
|
21
|
+
* A predicate IRI, or an operator node (`PathNode`). Not `contains`: ownership is decided per
|
|
22
|
+
* predicate across the registry, and `rdf:first` of every other list holds values the list
|
|
23
|
+
* does not own. The blank-node cascade follows it anyway, because it is blank-capable.
|
|
24
|
+
*/
|
|
25
|
+
get first(): unknown;
|
|
26
|
+
get rest(): PathList;
|
|
27
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
/*
|
|
8
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
9
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
10
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
11
|
+
*/
|
|
12
|
+
import { linkedShape } from '../package.js';
|
|
13
|
+
import { Shape } from './Shape.js';
|
|
14
|
+
import { objectProperty } from './SHACL.js';
|
|
15
|
+
import { shacl } from '../ontologies/shacl.js';
|
|
16
|
+
import { rdf } from '../ontologies/rdf.js';
|
|
17
|
+
/**
|
|
18
|
+
* A cell of the `rdf:List` inside a SHACL property path: the members of a sequence path, or the
|
|
19
|
+
* operand of `sh:alternativePath`.
|
|
20
|
+
*
|
|
21
|
+
* Both properties are `sh:BlankNodeOrIRI`, so a cell written without an id is a blank node, and so
|
|
22
|
+
* is an operator node (`PathNode`) held by `first`. That keeps a sequence path a blank list, which
|
|
23
|
+
* SHACL §2.3.1 needs: an IRI as the `sh:path` value is a predicate path.
|
|
24
|
+
*
|
|
25
|
+
* It is a separate shape from `List` on purpose. `List.first` also holds literals (`sh:in`), so it
|
|
26
|
+
* cannot be declared node-only, and making `List.rest` blank-capable would turn the tail cells of
|
|
27
|
+
* every list built without ids into blank nodes. Both shapes target `rdf:List`; `List` is
|
|
28
|
+
* registered first, so a lookup by `rdf:List` still returns `List`.
|
|
29
|
+
*
|
|
30
|
+
* `dependent` and the `contains` on `rest` keep removing the IRI-named, typed list cells of
|
|
31
|
+
* versions before 2.30 through the typed cascade.
|
|
32
|
+
*/
|
|
33
|
+
let PathList = class PathList extends Shape {
|
|
34
|
+
/**
|
|
35
|
+
* A predicate IRI, or an operator node (`PathNode`). Not `contains`: ownership is decided per
|
|
36
|
+
* predicate across the registry, and `rdf:first` of every other list holds values the list
|
|
37
|
+
* does not own. The blank-node cascade follows it anyway, because it is blank-capable.
|
|
38
|
+
*/
|
|
39
|
+
get first() {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
get rest() {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
PathList.targetClass = rdf.List;
|
|
47
|
+
__decorate([
|
|
48
|
+
objectProperty({ path: rdf.first, maxCount: 1, nodeKind: shacl.BlankNodeOrIRI })
|
|
49
|
+
], PathList.prototype, "first", null);
|
|
50
|
+
__decorate([
|
|
51
|
+
objectProperty({
|
|
52
|
+
path: rdf.rest,
|
|
53
|
+
maxCount: 1,
|
|
54
|
+
shape: PathList,
|
|
55
|
+
contains: true,
|
|
56
|
+
nodeKind: shacl.BlankNodeOrIRI,
|
|
57
|
+
})
|
|
58
|
+
], PathList.prototype, "rest", null);
|
|
59
|
+
PathList = __decorate([
|
|
60
|
+
linkedShape({ name: 'PathList', dependent: true })
|
|
61
|
+
], PathList);
|
|
62
|
+
export { PathList };
|
|
63
|
+
//# sourceMappingURL=PathList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PathList.js","sourceRoot":"","sources":["../../../src/shapes/PathList.ts"],"names":[],"mappings":";;;;;;AAAA;;;;GAIG;AACH,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAC,KAAK,EAAC,MAAM,wBAAwB,CAAC;AAC7C,OAAO,EAAC,GAAG,EAAC,MAAM,sBAAsB,CAAC;AAEzC;;;;;;;;;;;;;;;GAeG;AAEI,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,KAAK;IAGjC;;;;OAIG;IAEH,IAAI,KAAK;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IASD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC;IACd,CAAC;;AArBM,oBAAW,GAAG,GAAG,CAAC,IAAI,AAAX,CAAY;AAQ9B;IADC,cAAc,CAAC,EAAC,IAAI,EAAE,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAC,CAAC;qCAG9E;AASD;IAPC,cAAc,CAAC;QACd,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,QAAQ,EAAE,CAAC;QACX,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,KAAK,CAAC,cAAc;KAC/B,CAAC;oCAGD;AAtBU,QAAQ;IADpB,WAAW,CAAC,EAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAC,CAAC;GACpC,QAAQ,CAuBpB","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 {linkedShape} from '../package.js';\nimport {Shape} from './Shape.js';\nimport {objectProperty} from './SHACL.js';\nimport {shacl} from '../ontologies/shacl.js';\nimport {rdf} from '../ontologies/rdf.js';\n\n/**\n * A cell of the `rdf:List` inside a SHACL property path: the members of a sequence path, or the\n * operand of `sh:alternativePath`.\n *\n * Both properties are `sh:BlankNodeOrIRI`, so a cell written without an id is a blank node, and so\n * is an operator node (`PathNode`) held by `first`. That keeps a sequence path a blank list, which\n * SHACL §2.3.1 needs: an IRI as the `sh:path` value is a predicate path.\n *\n * It is a separate shape from `List` on purpose. `List.first` also holds literals (`sh:in`), so it\n * cannot be declared node-only, and making `List.rest` blank-capable would turn the tail cells of\n * every list built without ids into blank nodes. Both shapes target `rdf:List`; `List` is\n * registered first, so a lookup by `rdf:List` still returns `List`.\n *\n * `dependent` and the `contains` on `rest` keep removing the IRI-named, typed list cells of\n * versions before 2.30 through the typed cascade.\n */\n@linkedShape({name: 'PathList', dependent: true})\nexport class PathList extends Shape {\n static targetClass = rdf.List;\n\n /**\n * A predicate IRI, or an operator node (`PathNode`). Not `contains`: ownership is decided per\n * predicate across the registry, and `rdf:first` of every other list holds values the list\n * does not own. The blank-node cascade follows it anyway, because it is blank-capable.\n */\n @objectProperty({path: rdf.first, maxCount: 1, nodeKind: shacl.BlankNodeOrIRI})\n get first(): unknown {\n return null;\n }\n\n @objectProperty({\n path: rdf.rest,\n maxCount: 1,\n shape: PathList,\n contains: true,\n nodeKind: shacl.BlankNodeOrIRI,\n })\n get rest(): PathList {\n return null;\n }\n}\n"]}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { Shape } from './Shape.js';
|
|
2
|
-
import {
|
|
2
|
+
import { PathList } from './PathList.js';
|
|
3
3
|
/**
|
|
4
4
|
* Operator node for SHACL property paths that are NOT a simple predicate or a sequence:
|
|
5
5
|
* inverse (`sh:inversePath`), alternative (`sh:alternativePath` → an `rdf:List`), and the
|
|
6
6
|
* cardinality forms (`sh:zeroOrMorePath`/`sh:oneOrMorePath`/`sh:zeroOrOnePath`).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* only form SHACL §2.3.1 defines, a blank node that is
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
8
|
+
* Every slot is `sh:BlankNodeOrIRI`, as is `PropertyShape.path`, so an operator node written
|
|
9
|
+
* without an id is an untyped blank node: the only form SHACL §2.3.1 defines, a blank node that is
|
|
10
|
+
* the subject of exactly one triple (see `serializePathToNodeData`). The blank-node cascade
|
|
11
|
+
* follows these blank-capable slots on delete / replace. The class stays `dependent`, with
|
|
12
|
+
* `contains` slots and its `core:PathNode` type, for the IRI-named, typed nodes versions before
|
|
13
|
+
* 2.30 wrote: the typed cascade removes those on the next sync.
|
|
14
|
+
* Operands are polymorphic (a predicate IRI, a nested `PathNode`, or a `PathList`), so no fixed
|
|
15
|
+
* `valueShape` is declared except for `alternativePath`, which is always a `PathList`.
|
|
15
16
|
*/
|
|
16
17
|
export declare class PathNode extends Shape {
|
|
17
18
|
static targetClass: import("../utils/NodeReference.js").NodeReferenceValue;
|
|
18
19
|
get inversePath(): unknown;
|
|
19
|
-
get alternativePath():
|
|
20
|
+
get alternativePath(): PathList;
|
|
20
21
|
get zeroOrMorePath(): unknown;
|
|
21
22
|
get oneOrMorePath(): unknown;
|
|
22
23
|
get zeroOrOnePath(): unknown;
|
|
@@ -14,19 +14,21 @@ import { Shape } from './Shape.js';
|
|
|
14
14
|
import { objectProperty } from './SHACL.js';
|
|
15
15
|
import { shacl } from '../ontologies/shacl.js';
|
|
16
16
|
import { coreOntology } from '../ontologies/linked-core.js';
|
|
17
|
-
import {
|
|
17
|
+
import { PathList } from './PathList.js';
|
|
18
|
+
const BLANK_OR_IRI = shacl.BlankNodeOrIRI;
|
|
18
19
|
/**
|
|
19
20
|
* Operator node for SHACL property paths that are NOT a simple predicate or a sequence:
|
|
20
21
|
* inverse (`sh:inversePath`), alternative (`sh:alternativePath` → an `rdf:List`), and the
|
|
21
22
|
* cardinality forms (`sh:zeroOrMorePath`/`sh:oneOrMorePath`/`sh:zeroOrOnePath`).
|
|
22
23
|
*
|
|
23
|
-
*
|
|
24
|
-
* only form SHACL §2.3.1 defines, a blank node that is
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
24
|
+
* Every slot is `sh:BlankNodeOrIRI`, as is `PropertyShape.path`, so an operator node written
|
|
25
|
+
* without an id is an untyped blank node: the only form SHACL §2.3.1 defines, a blank node that is
|
|
26
|
+
* the subject of exactly one triple (see `serializePathToNodeData`). The blank-node cascade
|
|
27
|
+
* follows these blank-capable slots on delete / replace. The class stays `dependent`, with
|
|
28
|
+
* `contains` slots and its `core:PathNode` type, for the IRI-named, typed nodes versions before
|
|
29
|
+
* 2.30 wrote: the typed cascade removes those on the next sync.
|
|
30
|
+
* Operands are polymorphic (a predicate IRI, a nested `PathNode`, or a `PathList`), so no fixed
|
|
31
|
+
* `valueShape` is declared except for `alternativePath`, which is always a `PathList`.
|
|
30
32
|
*/
|
|
31
33
|
// Named explicitly: the class shares its name with the ontology term coreOntology.PathNode,
|
|
32
34
|
// and a bundler resolving that collision renames the class (PathNode2), which would change
|
|
@@ -50,19 +52,25 @@ let PathNode = class PathNode extends Shape {
|
|
|
50
52
|
};
|
|
51
53
|
PathNode.targetClass = coreOntology.PathNode;
|
|
52
54
|
__decorate([
|
|
53
|
-
objectProperty({ path: shacl.inversePath, maxCount: 1, contains: true })
|
|
55
|
+
objectProperty({ path: shacl.inversePath, maxCount: 1, contains: true, nodeKind: BLANK_OR_IRI })
|
|
54
56
|
], PathNode.prototype, "inversePath", null);
|
|
55
57
|
__decorate([
|
|
56
|
-
objectProperty({
|
|
58
|
+
objectProperty({
|
|
59
|
+
path: shacl.alternativePath,
|
|
60
|
+
maxCount: 1,
|
|
61
|
+
shape: PathList,
|
|
62
|
+
contains: true,
|
|
63
|
+
nodeKind: BLANK_OR_IRI,
|
|
64
|
+
})
|
|
57
65
|
], PathNode.prototype, "alternativePath", null);
|
|
58
66
|
__decorate([
|
|
59
|
-
objectProperty({ path: shacl.zeroOrMorePath, maxCount: 1, contains: true })
|
|
67
|
+
objectProperty({ path: shacl.zeroOrMorePath, maxCount: 1, contains: true, nodeKind: BLANK_OR_IRI })
|
|
60
68
|
], PathNode.prototype, "zeroOrMorePath", null);
|
|
61
69
|
__decorate([
|
|
62
|
-
objectProperty({ path: shacl.oneOrMorePath, maxCount: 1, contains: true })
|
|
70
|
+
objectProperty({ path: shacl.oneOrMorePath, maxCount: 1, contains: true, nodeKind: BLANK_OR_IRI })
|
|
63
71
|
], PathNode.prototype, "oneOrMorePath", null);
|
|
64
72
|
__decorate([
|
|
65
|
-
objectProperty({ path: shacl.zeroOrOnePath, maxCount: 1, contains: true })
|
|
73
|
+
objectProperty({ path: shacl.zeroOrOnePath, maxCount: 1, contains: true, nodeKind: BLANK_OR_IRI })
|
|
66
74
|
], PathNode.prototype, "zeroOrOnePath", null);
|
|
67
75
|
PathNode = __decorate([
|
|
68
76
|
linkedShape({ name: 'PathNode', dependent: true })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PathNode.js","sourceRoot":"","sources":["../../../src/shapes/PathNode.ts"],"names":[],"mappings":";;;;;;AAAA;;;;GAIG;AACH,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAC,KAAK,EAAC,MAAM,wBAAwB,CAAC;AAC7C,OAAO,EAAC,YAAY,EAAC,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"PathNode.js","sourceRoot":"","sources":["../../../src/shapes/PathNode.ts"],"names":[],"mappings":";;;;;;AAAA;;;;GAIG;AACH,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAC,KAAK,EAAC,MAAM,wBAAwB,CAAC;AAC7C,OAAO,EAAC,YAAY,EAAC,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAEvC,MAAM,YAAY,GAAG,KAAK,CAAC,cAAc,CAAC;AAE1C;;;;;;;;;;;;;GAaG;AACH,4FAA4F;AAC5F,2FAA2F;AAC3F,mBAAmB;AAEZ,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,KAAK;IAIjC,IAAI,WAAW;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IASD,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,IAAI,aAAa;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,IAAI,aAAa;QACf,OAAO,IAAI,CAAC;IACd,CAAC;;AA/BM,oBAAW,GAAG,YAAY,CAAC,QAAQ,AAAxB,CAAyB;AAG3C;IADC,cAAc,CAAC,EAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAC,CAAC;2CAG9F;AASD;IAPC,cAAc,CAAC;QACd,IAAI,EAAE,KAAK,CAAC,eAAe;QAC3B,QAAQ,EAAE,CAAC;QACX,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,YAAY;KACvB,CAAC;+CAGD;AAGD;IADC,cAAc,CAAC,EAAC,IAAI,EAAE,KAAK,CAAC,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAC,CAAC;8CAGjG;AAGD;IADC,cAAc,CAAC,EAAC,IAAI,EAAE,KAAK,CAAC,aAAa,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAC,CAAC;6CAGhG;AAGD;IADC,cAAc,CAAC,EAAC,IAAI,EAAE,KAAK,CAAC,aAAa,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAC,CAAC;6CAGhG;AAhCU,QAAQ;IADpB,WAAW,CAAC,EAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAC,CAAC;GACpC,QAAQ,CAiCpB","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 {linkedShape} from '../package.js';\nimport {Shape} from './Shape.js';\nimport {objectProperty} from './SHACL.js';\nimport {shacl} from '../ontologies/shacl.js';\nimport {coreOntology} from '../ontologies/linked-core.js';\nimport {PathList} from './PathList.js';\n\nconst BLANK_OR_IRI = shacl.BlankNodeOrIRI;\n\n/**\n * Operator node for SHACL property paths that are NOT a simple predicate or a sequence:\n * inverse (`sh:inversePath`), alternative (`sh:alternativePath` → an `rdf:List`), and the\n * cardinality forms (`sh:zeroOrMorePath`/`sh:oneOrMorePath`/`sh:zeroOrOnePath`).\n *\n * Every slot is `sh:BlankNodeOrIRI`, as is `PropertyShape.path`, so an operator node written\n * without an id is an untyped blank node: the only form SHACL §2.3.1 defines, a blank node that is\n * the subject of exactly one triple (see `serializePathToNodeData`). The blank-node cascade\n * follows these blank-capable slots on delete / replace. The class stays `dependent`, with\n * `contains` slots and its `core:PathNode` type, for the IRI-named, typed nodes versions before\n * 2.30 wrote: the typed cascade removes those on the next sync.\n * Operands are polymorphic (a predicate IRI, a nested `PathNode`, or a `PathList`), so no fixed\n * `valueShape` is declared except for `alternativePath`, which is always a `PathList`.\n */\n// Named explicitly: the class shares its name with the ontology term coreOntology.PathNode,\n// and a bundler resolving that collision renames the class (PathNode2), which would change\n// the shape's IRI.\n@linkedShape({name: 'PathNode', dependent: true})\nexport class PathNode extends Shape {\n static targetClass = coreOntology.PathNode;\n\n @objectProperty({path: shacl.inversePath, maxCount: 1, contains: true, nodeKind: BLANK_OR_IRI})\n get inversePath(): unknown {\n return null;\n }\n\n @objectProperty({\n path: shacl.alternativePath,\n maxCount: 1,\n shape: PathList,\n contains: true,\n nodeKind: BLANK_OR_IRI,\n })\n get alternativePath(): PathList {\n return null;\n }\n\n @objectProperty({path: shacl.zeroOrMorePath, maxCount: 1, contains: true, nodeKind: BLANK_OR_IRI})\n get zeroOrMorePath(): unknown {\n return null;\n }\n\n @objectProperty({path: shacl.oneOrMorePath, maxCount: 1, contains: true, nodeKind: BLANK_OR_IRI})\n get oneOrMorePath(): unknown {\n return null;\n }\n\n @objectProperty({path: shacl.zeroOrOnePath, maxCount: 1, contains: true, nodeKind: BLANK_OR_IRI})\n get zeroOrOnePath(): unknown {\n return null;\n }\n}\n"]}
|
package/lib/esm/shapes/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shapes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qFAAqF;AACrF,mFAAmF;AACnF,EAAE;AACF,2FAA2F;AAC3F,qFAAqF;AACrF,OAAO,YAAY,CAAC;AACpB,OAAO,WAAW,CAAC;AACnB,OAAO,eAAe,CAAC","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// Loads every shape @_linked/core defines, for their registration side effects only.\n// Consumers: `import '@_linked/core/shapes/index'`. Nothing is exported from here.\n//\n// Shape, NodeShape, PropertyShape and List are registered by utils/Package.ts, because the\n// SHACL metamodel cannot decorate itself. List.js loads it; SHACL.js alone does not.\nimport './SHACL.js';\nimport './List.js';\nimport './PathNode.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shapes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qFAAqF;AACrF,mFAAmF;AACnF,EAAE;AACF,2FAA2F;AAC3F,qFAAqF;AACrF,OAAO,YAAY,CAAC;AACpB,OAAO,WAAW,CAAC;AACnB,OAAO,eAAe,CAAC;AACvB,OAAO,eAAe,CAAC","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// Loads every shape @_linked/core defines, for their registration side effects only.\n// Consumers: `import '@_linked/core/shapes/index'`. Nothing is exported from here.\n//\n// Shape, NodeShape, PropertyShape and List are registered by utils/Package.ts, because the\n// SHACL metamodel cannot decorate itself. List.js loads it; SHACL.js alone does not.\nimport './SHACL.js';\nimport './List.js';\nimport './PathList.js';\nimport './PathNode.js';\n"]}
|
|
@@ -1,34 +1,35 @@
|
|
|
1
1
|
import type { PathExpr } from '../paths/PropertyPathExpr.js';
|
|
2
2
|
import type { NodeReferenceValue } from '../utils/NodeReference.js';
|
|
3
|
-
import {
|
|
3
|
+
import { PathList } from './PathList.js';
|
|
4
4
|
import { PathNode } from './PathNode.js';
|
|
5
5
|
/**
|
|
6
6
|
* Node-data the create pipeline accepts for a `sh:path` value: an IRI reference (simple path),
|
|
7
|
-
*
|
|
7
|
+
* a `PathList` (sequence / alternative members), or a `PathNode` operator node.
|
|
8
8
|
*/
|
|
9
9
|
export type PathNodeData = NodeReferenceValue | {
|
|
10
|
-
shape: typeof
|
|
11
|
-
__blank: true;
|
|
10
|
+
shape: typeof PathList | typeof PathNode;
|
|
12
11
|
[k: string]: unknown;
|
|
13
12
|
};
|
|
14
13
|
/**
|
|
15
14
|
* Translate a `PathExpr` into create-pipeline node-data for `sh:path`.
|
|
16
15
|
*
|
|
17
16
|
* - simple `PathRef` → `{id}` (a shared predicate IRI; NOT owned)
|
|
18
|
-
* - sequence → an `rdf:List` of segments
|
|
19
|
-
* - inverse / alternative / cardinality → a `PathNode` operator node (alt's operand is
|
|
17
|
+
* - sequence → a `PathList` (an `rdf:List`) of segments
|
|
18
|
+
* - inverse / alternative / cardinality → a `PathNode` operator node (alt's operand is a `PathList`)
|
|
20
19
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* Operator nodes and list cells carry no id. `PropertyShape.path`, the `PathNode` slots and
|
|
21
|
+
* `PathList.first` / `.rest` are `sh:BlankNodeOrIRI`, so the create writes each of them as an
|
|
22
|
+
* untyped blank node, the only form SHACL §2.3.1 defines: an IRI in `sh:path` is a predicate path,
|
|
23
|
+
* and an inverse, alternative or cardinality path is a blank node that is the subject of exactly
|
|
24
|
+
* one triple.
|
|
24
25
|
*
|
|
25
26
|
* ```turtle
|
|
26
27
|
* <ps> sh:path [ sh:inversePath schema:image ] .
|
|
27
28
|
* <ps> sh:path ( schema:knows [ sh:zeroOrMorePath schema:parent ] ) .
|
|
28
29
|
* ```
|
|
29
30
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
31
|
+
* A re-sync's delete removes the structure (the blank-node cascade follows the blank-capable
|
|
32
|
+
* properties) before the create writes it again.
|
|
32
33
|
*
|
|
33
34
|
* @param _base ignored. It seeded the IRIs of the nodes this used to mint (`{base}/inv`, …);
|
|
34
35
|
* blank nodes have none. Kept so existing two-argument calls still compile.
|