@_linked/core 0.0.1 → 1.0.0-next.20260216062729
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 +71 -0
- package/LICENSE +1 -1
- package/README.md +147 -92
- package/lib/cjs/queries/SelectQuery.d.ts +5 -0
- package/lib/cjs/queries/SelectQuery.js +14 -0
- package/lib/cjs/queries/SelectQuery.js.map +1 -1
- package/lib/cjs/shapes/SHACL.d.ts +1 -0
- package/lib/cjs/shapes/SHACL.js +82 -2
- package/lib/cjs/shapes/SHACL.js.map +1 -1
- package/lib/cjs/shapes/Shape.d.ts +13 -1
- package/lib/cjs/shapes/Shape.js +6 -0
- package/lib/cjs/shapes/Shape.js.map +1 -1
- package/lib/cjs/test-helpers/query-fixtures.d.ts +583 -0
- package/lib/cjs/test-helpers/query-fixtures.js +39 -1
- package/lib/cjs/test-helpers/query-fixtures.js.map +1 -1
- package/lib/esm/queries/SelectQuery.d.ts +5 -0
- package/lib/esm/queries/SelectQuery.js +14 -0
- package/lib/esm/queries/SelectQuery.js.map +1 -1
- package/lib/esm/shapes/SHACL.d.ts +1 -0
- package/lib/esm/shapes/SHACL.js +82 -2
- package/lib/esm/shapes/SHACL.js.map +1 -1
- package/lib/esm/shapes/Shape.d.ts +13 -1
- package/lib/esm/shapes/Shape.js +6 -0
- package/lib/esm/shapes/Shape.js.map +1 -1
- package/lib/esm/test-helpers/query-fixtures.d.ts +583 -0
- package/lib/esm/test-helpers/query-fixtures.js +38 -0
- package/lib/esm/test-helpers/query-fixtures.js.map +1 -1
- package/package.json +17 -1
- package/.context/notes.md +0 -0
- package/.context/todos.md +0 -0
- package/AGENTS.md +0 -59
- package/docs/001-core-extraction.md +0 -305
- package/jest.config.js +0 -25
- package/scripts/dual-package.js +0 -25
- package/src/collections/CoreMap.ts +0 -127
- package/src/collections/CoreSet.ts +0 -171
- package/src/collections/ShapeSet.ts +0 -18
- package/src/index.ts +0 -88
- package/src/interfaces/ICoreIterable.ts +0 -35
- package/src/interfaces/IFileStore.ts +0 -28
- package/src/interfaces/IQuadStore.ts +0 -16
- package/src/interfaces/IQueryParser.ts +0 -51
- package/src/ontologies/lincd.ts +0 -25
- package/src/ontologies/npm.ts +0 -15
- package/src/ontologies/owl.ts +0 -26
- package/src/ontologies/rdf.ts +0 -32
- package/src/ontologies/rdfs.ts +0 -38
- package/src/ontologies/shacl.ts +0 -136
- package/src/ontologies/xsd.ts +0 -47
- package/src/package.ts +0 -11
- package/src/queries/CreateQuery.ts +0 -41
- package/src/queries/DeleteQuery.ts +0 -54
- package/src/queries/MutationQuery.ts +0 -287
- package/src/queries/QueryContext.ts +0 -41
- package/src/queries/QueryFactory.ts +0 -275
- package/src/queries/QueryParser.ts +0 -79
- package/src/queries/SelectQuery.ts +0 -2101
- package/src/queries/UpdateQuery.ts +0 -47
- package/src/shapes/List.ts +0 -52
- package/src/shapes/SHACL.ts +0 -653
- package/src/shapes/Shape.ts +0 -282
- package/src/test-helpers/query-fixtures.ts +0 -313
- package/src/tests/core-utils.test.ts +0 -286
- package/src/tests/metadata.test.ts +0 -65
- package/src/tests/query.test.ts +0 -599
- package/src/tests/query.types.test.ts +0 -606
- package/src/tests/store-routing.test.ts +0 -133
- package/src/utils/LinkedErrorLogging.ts +0 -25
- package/src/utils/LinkedFileStorage.ts +0 -75
- package/src/utils/LinkedStorage.ts +0 -120
- package/src/utils/NameSpace.ts +0 -5
- package/src/utils/NodeReference.ts +0 -16
- package/src/utils/Package.ts +0 -681
- package/src/utils/Prefix.ts +0 -108
- package/src/utils/ShapeClass.ts +0 -335
- package/src/utils/Types.ts +0 -19
- package/src/utils/URI.ts +0 -40
- package/src/utils/cached.ts +0 -53
- package/tsconfig-cjs.json +0 -8
- package/tsconfig-esm.json +0 -9
- package/tsconfig.json +0 -29
package/src/shapes/SHACL.ts
DELETED
|
@@ -1,653 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
-
*/
|
|
6
|
-
import {NodeReferenceValue} from '../utils/NodeReference.js';
|
|
7
|
-
import {Shape} from './Shape.js';
|
|
8
|
-
import {shacl} from '../ontologies/shacl.js';
|
|
9
|
-
import {URI} from '../utils/URI.js';
|
|
10
|
-
import {toNodeReference} from '../utils/NodeReference.js';
|
|
11
|
-
import {QResult} from '../queries/SelectQuery.js';
|
|
12
|
-
import {getShapeClass} from '../utils/ShapeClass.js';
|
|
13
|
-
|
|
14
|
-
export const LINCD_DATA_ROOT: string = 'https://data.lincd.org/';
|
|
15
|
-
|
|
16
|
-
type NodeKindConfig = NodeReferenceValue | NodeReferenceValue[];
|
|
17
|
-
|
|
18
|
-
export type PropertyPathInput = NodeReferenceValue;
|
|
19
|
-
export type PropertyPathInputList = PropertyPathInput | PropertyPathInput[];
|
|
20
|
-
|
|
21
|
-
const toPlainNodeRef = (
|
|
22
|
-
value: NodeReferenceValue | {id: string} | string,
|
|
23
|
-
): NodeReferenceValue => {
|
|
24
|
-
if (typeof value === 'string') {
|
|
25
|
-
return {id: value};
|
|
26
|
-
}
|
|
27
|
-
if (value && typeof value === 'object' && 'id' in value) {
|
|
28
|
-
return {id: (value as NodeReferenceValue).id};
|
|
29
|
-
}
|
|
30
|
-
return toNodeReference(value as NodeReferenceValue);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const normalizePathInput = (
|
|
34
|
-
value: PropertyPathInputList,
|
|
35
|
-
): PropertyPathInputList => {
|
|
36
|
-
if (Array.isArray(value)) {
|
|
37
|
-
return value.map((entry) => toPlainNodeRef(entry));
|
|
38
|
-
}
|
|
39
|
-
return toPlainNodeRef(value);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const normalizeNodeKind = (
|
|
43
|
-
nodeKind?: NodeKindConfig,
|
|
44
|
-
defaultNodeKind?: NodeReferenceValue,
|
|
45
|
-
): NodeReferenceValue | undefined => {
|
|
46
|
-
if (!nodeKind) {
|
|
47
|
-
return defaultNodeKind;
|
|
48
|
-
}
|
|
49
|
-
if (Array.isArray(nodeKind)) {
|
|
50
|
-
const ids = nodeKind.map((entry) => entry?.id);
|
|
51
|
-
const includesBlank = ids.includes(shacl.BlankNode.id);
|
|
52
|
-
const includesNamed = ids.includes(shacl.IRI.id);
|
|
53
|
-
const includesLiteral = ids.includes(shacl.Literal.id);
|
|
54
|
-
if (includesBlank && includesNamed) {
|
|
55
|
-
return shacl.BlankNodeOrIRI;
|
|
56
|
-
}
|
|
57
|
-
if (includesLiteral && includesNamed) {
|
|
58
|
-
return shacl.IRIOrLiteral;
|
|
59
|
-
}
|
|
60
|
-
if (includesLiteral && includesBlank) {
|
|
61
|
-
return shacl.BlankNodeOrLiteral;
|
|
62
|
-
}
|
|
63
|
-
return nodeKind[0];
|
|
64
|
-
}
|
|
65
|
-
return nodeKind;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export interface NodeShapeConfig {
|
|
69
|
-
/**
|
|
70
|
-
* Set to true to close the shape. This means any target node of this shape
|
|
71
|
-
* that has properties outside the defined properties of this shape is invalid.
|
|
72
|
-
*/
|
|
73
|
-
closed?: boolean;
|
|
74
|
-
/**
|
|
75
|
-
* Optional list of properties that are also permitted in addition to those explicitly listed by this shape.
|
|
76
|
-
*/
|
|
77
|
-
ignoredProperties?: NodeReferenceValue[];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface LiteralPropertyShapeConfig extends PropertyShapeConfig {
|
|
81
|
-
nodeKind?: NodeReferenceValue;
|
|
82
|
-
/**
|
|
83
|
-
* Values of the configured property must be less than the values of this 'lessThan' property
|
|
84
|
-
*/
|
|
85
|
-
lessThan?: NodeReferenceValue | string;
|
|
86
|
-
/**
|
|
87
|
-
* Values of the configured property must be less than or equal the values of this 'lessThan' property
|
|
88
|
-
*/
|
|
89
|
-
lessThanOrEquals?: NodeReferenceValue | string;
|
|
90
|
-
/**
|
|
91
|
-
* All values of this property must be higher than this number
|
|
92
|
-
*/
|
|
93
|
-
minExclusive?: number | string;
|
|
94
|
-
/**
|
|
95
|
-
* All values of this property must be higher than or equal this number
|
|
96
|
-
*/
|
|
97
|
-
minInclusive?: number;
|
|
98
|
-
/**
|
|
99
|
-
* All values of this property must be lower than this number
|
|
100
|
-
*/
|
|
101
|
-
maxExclusive?: number;
|
|
102
|
-
/**
|
|
103
|
-
* All values of this property must be lower than or equal this number
|
|
104
|
-
*/
|
|
105
|
-
maxInclusive?: number;
|
|
106
|
-
/**
|
|
107
|
-
* All literal values of this property must at least be this long
|
|
108
|
-
*/
|
|
109
|
-
minLength?: number;
|
|
110
|
-
/**
|
|
111
|
-
* All literal values of this property must at most be this long
|
|
112
|
-
*/
|
|
113
|
-
maxLength?: number;
|
|
114
|
-
/**
|
|
115
|
-
* All literal values of this property must match this regular expression
|
|
116
|
-
*/
|
|
117
|
-
pattern?: RegExp;
|
|
118
|
-
/**
|
|
119
|
-
* All literal values of this property must have one of these languages as their language tag
|
|
120
|
-
*/
|
|
121
|
-
languageIn?: string[];
|
|
122
|
-
/**
|
|
123
|
-
* No pair of values may use the same language tag.
|
|
124
|
-
*/
|
|
125
|
-
uniqueLang?: boolean;
|
|
126
|
-
/**
|
|
127
|
-
* Each literal value of this property must use this datatype
|
|
128
|
-
*/
|
|
129
|
-
datatype?: NodeReferenceValue | string;
|
|
130
|
-
/**
|
|
131
|
-
* Each value of the property must occur in this set
|
|
132
|
-
*/
|
|
133
|
-
in?: NodeReferenceValue[];
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export interface ObjectPropertyShapeConfig extends PropertyShapeConfig {
|
|
137
|
-
nodeKind?: NodeReferenceValue;
|
|
138
|
-
/**
|
|
139
|
-
* Each value of this property must have this class as its rdf:type
|
|
140
|
-
*/
|
|
141
|
-
class?: NodeReferenceValue | string;
|
|
142
|
-
/**
|
|
143
|
-
* The shape that values of this property path need to confirm to.
|
|
144
|
-
* You need to provide a class that extends Shape.
|
|
145
|
-
*/
|
|
146
|
-
shape?: typeof Shape | [string, string];
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export interface PropertyShapeConfig {
|
|
150
|
-
/**
|
|
151
|
-
* The property path of this property shape.
|
|
152
|
-
*/
|
|
153
|
-
path: PropertyPathInputList;
|
|
154
|
-
/**
|
|
155
|
-
* Indicates that this property must exist.
|
|
156
|
-
* Shorthand for minCount=1
|
|
157
|
-
*/
|
|
158
|
-
required?: boolean;
|
|
159
|
-
/**
|
|
160
|
-
* Each value must be of this node type.
|
|
161
|
-
*/
|
|
162
|
-
nodeKind?: NodeKindConfig;
|
|
163
|
-
/**
|
|
164
|
-
* Minimum number of values required
|
|
165
|
-
*/
|
|
166
|
-
minCount?: number;
|
|
167
|
-
/**
|
|
168
|
-
* Maximum number of values allowed
|
|
169
|
-
*/
|
|
170
|
-
maxCount?: number;
|
|
171
|
-
/**
|
|
172
|
-
* Values of the configured property must equal the values of this 'equals' property.
|
|
173
|
-
*/
|
|
174
|
-
equals?: NodeReferenceValue | string;
|
|
175
|
-
/**
|
|
176
|
-
* Values of the configured property must differ from the values of this 'disjoint' property
|
|
177
|
-
*/
|
|
178
|
-
disjoint?: NodeReferenceValue | string;
|
|
179
|
-
/**
|
|
180
|
-
* At least one value of this property must equal the given Node
|
|
181
|
-
*/
|
|
182
|
-
hasValue?: NodeReferenceValue | string;
|
|
183
|
-
name?: string;
|
|
184
|
-
description?: string;
|
|
185
|
-
order?: number;
|
|
186
|
-
group?: string;
|
|
187
|
-
/**
|
|
188
|
-
* should correlate to the given datatype or class
|
|
189
|
-
*/
|
|
190
|
-
defaultValue?: unknown;
|
|
191
|
-
/**
|
|
192
|
-
* Each value of the property must occur in this set
|
|
193
|
-
*/
|
|
194
|
-
in?: NodeReferenceValue[];
|
|
195
|
-
/**
|
|
196
|
-
* Values of the configured property path are sorted by the values of this property path.
|
|
197
|
-
*/
|
|
198
|
-
sortBy?: PropertyPathInputList;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export interface ParameterConfig {
|
|
202
|
-
optional?: number;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export class NodeShape extends Shape {
|
|
206
|
-
static targetClass = shacl.NodeShape;
|
|
207
|
-
private _label?: string;
|
|
208
|
-
description?: string;
|
|
209
|
-
targetClass?: NodeReferenceValue;
|
|
210
|
-
extends?: NodeReferenceValue;
|
|
211
|
-
private propertyShapes: PropertyShape[] = [];
|
|
212
|
-
|
|
213
|
-
constructor(node?: string | NodeReferenceValue) {
|
|
214
|
-
super(node);
|
|
215
|
-
if (this.id) {
|
|
216
|
-
this.nodeRef = {id: this.id};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
nodeRef?: NodeReferenceValue;
|
|
221
|
-
|
|
222
|
-
get label(): string {
|
|
223
|
-
return this._label;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
set label(value: string) {
|
|
227
|
-
this._label = value;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
get properties(): QResult<PropertyShape>[] {
|
|
231
|
-
return this.propertyShapes.map((propertyShape) => propertyShape.getResult());
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
addPropertyShape(propertyShape: PropertyShape) {
|
|
235
|
-
propertyShape.parentNodeShape = this;
|
|
236
|
-
this.propertyShapes.push(propertyShape);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
getPropertyShapes(includeSuperClasses: boolean = false): PropertyShape[] {
|
|
240
|
-
if (!includeSuperClasses) {
|
|
241
|
-
return [...this.propertyShapes];
|
|
242
|
-
}
|
|
243
|
-
const res: PropertyShape[] = [];
|
|
244
|
-
let shapeClass = getShapeClass(this.id);
|
|
245
|
-
if (!shapeClass) {
|
|
246
|
-
return [...this.propertyShapes];
|
|
247
|
-
}
|
|
248
|
-
while (shapeClass && (shapeClass as typeof Shape).shape) {
|
|
249
|
-
res.push(...(shapeClass as typeof Shape).shape.propertyShapes);
|
|
250
|
-
if (shapeClass === Shape) {
|
|
251
|
-
break;
|
|
252
|
-
}
|
|
253
|
-
shapeClass = Object.getPrototypeOf(shapeClass);
|
|
254
|
-
}
|
|
255
|
-
return res;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
getPropertyShape(
|
|
259
|
-
label: string,
|
|
260
|
-
checkSubShapes: boolean = true,
|
|
261
|
-
): PropertyShape {
|
|
262
|
-
let shapeClass = getShapeClass(this.id);
|
|
263
|
-
let res: PropertyShape;
|
|
264
|
-
if (!shapeClass) {
|
|
265
|
-
return this.propertyShapes.find((shape) => shape.label === label);
|
|
266
|
-
}
|
|
267
|
-
while (!res && shapeClass && (shapeClass as typeof Shape).shape) {
|
|
268
|
-
res = (shapeClass as typeof Shape).shape.propertyShapes.find(
|
|
269
|
-
(shape) => shape.label === label,
|
|
270
|
-
);
|
|
271
|
-
if (checkSubShapes) {
|
|
272
|
-
if (shapeClass === Shape) {
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
shapeClass = Object.getPrototypeOf(shapeClass);
|
|
276
|
-
} else {
|
|
277
|
-
break;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return res;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
validateNode(_node?: unknown): boolean {
|
|
284
|
-
return true;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
equals(other: NodeShape): boolean {
|
|
288
|
-
return !!other && this.id === other.id;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
export class PropertyShape extends Shape {
|
|
293
|
-
static targetClass = shacl.PropertyShape;
|
|
294
|
-
private _label?: string;
|
|
295
|
-
path: PropertyPathInputList;
|
|
296
|
-
nodeKind?: NodeReferenceValue;
|
|
297
|
-
datatype?: NodeReferenceValue;
|
|
298
|
-
minCount?: number;
|
|
299
|
-
maxCount?: number;
|
|
300
|
-
name?: string;
|
|
301
|
-
description?: string;
|
|
302
|
-
order?: number;
|
|
303
|
-
group?: string;
|
|
304
|
-
class?: NodeReferenceValue;
|
|
305
|
-
in?: NodeReferenceValue[];
|
|
306
|
-
equalsConstraint?: NodeReferenceValue;
|
|
307
|
-
disjoint?: NodeReferenceValue;
|
|
308
|
-
hasValueConstraint?: NodeReferenceValue;
|
|
309
|
-
defaultValue?: unknown;
|
|
310
|
-
sortBy?: PropertyPathInputList;
|
|
311
|
-
valueShape?: NodeReferenceValue;
|
|
312
|
-
parentNodeShape?: NodeShape;
|
|
313
|
-
|
|
314
|
-
constructor() {
|
|
315
|
-
super();
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
get label(): string {
|
|
319
|
-
return this._label;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
set label(value: string) {
|
|
323
|
-
this._label = value;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
getResult(): QResult<PropertyShape> {
|
|
327
|
-
const result: QResult<PropertyShape, Record<string, unknown>> = {
|
|
328
|
-
id: this.id,
|
|
329
|
-
label: this.label,
|
|
330
|
-
path: this.path,
|
|
331
|
-
};
|
|
332
|
-
if (this.nodeKind) {
|
|
333
|
-
result.nodeKind = this.nodeKind;
|
|
334
|
-
}
|
|
335
|
-
if (this.datatype) {
|
|
336
|
-
result.datatype = this.datatype;
|
|
337
|
-
}
|
|
338
|
-
if (typeof this.minCount === 'number') {
|
|
339
|
-
result.minCount = this.minCount;
|
|
340
|
-
}
|
|
341
|
-
if (typeof this.maxCount === 'number') {
|
|
342
|
-
result.maxCount = this.maxCount;
|
|
343
|
-
}
|
|
344
|
-
if (this.name) {
|
|
345
|
-
result.name = this.name;
|
|
346
|
-
}
|
|
347
|
-
if (this.description) {
|
|
348
|
-
result.description = this.description;
|
|
349
|
-
}
|
|
350
|
-
if (typeof this.order === 'number') {
|
|
351
|
-
result.order = this.order;
|
|
352
|
-
}
|
|
353
|
-
if (this.group) {
|
|
354
|
-
result.group = this.group;
|
|
355
|
-
}
|
|
356
|
-
if (this.class) {
|
|
357
|
-
result.class = this.class;
|
|
358
|
-
}
|
|
359
|
-
if (this.in) {
|
|
360
|
-
result.in = this.in;
|
|
361
|
-
}
|
|
362
|
-
if (this.equalsConstraint) {
|
|
363
|
-
result.equals = this.equalsConstraint;
|
|
364
|
-
}
|
|
365
|
-
if (this.disjoint) {
|
|
366
|
-
result.disjoint = this.disjoint;
|
|
367
|
-
}
|
|
368
|
-
if (this.hasValueConstraint) {
|
|
369
|
-
result.hasValue = this.hasValueConstraint;
|
|
370
|
-
}
|
|
371
|
-
if (this.defaultValue !== undefined) {
|
|
372
|
-
result.defaultValue = this.defaultValue;
|
|
373
|
-
}
|
|
374
|
-
if (this.sortBy) {
|
|
375
|
-
result.sortBy = this.sortBy;
|
|
376
|
-
}
|
|
377
|
-
if (this.valueShape) {
|
|
378
|
-
result.valueShape = this.valueShape;
|
|
379
|
-
}
|
|
380
|
-
return result as QResult<PropertyShape>;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
clone(): this {
|
|
384
|
-
const constructor = this.constructor as new () => this;
|
|
385
|
-
const clone = new constructor();
|
|
386
|
-
Object.assign(clone, this);
|
|
387
|
-
return clone;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
const connectValueShape = <
|
|
392
|
-
Config extends LiteralPropertyShapeConfig | ObjectPropertyShapeConfig,
|
|
393
|
-
>(
|
|
394
|
-
config: Config,
|
|
395
|
-
propertyKey: string,
|
|
396
|
-
property: PropertyShape,
|
|
397
|
-
) => {
|
|
398
|
-
if ((config as ObjectPropertyShapeConfig).shape) {
|
|
399
|
-
const shapeConfig = (config as ObjectPropertyShapeConfig).shape;
|
|
400
|
-
|
|
401
|
-
if (Array.isArray(shapeConfig)) {
|
|
402
|
-
const [packageName, shapeName] = shapeConfig;
|
|
403
|
-
const nodeShapeUri = getNodeShapeUri(packageName, shapeName);
|
|
404
|
-
property.valueShape = {id: nodeShapeUri};
|
|
405
|
-
} else {
|
|
406
|
-
const shapeClass = shapeConfig as typeof Shape;
|
|
407
|
-
if (shapeClass.shape) {
|
|
408
|
-
property.valueShape = {id: shapeClass.shape.id};
|
|
409
|
-
} else {
|
|
410
|
-
onShapeSetup(
|
|
411
|
-
shapeConfig,
|
|
412
|
-
(nodeShape: NodeShape) => {
|
|
413
|
-
property.valueShape = {id: nodeShape.id};
|
|
414
|
-
},
|
|
415
|
-
propertyKey,
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
export function registerPropertyShape(
|
|
423
|
-
shape: NodeShape,
|
|
424
|
-
propertyShape: PropertyShape,
|
|
425
|
-
) {
|
|
426
|
-
const existing = shape.getPropertyShape(propertyShape.label, false);
|
|
427
|
-
if (existing) {
|
|
428
|
-
Object.assign(existing, propertyShape);
|
|
429
|
-
return existing;
|
|
430
|
-
}
|
|
431
|
-
propertyShape.id = `${shape.id}/${propertyShape.label}`;
|
|
432
|
-
shape.addPropertyShape(propertyShape);
|
|
433
|
-
return propertyShape;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
export function createPropertyShape<
|
|
437
|
-
Config extends LiteralPropertyShapeConfig | ObjectPropertyShapeConfig,
|
|
438
|
-
>(
|
|
439
|
-
config: Config,
|
|
440
|
-
propertyKey: string,
|
|
441
|
-
defaultNodeKind: NodeReferenceValue = null,
|
|
442
|
-
shapeClass: typeof Shape | [string, string] = null,
|
|
443
|
-
) {
|
|
444
|
-
const propertyShape = new PropertyShape();
|
|
445
|
-
propertyShape.path = normalizePathInput(config.path);
|
|
446
|
-
propertyShape.label = propertyKey;
|
|
447
|
-
|
|
448
|
-
if (config.name) {
|
|
449
|
-
propertyShape.name = config.name;
|
|
450
|
-
}
|
|
451
|
-
if (config.description) {
|
|
452
|
-
propertyShape.description = config.description;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (config.required) {
|
|
456
|
-
propertyShape.minCount = 1;
|
|
457
|
-
} else if (config.minCount) {
|
|
458
|
-
propertyShape.minCount = config.minCount;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
if (config.maxCount) {
|
|
462
|
-
propertyShape.maxCount = config.maxCount;
|
|
463
|
-
}
|
|
464
|
-
if ((config as LiteralPropertyShapeConfig).datatype) {
|
|
465
|
-
propertyShape.datatype = toPlainNodeRef(
|
|
466
|
-
(config as LiteralPropertyShapeConfig).datatype,
|
|
467
|
-
);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
if ((config as ObjectPropertyShapeConfig).class) {
|
|
471
|
-
propertyShape.class = toPlainNodeRef(
|
|
472
|
-
(config as ObjectPropertyShapeConfig).class,
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
if (config.equals) {
|
|
477
|
-
propertyShape.equalsConstraint = toPlainNodeRef(config.equals);
|
|
478
|
-
}
|
|
479
|
-
if (config.disjoint) {
|
|
480
|
-
propertyShape.disjoint = toPlainNodeRef(config.disjoint);
|
|
481
|
-
}
|
|
482
|
-
if (config.hasValue) {
|
|
483
|
-
propertyShape.hasValueConstraint = toPlainNodeRef(config.hasValue);
|
|
484
|
-
}
|
|
485
|
-
if (config.defaultValue !== undefined) {
|
|
486
|
-
propertyShape.defaultValue = config.defaultValue;
|
|
487
|
-
}
|
|
488
|
-
if (config.in) {
|
|
489
|
-
propertyShape.in = config.in.map((entry) => toPlainNodeRef(entry));
|
|
490
|
-
}
|
|
491
|
-
if (config.sortBy) {
|
|
492
|
-
propertyShape.sortBy = normalizePathInput(config.sortBy);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
propertyShape.nodeKind = normalizeNodeKind(config.nodeKind, defaultNodeKind);
|
|
496
|
-
|
|
497
|
-
if (shapeClass) {
|
|
498
|
-
onShapeSetup(shapeClass, (shape: NodeShape) => {
|
|
499
|
-
connectValueShape(config, propertyKey, propertyShape);
|
|
500
|
-
registerPropertyShape(shape, propertyShape);
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
return propertyShape;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
export function onShapeSetup(
|
|
508
|
-
shapeClass: typeof Shape | [string, string],
|
|
509
|
-
callback: (shape: NodeShape) => void,
|
|
510
|
-
propertyName?: string,
|
|
511
|
-
waitForSuperShapes?: boolean,
|
|
512
|
-
) {
|
|
513
|
-
const cb = waitForSuperShapes
|
|
514
|
-
? (shape: NodeShape) => {
|
|
515
|
-
const superClass = Object.getPrototypeOf(shapeClass) as typeof Shape;
|
|
516
|
-
if (superClass.name === 'Shape') {
|
|
517
|
-
callback(shape);
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
520
|
-
if (superClass.name === '') {
|
|
521
|
-
console.error(
|
|
522
|
-
`Shape ${shape.label} does not extend base class lincd/shapes/Shape. Make sure it extends Shape.`,
|
|
523
|
-
);
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
onShapeSetup(
|
|
527
|
-
superClass,
|
|
528
|
-
() => {
|
|
529
|
-
callback(shape);
|
|
530
|
-
},
|
|
531
|
-
propertyName,
|
|
532
|
-
waitForSuperShapes,
|
|
533
|
-
);
|
|
534
|
-
}
|
|
535
|
-
: callback;
|
|
536
|
-
|
|
537
|
-
const safeCallback = (
|
|
538
|
-
targetShapeClass: typeof Shape,
|
|
539
|
-
innerCallback: (shape: NodeShape) => void,
|
|
540
|
-
) => {
|
|
541
|
-
if (targetShapeClass.hasOwnProperty('shape')) {
|
|
542
|
-
innerCallback((targetShapeClass as typeof Shape).shape);
|
|
543
|
-
} else {
|
|
544
|
-
if (!targetShapeClass['shapeCallbacks']) {
|
|
545
|
-
targetShapeClass['shapeCallbacks'] = [];
|
|
546
|
-
}
|
|
547
|
-
targetShapeClass['shapeCallbacks'].push(innerCallback);
|
|
548
|
-
}
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
if (Array.isArray(shapeClass)) {
|
|
552
|
-
const [packageName, shapeName] = shapeClass;
|
|
553
|
-
const nodeShapeId = getNodeShapeUri(packageName, shapeName);
|
|
554
|
-
if (typeof document !== 'undefined') {
|
|
555
|
-
window.addEventListener('load', () => {
|
|
556
|
-
shapeClass = getShapeClass(nodeShapeId);
|
|
557
|
-
if (!shapeClass) {
|
|
558
|
-
console.warn(
|
|
559
|
-
`Could not find value shape (${packageName}/${shapeName}) for accessor get ${propertyName}(). Likely because it is not bundled.`,
|
|
560
|
-
);
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
safeCallback(shapeClass, cb);
|
|
564
|
-
});
|
|
565
|
-
} else {
|
|
566
|
-
addNodeShapeCallback(nodeShapeId, cb);
|
|
567
|
-
}
|
|
568
|
-
} else {
|
|
569
|
-
safeCallback(shapeClass, cb);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
const _linkedProperty = <
|
|
574
|
-
Config extends ObjectPropertyShapeConfig | LiteralPropertyShapeConfig,
|
|
575
|
-
>(
|
|
576
|
-
config: Config,
|
|
577
|
-
defaultNodeKind: NodeReferenceValue = null,
|
|
578
|
-
) => {
|
|
579
|
-
return function (
|
|
580
|
-
target: any,
|
|
581
|
-
propertyKey: string,
|
|
582
|
-
_descriptor: PropertyDescriptor,
|
|
583
|
-
) {
|
|
584
|
-
createPropertyShape(config, propertyKey, defaultNodeKind, target.constructor);
|
|
585
|
-
};
|
|
586
|
-
};
|
|
587
|
-
|
|
588
|
-
export const literalProperty = (config: LiteralPropertyShapeConfig) => {
|
|
589
|
-
return _linkedProperty<LiteralPropertyShapeConfig>(config, shacl.Literal);
|
|
590
|
-
};
|
|
591
|
-
|
|
592
|
-
export const objectProperty = (config: ObjectPropertyShapeConfig) => {
|
|
593
|
-
return _linkedProperty<ObjectPropertyShapeConfig>(config, shacl.IRI);
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
export const linkedProperty = (
|
|
597
|
-
config: ObjectPropertyShapeConfig | LiteralPropertyShapeConfig,
|
|
598
|
-
) => {
|
|
599
|
-
return _linkedProperty(config);
|
|
600
|
-
};
|
|
601
|
-
|
|
602
|
-
export function disallowProperty(
|
|
603
|
-
target: any,
|
|
604
|
-
propertyKey: string,
|
|
605
|
-
_descriptor: PropertyDescriptor,
|
|
606
|
-
) {
|
|
607
|
-
onShapeSetup(
|
|
608
|
-
target.constructor,
|
|
609
|
-
(shape: NodeShape) => {
|
|
610
|
-
const superClass = Object.getPrototypeOf(target.constructor) as typeof Shape;
|
|
611
|
-
const superNodeShape = superClass.shape;
|
|
612
|
-
const superPropertyShape = superNodeShape.getPropertyShape(
|
|
613
|
-
propertyKey,
|
|
614
|
-
true,
|
|
615
|
-
);
|
|
616
|
-
if (!superPropertyShape) {
|
|
617
|
-
console.warn(
|
|
618
|
-
`Property ${propertyKey} not found in super class ${superClass.name} or any of its super classes. Does it have a property decorator? Cannot disallow property ${target.constructor.name}.${propertyKey}`,
|
|
619
|
-
);
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
const clonedPropertyShape = superPropertyShape.clone();
|
|
623
|
-
clonedPropertyShape.maxCount = 0;
|
|
624
|
-
registerPropertyShape(shape, clonedPropertyShape);
|
|
625
|
-
},
|
|
626
|
-
'',
|
|
627
|
-
true,
|
|
628
|
-
);
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
export function getNodeShapeUri(packageName: string, shapeName: string): string {
|
|
632
|
-
return `${LINCD_DATA_ROOT}module/${URI.sanitize(packageName)}/shape/${URI.sanitize(
|
|
633
|
-
shapeName,
|
|
634
|
-
)}`;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
const nodeShapeCallbacks = new Map<string, ((shape: NodeShape) => void)[]>();
|
|
638
|
-
export function getAndClearCallbacks(
|
|
639
|
-
nodeShapeId: string,
|
|
640
|
-
): ((shape: NodeShape) => void)[] {
|
|
641
|
-
const callbacks = nodeShapeCallbacks.get(nodeShapeId);
|
|
642
|
-
nodeShapeCallbacks.delete(nodeShapeId);
|
|
643
|
-
return callbacks;
|
|
644
|
-
}
|
|
645
|
-
export const addNodeShapeCallback = (
|
|
646
|
-
nodeShapeId: string,
|
|
647
|
-
callback: (shape: NodeShape) => void,
|
|
648
|
-
) => {
|
|
649
|
-
if (!nodeShapeCallbacks.has(nodeShapeId)) {
|
|
650
|
-
nodeShapeCallbacks.set(nodeShapeId, []);
|
|
651
|
-
}
|
|
652
|
-
nodeShapeCallbacks.get(nodeShapeId).push(callback);
|
|
653
|
-
};
|