@shaclmate/shacl-ast 4.0.50 → 4.0.51
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/dist/AbstractShapesGraph.d.ts +75 -0
- package/dist/AbstractShapesGraph.js +364 -0
- package/dist/Curie.d.ts +21 -0
- package/dist/Curie.js +29 -0
- package/dist/CurieFactory.d.ts +16 -0
- package/dist/CurieFactory.js +46 -0
- package/dist/IdentifierNodeKind.d.ts +6 -0
- package/dist/IdentifierNodeKind.js +2 -0
- package/dist/NodeKind.d.ts +11 -0
- package/dist/NodeKind.js +43 -0
- package/dist/ShapesGraph.d.ts +27 -0
- package/dist/ShapesGraph.js +49 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/shacl-ast.shaclmate.d.ts +4019 -0
- package/dist/shacl-ast.shaclmate.js +3265 -0
- package/package.json +17 -17
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type PrefixMap from "@rdfjs/prefix-map/PrefixMap.js";
|
|
2
|
+
import TermMap from "@rdfjs/term-map";
|
|
3
|
+
import type { BlankNode, DatasetCore, NamedNode } from "@rdfjs/types";
|
|
4
|
+
import { type Resource, ResourceSet } from "@rdfx/resource";
|
|
5
|
+
import { Either } from "purify-ts";
|
|
6
|
+
import type * as generated from "./shacl-ast.shaclmate.js";
|
|
7
|
+
export declare abstract class AbstractShapesGraph<NodeShapeT extends generated.NodeShape, OntologyT extends generated.Ontology, PropertyGroupT extends generated.PropertyGroup, PropertyShapeT extends generated.PropertyShape> {
|
|
8
|
+
private readonly nodeShapesByIdentifier;
|
|
9
|
+
private readonly ontologiesByIdentifier;
|
|
10
|
+
private readonly propertyGroupsByIdentifier;
|
|
11
|
+
private readonly propertyShapesByIdentifier;
|
|
12
|
+
protected abstract readonly typeFunctions: {
|
|
13
|
+
NodeShape: TypeFunctions<NodeShapeT>;
|
|
14
|
+
Ontology: TypeFunctions<OntologyT>;
|
|
15
|
+
PropertyGroup: TypeFunctions<PropertyGroupT>;
|
|
16
|
+
PropertyShape: TypeFunctions<PropertyShapeT>;
|
|
17
|
+
};
|
|
18
|
+
constructor(parameters: {
|
|
19
|
+
nodeShapesByIdentifier: IdentifierMap<NodeShapeT>;
|
|
20
|
+
ontologiesByIdentifier: IdentifierMap<OntologyT>;
|
|
21
|
+
propertyGroupsByIdentifier: IdentifierMap<PropertyGroupT>;
|
|
22
|
+
propertyShapesByIdentifier: IdentifierMap<PropertyShapeT>;
|
|
23
|
+
});
|
|
24
|
+
get nodeShapes(): readonly NodeShapeT[];
|
|
25
|
+
get ontologies(): readonly OntologyT[];
|
|
26
|
+
get propertyGroups(): readonly PropertyGroupT[];
|
|
27
|
+
get propertyShapes(): readonly PropertyShapeT[];
|
|
28
|
+
nodeShape(identifier: BlankNode | NamedNode): Either<Error, NodeShapeT>;
|
|
29
|
+
ontology(identifier: BlankNode | NamedNode): Either<Error, OntologyT>;
|
|
30
|
+
propertyGroup(identifier: BlankNode | NamedNode): Either<Error, PropertyGroupT>;
|
|
31
|
+
propertyShape(identifier: BlankNode | NamedNode): Either<Error, PropertyShapeT>;
|
|
32
|
+
shape(identifier: BlankNode | NamedNode): Either<Error, NodeShapeT | PropertyShapeT>;
|
|
33
|
+
/**
|
|
34
|
+
* Convert the shapes graph to a dataset.
|
|
35
|
+
*/
|
|
36
|
+
toDataset(): DatasetCore;
|
|
37
|
+
/**
|
|
38
|
+
* Convert the shapes graph to an RDF string.
|
|
39
|
+
*
|
|
40
|
+
* If the format isn't specified, defaults to N-Triples.
|
|
41
|
+
*/
|
|
42
|
+
toString(options?: {
|
|
43
|
+
format?: "application/n-triples" | "application/n-quads";
|
|
44
|
+
}): string;
|
|
45
|
+
}
|
|
46
|
+
type IdentifierMap<T> = TermMap<BlankNode | NamedNode, T>;
|
|
47
|
+
type TypeFunctions<T> = {
|
|
48
|
+
fromRdfResource: (resource: Resource, options?: {
|
|
49
|
+
ignoreRdfType?: boolean;
|
|
50
|
+
}) => Either<Error, T>;
|
|
51
|
+
toRdfResource: (value: T, options?: {
|
|
52
|
+
resourceSet?: ResourceSet;
|
|
53
|
+
}) => Resource;
|
|
54
|
+
};
|
|
55
|
+
export declare namespace AbstractShapesGraph {
|
|
56
|
+
abstract class AbstractBuilder<NodeShapeT extends generated.NodeShape, OntologyT extends generated.Ontology, PropertyGroupT extends generated.PropertyGroup, PropertyShapeT extends generated.PropertyShape> {
|
|
57
|
+
protected readonly nodeShapesByIdentifier: IdentifierMap<NodeShapeT>;
|
|
58
|
+
protected readonly ontologiesByIdentifier: IdentifierMap<OntologyT>;
|
|
59
|
+
protected readonly propertyGroupsByIdentifier: IdentifierMap<PropertyGroupT>;
|
|
60
|
+
protected readonly propertyShapesByIdentifier: IdentifierMap<PropertyShapeT>;
|
|
61
|
+
protected abstract readonly typeFunctions: {
|
|
62
|
+
NodeShape: TypeFunctions<NodeShapeT>;
|
|
63
|
+
Ontology: TypeFunctions<OntologyT>;
|
|
64
|
+
PropertyGroup: TypeFunctions<PropertyGroupT>;
|
|
65
|
+
PropertyShape: TypeFunctions<PropertyShapeT>;
|
|
66
|
+
};
|
|
67
|
+
add(...objects: readonly (NodeShapeT | OntologyT | PropertyGroupT | PropertyShapeT)[]): this;
|
|
68
|
+
parseDataset(dataset: DatasetCore, options?: {
|
|
69
|
+
ignoreUndefinedShapes?: boolean;
|
|
70
|
+
prefixMap?: PrefixMap;
|
|
71
|
+
}): Either<Error, this>;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export {};
|
|
75
|
+
//# sourceMappingURL=AbstractShapesGraph.d.ts.map
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import datasetFactory from "@rdfjs/dataset";
|
|
2
|
+
import TermMap from "@rdfjs/term-map";
|
|
3
|
+
import TermSet from "@rdfjs/term-set";
|
|
4
|
+
import dataFactory from "@rdfx/data-factory";
|
|
5
|
+
import { ResourceSet } from "@rdfx/resource";
|
|
6
|
+
import { NTriplesTerm } from "@rdfx/string";
|
|
7
|
+
import { owl, sh } from "@tpluscode/rdf-ns-builders";
|
|
8
|
+
import { Either, Left } from "purify-ts";
|
|
9
|
+
import { CurieFactory } from "./CurieFactory.js";
|
|
10
|
+
export class AbstractShapesGraph {
|
|
11
|
+
nodeShapesByIdentifier;
|
|
12
|
+
ontologiesByIdentifier;
|
|
13
|
+
propertyGroupsByIdentifier;
|
|
14
|
+
propertyShapesByIdentifier;
|
|
15
|
+
constructor(parameters) {
|
|
16
|
+
// Defensive copies
|
|
17
|
+
this.nodeShapesByIdentifier = new TermMap([
|
|
18
|
+
...parameters.nodeShapesByIdentifier.entries(),
|
|
19
|
+
]);
|
|
20
|
+
this.ontologiesByIdentifier = new TermMap([
|
|
21
|
+
...parameters.ontologiesByIdentifier.entries(),
|
|
22
|
+
]);
|
|
23
|
+
this.propertyGroupsByIdentifier = new TermMap([
|
|
24
|
+
...parameters.propertyGroupsByIdentifier.entries(),
|
|
25
|
+
]);
|
|
26
|
+
this.propertyShapesByIdentifier = new TermMap([
|
|
27
|
+
...parameters.propertyShapesByIdentifier.entries(),
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
30
|
+
get nodeShapes() {
|
|
31
|
+
return [...this.nodeShapesByIdentifier.values()];
|
|
32
|
+
}
|
|
33
|
+
get ontologies() {
|
|
34
|
+
return [...this.ontologiesByIdentifier.values()];
|
|
35
|
+
}
|
|
36
|
+
get propertyGroups() {
|
|
37
|
+
return [...this.propertyGroupsByIdentifier.values()];
|
|
38
|
+
}
|
|
39
|
+
get propertyShapes() {
|
|
40
|
+
return [...this.propertyShapesByIdentifier.values()];
|
|
41
|
+
}
|
|
42
|
+
nodeShape(identifier) {
|
|
43
|
+
const nodeShape = this.nodeShapesByIdentifier.get(identifier);
|
|
44
|
+
return nodeShape
|
|
45
|
+
? Either.of(nodeShape)
|
|
46
|
+
: Left(new Error(`no such node shape ${identifier}`));
|
|
47
|
+
}
|
|
48
|
+
ontology(identifier) {
|
|
49
|
+
const ontology = this.ontologiesByIdentifier.get(identifier);
|
|
50
|
+
return ontology
|
|
51
|
+
? Either.of(ontology)
|
|
52
|
+
: Left(new Error(`no such ontology ${identifier}`));
|
|
53
|
+
}
|
|
54
|
+
propertyGroup(identifier) {
|
|
55
|
+
const propertyGroup = this.propertyGroupsByIdentifier.get(identifier);
|
|
56
|
+
return propertyGroup
|
|
57
|
+
? Either.of(propertyGroup)
|
|
58
|
+
: Left(new Error(`no such property group ${identifier}`));
|
|
59
|
+
}
|
|
60
|
+
propertyShape(identifier) {
|
|
61
|
+
const propertyShape = this.propertyShapesByIdentifier.get(identifier);
|
|
62
|
+
return propertyShape
|
|
63
|
+
? Either.of(propertyShape)
|
|
64
|
+
: Left(new Error(`no such property shape ${identifier}`));
|
|
65
|
+
}
|
|
66
|
+
shape(identifier) {
|
|
67
|
+
return this.nodeShape(identifier)
|
|
68
|
+
.alt(this.propertyShape(identifier))
|
|
69
|
+
.mapLeft(() => new Error(`no such shape ${identifier}`));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Convert the shapes graph to a dataset.
|
|
73
|
+
*/
|
|
74
|
+
toDataset() {
|
|
75
|
+
const dataset = datasetFactory.dataset();
|
|
76
|
+
const resourceSet = new ResourceSet({ dataFactory, dataset });
|
|
77
|
+
for (const nodeShape of this.nodeShapes) {
|
|
78
|
+
this.typeFunctions.NodeShape.toRdfResource(nodeShape, { resourceSet });
|
|
79
|
+
}
|
|
80
|
+
for (const ontology of this.ontologies) {
|
|
81
|
+
this.typeFunctions.Ontology.toRdfResource(ontology, { resourceSet });
|
|
82
|
+
}
|
|
83
|
+
for (const propertyGroup of this.propertyGroups) {
|
|
84
|
+
this.typeFunctions.PropertyGroup.toRdfResource(propertyGroup, {
|
|
85
|
+
resourceSet,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
for (const propertyShape of this.propertyShapes) {
|
|
89
|
+
this.typeFunctions.PropertyShape.toRdfResource(propertyShape, {
|
|
90
|
+
resourceSet,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return dataset;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Convert the shapes graph to an RDF string.
|
|
97
|
+
*
|
|
98
|
+
* If the format isn't specified, defaults to N-Triples.
|
|
99
|
+
*/
|
|
100
|
+
toString(options) {
|
|
101
|
+
const format = options?.format ?? "application/n-triples";
|
|
102
|
+
const lines = [];
|
|
103
|
+
switch (format) {
|
|
104
|
+
case "application/n-quads": {
|
|
105
|
+
for (const quad of this.toDataset()) {
|
|
106
|
+
const graphString = quad.graph.termType === "DefaultGraph"
|
|
107
|
+
? ""
|
|
108
|
+
: ` ${NTriplesTerm.stringify(quad.graph)}`;
|
|
109
|
+
lines.push(`${NTriplesTerm.stringify(quad.subject)} ${NTriplesTerm.stringify(quad.predicate)} ${NTriplesTerm.stringify(quad.object)}${graphString} .\n`);
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case "application/n-triples":
|
|
114
|
+
{
|
|
115
|
+
for (const quad of this.toDataset()) {
|
|
116
|
+
lines.push(`${NTriplesTerm.stringify(quad.subject)} ${NTriplesTerm.stringify(quad.predicate)} ${NTriplesTerm.stringify(quad.object)} .\n`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
return lines.join("");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
(function (AbstractShapesGraph) {
|
|
125
|
+
class AbstractBuilder {
|
|
126
|
+
nodeShapesByIdentifier = new TermMap();
|
|
127
|
+
ontologiesByIdentifier = new TermMap();
|
|
128
|
+
propertyGroupsByIdentifier = new TermMap();
|
|
129
|
+
propertyShapesByIdentifier = new TermMap();
|
|
130
|
+
add(...objects) {
|
|
131
|
+
for (const object of objects) {
|
|
132
|
+
switch (object.$type) {
|
|
133
|
+
case "NodeShape":
|
|
134
|
+
this.nodeShapesByIdentifier.set(object.$identifier(), object);
|
|
135
|
+
break;
|
|
136
|
+
case "Ontology":
|
|
137
|
+
this.ontologiesByIdentifier.set(object.$identifier(), object);
|
|
138
|
+
break;
|
|
139
|
+
case "PropertyGroup":
|
|
140
|
+
this.propertyGroupsByIdentifier.set(object.$identifier(), object);
|
|
141
|
+
break;
|
|
142
|
+
case "PropertyShape":
|
|
143
|
+
this.propertyShapesByIdentifier.set(object.$identifier(), object);
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
parseDataset(dataset, options) {
|
|
150
|
+
function datasetHasMatch(subject, predicate, object, graph) {
|
|
151
|
+
for (const _ of dataset.match(subject, predicate, object, graph)) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
let curieDataset;
|
|
157
|
+
if (options?.prefixMap) {
|
|
158
|
+
const curieCache = new Map();
|
|
159
|
+
curieDataset = datasetFactory.dataset();
|
|
160
|
+
const curieFactory = new CurieFactory({
|
|
161
|
+
prefixMap: options.prefixMap,
|
|
162
|
+
});
|
|
163
|
+
const termToCurie = (term) => {
|
|
164
|
+
if (term.termType !== "NamedNode") {
|
|
165
|
+
return term;
|
|
166
|
+
}
|
|
167
|
+
const cachedCurie = curieCache.get(term.value);
|
|
168
|
+
if (cachedCurie) {
|
|
169
|
+
return cachedCurie;
|
|
170
|
+
}
|
|
171
|
+
const curie = curieFactory.create(term).extract() ?? term;
|
|
172
|
+
curieCache.set(term.value, curie);
|
|
173
|
+
return curie;
|
|
174
|
+
};
|
|
175
|
+
for (const quad of dataset) {
|
|
176
|
+
const curieObject = termToCurie(quad.object);
|
|
177
|
+
const curieSubject = termToCurie(quad.subject);
|
|
178
|
+
if (!Object.is(curieObject, quad.object) ||
|
|
179
|
+
!Object.is(curieSubject, quad.subject)) {
|
|
180
|
+
curieDataset.add(dataFactory.quad(curieSubject, quad.predicate, curieObject, quad.graph));
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
curieDataset.add(quad);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
curieDataset = dataset;
|
|
189
|
+
}
|
|
190
|
+
const curieResourceSet = new ResourceSet({
|
|
191
|
+
dataFactory,
|
|
192
|
+
dataset: curieDataset,
|
|
193
|
+
});
|
|
194
|
+
return Either.encase(() => {
|
|
195
|
+
function readGraph() {
|
|
196
|
+
const graphs = new TermSet();
|
|
197
|
+
for (const quad of dataset) {
|
|
198
|
+
graphs.add(quad.graph);
|
|
199
|
+
}
|
|
200
|
+
if (graphs.size !== 1) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
const graph = [...graphs.values()][0];
|
|
204
|
+
switch (graph.termType) {
|
|
205
|
+
case "BlankNode":
|
|
206
|
+
case "DefaultGraph":
|
|
207
|
+
case "NamedNode":
|
|
208
|
+
return graph;
|
|
209
|
+
default:
|
|
210
|
+
throw new RangeError(`expected NamedNode or default graph, actual ${graph.termType}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const graph = readGraph();
|
|
214
|
+
// Read ontologies
|
|
215
|
+
for (const ontologyResource of curieResourceSet.instancesOf(owl.Ontology, {
|
|
216
|
+
graph,
|
|
217
|
+
})) {
|
|
218
|
+
if (this.ontologiesByIdentifier.has(ontologyResource.identifier)) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
this.typeFunctions.Ontology.fromRdfResource(ontologyResource, {
|
|
222
|
+
ignoreRdfType: true,
|
|
223
|
+
}).ifRight((ontology) => this.add(ontology));
|
|
224
|
+
}
|
|
225
|
+
// Read property groups
|
|
226
|
+
for (const propertyGroupResource of curieResourceSet.instancesOf(sh.PropertyGroup, { graph })) {
|
|
227
|
+
if (propertyGroupResource.identifier.termType !== "NamedNode") {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (this.propertyGroupsByIdentifier.has(propertyGroupResource.identifier)) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
this.typeFunctions.PropertyGroup.fromRdfResource(curieResourceSet.resource(propertyGroupResource.identifier), { ignoreRdfType: true }).ifRight((propertyGroup) => this.add(propertyGroup));
|
|
234
|
+
}
|
|
235
|
+
// Read shapes
|
|
236
|
+
// Collect the shape identifiers in sets
|
|
237
|
+
const shapeNodeSet = new TermSet();
|
|
238
|
+
// Utility function for adding to the shapeNodeSet
|
|
239
|
+
function addShapeNode(shapeNode) {
|
|
240
|
+
switch (shapeNode.termType) {
|
|
241
|
+
case "BlankNode":
|
|
242
|
+
case "NamedNode":
|
|
243
|
+
shapeNodeSet.add(shapeNode);
|
|
244
|
+
return true;
|
|
245
|
+
default:
|
|
246
|
+
throw new RangeError(`unexpected shape node identifier term type: ${shapeNode.termType}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Test each shape condition
|
|
250
|
+
// https://www.w3.org/TR/shacl/#shapes
|
|
251
|
+
// Subject is a SHACL instance of sh:NodeShape or sh:PropertyShape
|
|
252
|
+
for (const rdfType of [sh.NodeShape, sh.PropertyShape]) {
|
|
253
|
+
for (const resource of curieResourceSet.instancesOf(rdfType, {
|
|
254
|
+
graph,
|
|
255
|
+
})) {
|
|
256
|
+
addShapeNode(resource.identifier);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Subject of a triple with sh:targetClass, sh:targetNode, sh:targetObjectsOf, or sh:targetSubjectsOf predicate
|
|
260
|
+
for (const predicate of [
|
|
261
|
+
sh.targetClass,
|
|
262
|
+
sh.targetNode,
|
|
263
|
+
sh.targetObjectsOf,
|
|
264
|
+
sh.targetSubjectsOf,
|
|
265
|
+
]) {
|
|
266
|
+
for (const quad of dataset.match(null, predicate, null, graph)) {
|
|
267
|
+
addShapeNode(quad.subject);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Subject of a triple that has a parameter as predicate
|
|
271
|
+
// https://www.w3.org/TR/shacl/#constraints
|
|
272
|
+
// https://www.w3.org/TR/shacl/#core-components
|
|
273
|
+
for (const predicate of [
|
|
274
|
+
sh.class,
|
|
275
|
+
sh.datatype,
|
|
276
|
+
sh.nodeKind,
|
|
277
|
+
sh.minCount,
|
|
278
|
+
sh.maxCount,
|
|
279
|
+
sh.minExclusive,
|
|
280
|
+
sh.minInclusive,
|
|
281
|
+
sh.maxExclusive,
|
|
282
|
+
sh.maxInclusive,
|
|
283
|
+
sh.minLength,
|
|
284
|
+
sh.maxLength,
|
|
285
|
+
sh.pattern,
|
|
286
|
+
sh.languageIn,
|
|
287
|
+
sh.uniqueLang,
|
|
288
|
+
sh.equals,
|
|
289
|
+
sh.disjoint,
|
|
290
|
+
sh.lessThan,
|
|
291
|
+
sh.lessThanOrEquals,
|
|
292
|
+
sh.not,
|
|
293
|
+
sh.and,
|
|
294
|
+
sh.or,
|
|
295
|
+
sh.xone,
|
|
296
|
+
sh.node,
|
|
297
|
+
sh.property,
|
|
298
|
+
sh.qualifiedValueShape,
|
|
299
|
+
sh.qualifiedMinCount,
|
|
300
|
+
sh.qualifiedMaxCount,
|
|
301
|
+
sh.closed,
|
|
302
|
+
sh.ignoredProperties,
|
|
303
|
+
sh.hasValue,
|
|
304
|
+
sh.in,
|
|
305
|
+
]) {
|
|
306
|
+
for (const quad of dataset.match(null, predicate, null, graph)) {
|
|
307
|
+
addShapeNode(quad.subject);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// Object of a shape-expecting, non-list-taking parameter such as sh:node
|
|
311
|
+
for (const predicate of [sh.node, sh.not, sh.property]) {
|
|
312
|
+
for (const quad of dataset.match(null, predicate, null, graph)) {
|
|
313
|
+
addShapeNode(quad.object);
|
|
314
|
+
if (!options?.ignoreUndefinedShapes &&
|
|
315
|
+
!datasetHasMatch(quad.object)) {
|
|
316
|
+
throw new Error(`undefined shape: ${quad.object}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
// Member of a SHACL list that is a value of a shape-expecting and list-taking parameter such as sh:or
|
|
321
|
+
for (const predicate of [sh.and, sh.or, sh.xone]) {
|
|
322
|
+
for (const quad of dataset.match(null, predicate, null, graph)) {
|
|
323
|
+
switch (quad.object.termType) {
|
|
324
|
+
case "BlankNode":
|
|
325
|
+
case "NamedNode":
|
|
326
|
+
break;
|
|
327
|
+
default:
|
|
328
|
+
throw new RangeError(`expected list term to be a blank or named node, not ${quad.object.termType}`);
|
|
329
|
+
}
|
|
330
|
+
for (const value of curieResourceSet
|
|
331
|
+
.resource(quad.object)
|
|
332
|
+
.toList()
|
|
333
|
+
.unsafeCoerce()) {
|
|
334
|
+
const identifier = value.toIdentifier().unsafeCoerce();
|
|
335
|
+
addShapeNode(identifier);
|
|
336
|
+
if (!options?.ignoreUndefinedShapes &&
|
|
337
|
+
!datasetHasMatch(identifier)) {
|
|
338
|
+
throw new Error(`undefined shape: ${identifier}`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// Separate shapes into node and property shapes.
|
|
344
|
+
for (const shapeNode of shapeNodeSet) {
|
|
345
|
+
if (dataset.match(shapeNode, sh.path, null, graph).size > 0) {
|
|
346
|
+
// A property shape is a shape in the shapes graph that is the subject of a triple that has sh:path as its predicate. A shape has at most one value for sh:path. Each value of sh:path in a shape must be a well-formed SHACL property path. It is recommended, but not required, for a property shape to be declared as a SHACL instance of sh:PropertyShape. SHACL instances of sh:PropertyShape have one value for the property sh:path.
|
|
347
|
+
this.add(this.typeFunctions.PropertyShape.fromRdfResource(curieResourceSet.resource(shapeNode), {
|
|
348
|
+
ignoreRdfType: true,
|
|
349
|
+
}).unsafeCoerce());
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
// A node shape is a shape in the shapes graph that is not the subject of a triple with sh:path as its predicate. It is recommended, but not required, for a node shape to be declared as a SHACL instance of sh:NodeShape. SHACL instances of sh:NodeShape cannot have a value for the property sh:path.
|
|
353
|
+
this.add(this.typeFunctions.NodeShape.fromRdfResource(curieResourceSet.resource(shapeNode), {
|
|
354
|
+
ignoreRdfType: true,
|
|
355
|
+
}).unsafeCoerce());
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return this;
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
AbstractShapesGraph.AbstractBuilder = AbstractBuilder;
|
|
363
|
+
})(AbstractShapesGraph || (AbstractShapesGraph = {}));
|
|
364
|
+
//# sourceMappingURL=AbstractShapesGraph.js.map
|
package/dist/Curie.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BlankNode, NamedNode } from "@rdfjs/types";
|
|
2
|
+
/**
|
|
3
|
+
* A Compact URI (https://www.w3.org/TR/curie)
|
|
4
|
+
*/
|
|
5
|
+
export declare class Curie implements NamedNode {
|
|
6
|
+
#private;
|
|
7
|
+
readonly prefix: string;
|
|
8
|
+
readonly reference: string;
|
|
9
|
+
readonly termType = "NamedNode";
|
|
10
|
+
readonly value: string;
|
|
11
|
+
constructor({ hasUniqueReference, prefix, reference, value, }: {
|
|
12
|
+
hasUniqueReference?: () => boolean;
|
|
13
|
+
prefix: string;
|
|
14
|
+
reference: string;
|
|
15
|
+
value: string;
|
|
16
|
+
});
|
|
17
|
+
equals(other: BlankNode | NamedNode): boolean;
|
|
18
|
+
get hasUniqueReference(): boolean;
|
|
19
|
+
toString(): string;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=Curie.d.ts.map
|
package/dist/Curie.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Compact URI (https://www.w3.org/TR/curie)
|
|
3
|
+
*/
|
|
4
|
+
export class Curie {
|
|
5
|
+
prefix;
|
|
6
|
+
#hasUniqueReference;
|
|
7
|
+
reference;
|
|
8
|
+
termType = "NamedNode";
|
|
9
|
+
value;
|
|
10
|
+
constructor({ hasUniqueReference, prefix, reference, value, }) {
|
|
11
|
+
this.#hasUniqueReference = hasUniqueReference ?? (() => false);
|
|
12
|
+
this.prefix = prefix;
|
|
13
|
+
this.reference = reference;
|
|
14
|
+
this.value = value;
|
|
15
|
+
}
|
|
16
|
+
equals(other) {
|
|
17
|
+
if (other.termType === "BlankNode") {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return this.value === other.value; // Allow a Curie to equal a NamedNode
|
|
21
|
+
}
|
|
22
|
+
get hasUniqueReference() {
|
|
23
|
+
return this.#hasUniqueReference();
|
|
24
|
+
}
|
|
25
|
+
toString() {
|
|
26
|
+
return `${this.prefix}:${this.reference}`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=Curie.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type PrefixMap from "@rdfjs/prefix-map/PrefixMap.js";
|
|
2
|
+
import type { NamedNode } from "@rdfjs/types";
|
|
3
|
+
import { Maybe } from "purify-ts";
|
|
4
|
+
import { Curie } from "./Curie.js";
|
|
5
|
+
/**
|
|
6
|
+
* Factory for Compact URIs (CURIEs). Tracks whether the reference part of the CURIE is unique.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CurieFactory {
|
|
9
|
+
private readonly prefixMap;
|
|
10
|
+
private readonly referenceCounts;
|
|
11
|
+
constructor({ prefixMap }: {
|
|
12
|
+
prefixMap: PrefixMap;
|
|
13
|
+
});
|
|
14
|
+
create(namedNode: NamedNode): Maybe<Curie>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=CurieFactory.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Maybe } from "purify-ts";
|
|
2
|
+
import { invariant } from "ts-invariant";
|
|
3
|
+
import { Curie } from "./Curie.js";
|
|
4
|
+
/**
|
|
5
|
+
* Factory for Compact URIs (CURIEs). Tracks whether the reference part of the CURIE is unique.
|
|
6
|
+
*/
|
|
7
|
+
export class CurieFactory {
|
|
8
|
+
prefixMap;
|
|
9
|
+
referenceCounts = {};
|
|
10
|
+
constructor({ prefixMap }) {
|
|
11
|
+
this.prefixMap = prefixMap;
|
|
12
|
+
}
|
|
13
|
+
create(namedNode) {
|
|
14
|
+
return Maybe.fromNullable(this.prefixMap.shrink(namedNode)?.value).map((value) => {
|
|
15
|
+
const split = value.split(":", 2);
|
|
16
|
+
invariant(split.length === 2);
|
|
17
|
+
const prefix = split[0];
|
|
18
|
+
const reference = split[1];
|
|
19
|
+
if (this.referenceCounts[reference] === undefined) {
|
|
20
|
+
this.referenceCounts[reference] = {};
|
|
21
|
+
}
|
|
22
|
+
if (this.referenceCounts[reference][prefix] === undefined) {
|
|
23
|
+
this.referenceCounts[reference][prefix] = 1;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.referenceCounts[reference][prefix] += 1;
|
|
27
|
+
}
|
|
28
|
+
return new Curie({
|
|
29
|
+
hasUniqueReference: () => {
|
|
30
|
+
const referenceCounts = this.referenceCounts[reference];
|
|
31
|
+
if (Object.entries(referenceCounts).length === 1) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
// logger.debug(
|
|
35
|
+
// `duplicate local part ${reference} in ${JSON.stringify(referenceCounts)}`,
|
|
36
|
+
// );
|
|
37
|
+
return false;
|
|
38
|
+
},
|
|
39
|
+
prefix: split[0],
|
|
40
|
+
reference: split[1],
|
|
41
|
+
value: namedNode.value,
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=CurieFactory.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { NamedNode } from "@rdfjs/types";
|
|
2
|
+
/**
|
|
3
|
+
* TypeScript enum corresponding to sh:NodeKind, for simpler manipulation.
|
|
4
|
+
*/
|
|
5
|
+
export type NodeKind = "BlankNode" | "IRI" | "Literal";
|
|
6
|
+
export declare namespace NodeKind {
|
|
7
|
+
function fromIri(iri: NamedNode<"http://www.w3.org/ns/shacl#BlankNode" | "http://www.w3.org/ns/shacl#BlankNodeOrIRI" | "http://www.w3.org/ns/shacl#BlankNodeOrLiteral" | "http://www.w3.org/ns/shacl#IRI" | "http://www.w3.org/ns/shacl#IRIOrLiteral" | "http://www.w3.org/ns/shacl#Literal">): ReadonlySet<NodeKind>;
|
|
8
|
+
function fromTermType(termType: "BlankNode" | "Literal" | "NamedNode"): NodeKind;
|
|
9
|
+
function toTermType(nodeKind: NodeKind): "BlankNode" | "Literal" | "NamedNode";
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=NodeKind.d.ts.map
|
package/dist/NodeKind.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export var NodeKind;
|
|
2
|
+
(function (NodeKind) {
|
|
3
|
+
function fromIri(iri) {
|
|
4
|
+
const nodeKinds = new Set();
|
|
5
|
+
switch (iri.value) {
|
|
6
|
+
case "http://www.w3.org/ns/shacl#BlankNode":
|
|
7
|
+
nodeKinds.add("BlankNode");
|
|
8
|
+
break;
|
|
9
|
+
case "http://www.w3.org/ns/shacl#BlankNodeOrIRI":
|
|
10
|
+
nodeKinds.add("BlankNode");
|
|
11
|
+
nodeKinds.add("IRI");
|
|
12
|
+
break;
|
|
13
|
+
case "http://www.w3.org/ns/shacl#BlankNodeOrLiteral":
|
|
14
|
+
nodeKinds.add("BlankNode");
|
|
15
|
+
nodeKinds.add("Literal");
|
|
16
|
+
break;
|
|
17
|
+
case "http://www.w3.org/ns/shacl#IRI":
|
|
18
|
+
nodeKinds.add("IRI");
|
|
19
|
+
break;
|
|
20
|
+
case "http://www.w3.org/ns/shacl#IRIOrLiteral":
|
|
21
|
+
nodeKinds.add("IRI");
|
|
22
|
+
nodeKinds.add("Literal");
|
|
23
|
+
break;
|
|
24
|
+
case "http://www.w3.org/ns/shacl#Literal":
|
|
25
|
+
nodeKinds.add("Literal");
|
|
26
|
+
break;
|
|
27
|
+
default:
|
|
28
|
+
iri.value;
|
|
29
|
+
throw new RangeError(iri.value);
|
|
30
|
+
}
|
|
31
|
+
return nodeKinds;
|
|
32
|
+
}
|
|
33
|
+
NodeKind.fromIri = fromIri;
|
|
34
|
+
function fromTermType(termType) {
|
|
35
|
+
return termType === "NamedNode" ? "IRI" : termType;
|
|
36
|
+
}
|
|
37
|
+
NodeKind.fromTermType = fromTermType;
|
|
38
|
+
function toTermType(nodeKind) {
|
|
39
|
+
return nodeKind === "IRI" ? "NamedNode" : nodeKind;
|
|
40
|
+
}
|
|
41
|
+
NodeKind.toTermType = toTermType;
|
|
42
|
+
})(NodeKind || (NodeKind = {}));
|
|
43
|
+
//# sourceMappingURL=NodeKind.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AbstractShapesGraph } from "./AbstractShapesGraph.js";
|
|
2
|
+
import * as generated from "./shacl-ast.shaclmate.js";
|
|
3
|
+
export declare class ShapesGraph extends AbstractShapesGraph<generated.NodeShape, generated.Ontology, generated.PropertyGroup, generated.PropertyShape> {
|
|
4
|
+
protected readonly typeFunctions: {
|
|
5
|
+
readonly NodeShape: typeof generated.NodeShape;
|
|
6
|
+
readonly Ontology: typeof generated.Ontology;
|
|
7
|
+
readonly PropertyGroup: typeof generated.PropertyGroup;
|
|
8
|
+
readonly PropertyShape: typeof generated.PropertyShape;
|
|
9
|
+
};
|
|
10
|
+
static builder(): ShapesGraph.Builder;
|
|
11
|
+
}
|
|
12
|
+
export declare namespace ShapesGraph {
|
|
13
|
+
class Builder extends AbstractShapesGraph.AbstractBuilder<generated.NodeShape, generated.Ontology, generated.PropertyGroup, generated.PropertyShape> {
|
|
14
|
+
protected readonly typeFunctions: {
|
|
15
|
+
readonly NodeShape: typeof generated.NodeShape;
|
|
16
|
+
readonly Ontology: typeof generated.Ontology;
|
|
17
|
+
readonly PropertyGroup: typeof generated.PropertyGroup;
|
|
18
|
+
readonly PropertyShape: typeof generated.PropertyShape;
|
|
19
|
+
};
|
|
20
|
+
build(): ShapesGraph;
|
|
21
|
+
nodeShape(parameters?: Parameters<typeof generated.NodeShape.createUnsafe>[0]): generated.NodeShape;
|
|
22
|
+
ontology(parameters?: Parameters<typeof generated.Ontology.createUnsafe>[0]): generated.Ontology;
|
|
23
|
+
propertyGroup(parameters?: Parameters<typeof generated.PropertyGroup.create>[0]): generated.PropertyGroup;
|
|
24
|
+
propertyShape(parameters: Parameters<typeof generated.PropertyShape.createUnsafe>[0]): generated.PropertyShape;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=ShapesGraph.d.ts.map
|