@shaclmate/shacl-ast 2.0.13
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/NodeKind.d.ts +9 -0
- package/NodeKind.js +10 -0
- package/NodeShape.d.ts +17 -0
- package/NodeShape.js +30 -0
- package/PropertyGroup.d.ts +9 -0
- package/PropertyGroup.js +13 -0
- package/PropertyPath.d.ts +36 -0
- package/PropertyPath.js +91 -0
- package/PropertyShape.d.ts +21 -0
- package/PropertyShape.js +63 -0
- package/README.md +25 -0
- package/Shape.d.ts +47 -0
- package/Shape.js +171 -0
- package/ShapeParameters.d.ts +7 -0
- package/ShapeParameters.js +2 -0
- package/ShapesGraph.d.ts +26 -0
- package/ShapesGraph.js +201 -0
- package/index.d.ts +8 -0
- package/index.js +8 -0
- package/package.json +50 -0
package/NodeKind.d.ts
ADDED
package/NodeKind.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript enum corresponding to sh:NodeKind, for simpler manipulation.
|
|
3
|
+
*/
|
|
4
|
+
export var NodeKind;
|
|
5
|
+
(function (NodeKind) {
|
|
6
|
+
NodeKind[NodeKind["BLANK_NODE"] = 1] = "BLANK_NODE";
|
|
7
|
+
NodeKind[NodeKind["IRI"] = 2] = "IRI";
|
|
8
|
+
NodeKind[NodeKind["LITERAL"] = 3] = "LITERAL";
|
|
9
|
+
})(NodeKind || (NodeKind = {}));
|
|
10
|
+
//# sourceMappingURL=NodeKind.js.map
|
package/NodeShape.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Maybe } from "purify-ts";
|
|
2
|
+
import type { Resource } from "rdfjs-resource";
|
|
3
|
+
import type { PropertyShape } from "./PropertyShape.js";
|
|
4
|
+
import { Shape } from "./Shape.js";
|
|
5
|
+
import type { ShapesGraph } from "./ShapesGraph.js";
|
|
6
|
+
export declare class NodeShape extends Shape {
|
|
7
|
+
readonly constraints: NodeShape.Constraints;
|
|
8
|
+
constructor(resource: Resource, shapesGraph: ShapesGraph);
|
|
9
|
+
toString(): string;
|
|
10
|
+
}
|
|
11
|
+
export declare namespace NodeShape {
|
|
12
|
+
class Constraints extends Shape.Constraints {
|
|
13
|
+
get closed(): Maybe<boolean>;
|
|
14
|
+
get properties(): readonly PropertyShape[];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=NodeShape.d.ts.map
|
package/NodeShape.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { sh } from "@tpluscode/rdf-ns-builders";
|
|
2
|
+
import { Shape } from "./Shape.js";
|
|
3
|
+
export class NodeShape extends Shape {
|
|
4
|
+
constructor(resource, shapesGraph) {
|
|
5
|
+
super(resource);
|
|
6
|
+
this.constraints = new NodeShape.Constraints(resource, shapesGraph);
|
|
7
|
+
}
|
|
8
|
+
toString() {
|
|
9
|
+
return `NodeShape(node=${this.resource.identifier.value})`;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
(function (NodeShape) {
|
|
13
|
+
class Constraints extends Shape.Constraints {
|
|
14
|
+
get closed() {
|
|
15
|
+
return this.resource
|
|
16
|
+
.value(sh.closed)
|
|
17
|
+
.chain((value) => value.toBoolean())
|
|
18
|
+
.toMaybe();
|
|
19
|
+
}
|
|
20
|
+
get properties() {
|
|
21
|
+
return [...this.resource.values(sh.property)].flatMap((value) => value
|
|
22
|
+
.toIdentifier()
|
|
23
|
+
.toMaybe()
|
|
24
|
+
.chain((shapeNode) => this.shapesGraph.propertyShapeByNode(shapeNode))
|
|
25
|
+
.toList());
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
NodeShape.Constraints = Constraints;
|
|
29
|
+
})(NodeShape || (NodeShape = {}));
|
|
30
|
+
//# sourceMappingURL=NodeShape.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Literal } from "@rdfjs/types";
|
|
2
|
+
import type { Maybe } from "purify-ts";
|
|
3
|
+
import type { Resource } from "rdfjs-resource";
|
|
4
|
+
export declare class PropertyGroup {
|
|
5
|
+
private readonly resource;
|
|
6
|
+
constructor(resource: Resource);
|
|
7
|
+
get label(): Maybe<Literal>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=PropertyGroup.d.ts.map
|
package/PropertyGroup.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { rdfs } from "@tpluscode/rdf-ns-builders";
|
|
2
|
+
export class PropertyGroup {
|
|
3
|
+
constructor(resource) {
|
|
4
|
+
this.resource = resource;
|
|
5
|
+
}
|
|
6
|
+
get label() {
|
|
7
|
+
return this.resource
|
|
8
|
+
.value(rdfs.label)
|
|
9
|
+
.chain((value) => value.toLiteral())
|
|
10
|
+
.toMaybe();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=PropertyGroup.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { NamedNode } from "@rdfjs/types";
|
|
2
|
+
import { Either } from "purify-ts";
|
|
3
|
+
import { Resource } from "rdfjs-resource";
|
|
4
|
+
export interface AlternativePath {
|
|
5
|
+
readonly kind: "AlternativePath";
|
|
6
|
+
readonly members: readonly PropertyPath[];
|
|
7
|
+
}
|
|
8
|
+
export interface InversePath {
|
|
9
|
+
readonly kind: "InversePath";
|
|
10
|
+
readonly path: PropertyPath;
|
|
11
|
+
}
|
|
12
|
+
export interface OneOrMorePath {
|
|
13
|
+
readonly kind: "OneOrMorePath";
|
|
14
|
+
readonly path: PropertyPath;
|
|
15
|
+
}
|
|
16
|
+
export interface PredicatePath {
|
|
17
|
+
readonly iri: NamedNode;
|
|
18
|
+
readonly kind: "PredicatePath";
|
|
19
|
+
}
|
|
20
|
+
export interface SequencePath {
|
|
21
|
+
readonly kind: "SequencePath";
|
|
22
|
+
readonly members: readonly PropertyPath[];
|
|
23
|
+
}
|
|
24
|
+
export interface ZeroOrMorePath {
|
|
25
|
+
readonly kind: "ZeroOrMorePath";
|
|
26
|
+
readonly path: PropertyPath;
|
|
27
|
+
}
|
|
28
|
+
export interface ZeroOrOnePath {
|
|
29
|
+
readonly kind: "ZeroOrOnePath";
|
|
30
|
+
readonly path: PropertyPath;
|
|
31
|
+
}
|
|
32
|
+
export type PropertyPath = AlternativePath | InversePath | OneOrMorePath | PredicatePath | SequencePath | ZeroOrMorePath | ZeroOrOnePath;
|
|
33
|
+
export declare namespace PropertyPath {
|
|
34
|
+
function fromResource(resource: Resource): Either<Error, PropertyPath>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=PropertyPath.d.ts.map
|
package/PropertyPath.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { rdf, sh } from "@tpluscode/rdf-ns-builders";
|
|
2
|
+
import { Either, Left } from "purify-ts";
|
|
3
|
+
import { Resource } from "rdfjs-resource";
|
|
4
|
+
export var PropertyPath;
|
|
5
|
+
(function (PropertyPath) {
|
|
6
|
+
function fromResource(resource) {
|
|
7
|
+
// Predicate path
|
|
8
|
+
// sh:path ex:parent
|
|
9
|
+
if (resource.identifier.termType === "NamedNode") {
|
|
10
|
+
return Either.of({ iri: resource.identifier, kind: "PredicatePath" });
|
|
11
|
+
}
|
|
12
|
+
// The other property path types are BlankNodes
|
|
13
|
+
const getPropertyPathList = (listResource) => {
|
|
14
|
+
return listResource.toList().chain((values) => {
|
|
15
|
+
const members = [];
|
|
16
|
+
for (const value of values) {
|
|
17
|
+
const memberResource = value.toResource().toMaybe();
|
|
18
|
+
if (memberResource.isNothing()) {
|
|
19
|
+
return Left(new Error("non-identifier in property path list"));
|
|
20
|
+
}
|
|
21
|
+
const member = PropertyPath.fromResource(memberResource.unsafeCoerce());
|
|
22
|
+
if (member.isLeft()) {
|
|
23
|
+
return member;
|
|
24
|
+
}
|
|
25
|
+
members.push(member.unsafeCoerce());
|
|
26
|
+
}
|
|
27
|
+
return Either.of(members);
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
for (const quad of resource.dataset.match(resource.identifier, null, null, null)) {
|
|
31
|
+
switch (quad.object.termType) {
|
|
32
|
+
case "BlankNode":
|
|
33
|
+
case "NamedNode":
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
return Left(new Error(`non-BlankNode/NamedNode property path object on path ${resource.identifier.value}: ${quad.object.termType} ${quad.object.value}`));
|
|
37
|
+
}
|
|
38
|
+
const objectResource = new Resource({
|
|
39
|
+
dataset: resource.dataset,
|
|
40
|
+
identifier: quad.object,
|
|
41
|
+
});
|
|
42
|
+
// Alternative path
|
|
43
|
+
// sh:path: [ sh:alternativePath ( ex:father ex:mother ) ]
|
|
44
|
+
if (quad.predicate.equals(sh.alternativePath)) {
|
|
45
|
+
return getPropertyPathList(objectResource).map((members) => ({
|
|
46
|
+
kind: "AlternativePath",
|
|
47
|
+
members,
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
// Inverse path
|
|
51
|
+
// sh:path: [ sh:inversePath ex:parent ]
|
|
52
|
+
if (quad.predicate.equals(sh.inversePath)) {
|
|
53
|
+
return PropertyPath.fromResource(objectResource).map((path) => ({
|
|
54
|
+
kind: "InversePath",
|
|
55
|
+
path,
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
// One or more path
|
|
59
|
+
if (quad.predicate.equals(sh.oneOrMorePath)) {
|
|
60
|
+
return PropertyPath.fromResource(objectResource).map((path) => ({
|
|
61
|
+
kind: "OneOrMorePath",
|
|
62
|
+
path,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
// Sequence path
|
|
66
|
+
// sh:path ( ex:parent ex:firstName )
|
|
67
|
+
if (quad.predicate.equals(rdf.first)) {
|
|
68
|
+
return getPropertyPathList(objectResource).map((members) => ({
|
|
69
|
+
kind: "SequencePath",
|
|
70
|
+
members,
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
// Zero or more path
|
|
74
|
+
if (quad.predicate.equals(sh.zeroOrMorePath)) {
|
|
75
|
+
return PropertyPath.fromResource(objectResource).map((path) => ({
|
|
76
|
+
kind: "ZeroOrMorePath",
|
|
77
|
+
path,
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
if (quad.predicate.equals(sh.zeroOrOnePath)) {
|
|
81
|
+
return PropertyPath.fromResource(objectResource).map((path) => ({
|
|
82
|
+
kind: "ZeroOrOnePath",
|
|
83
|
+
path,
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return Left(new Error(`unrecognized or ill-formed SHACL property path ${resource.identifier.value}`));
|
|
88
|
+
}
|
|
89
|
+
PropertyPath.fromResource = fromResource;
|
|
90
|
+
})(PropertyPath || (PropertyPath = {}));
|
|
91
|
+
//# sourceMappingURL=PropertyPath.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BlankNode, Literal, NamedNode } from "@rdfjs/types";
|
|
2
|
+
import type { Maybe } from "purify-ts";
|
|
3
|
+
import type { Resource } from "rdfjs-resource";
|
|
4
|
+
import type { PropertyGroup } from "./PropertyGroup.js";
|
|
5
|
+
import { PropertyPath } from "./PropertyPath.js";
|
|
6
|
+
import { Shape } from "./Shape.js";
|
|
7
|
+
import type { ShapesGraph } from "./ShapesGraph.js";
|
|
8
|
+
export declare class PropertyShape extends Shape {
|
|
9
|
+
private readonly shapesGraph;
|
|
10
|
+
readonly constraints: Shape.Constraints;
|
|
11
|
+
constructor(resource: Resource, shapesGraph: ShapesGraph);
|
|
12
|
+
get defaultValue(): Maybe<BlankNode | Literal | NamedNode>;
|
|
13
|
+
get editor(): Maybe<NamedNode>;
|
|
14
|
+
get group(): Maybe<PropertyGroup>;
|
|
15
|
+
get order(): Maybe<number>;
|
|
16
|
+
get path(): PropertyPath;
|
|
17
|
+
get singleLine(): Maybe<boolean>;
|
|
18
|
+
get viewer(): Maybe<NamedNode>;
|
|
19
|
+
toString(): string;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=PropertyShape.d.ts.map
|
package/PropertyShape.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { dash, sh } from "@tpluscode/rdf-ns-builders";
|
|
2
|
+
import { PropertyPath } from "./PropertyPath.js";
|
|
3
|
+
import { Shape } from "./Shape.js";
|
|
4
|
+
export class PropertyShape extends Shape {
|
|
5
|
+
constructor(resource, shapesGraph) {
|
|
6
|
+
super(resource);
|
|
7
|
+
this.shapesGraph = shapesGraph;
|
|
8
|
+
this.constraints = new PropertyShape.Constraints(resource, shapesGraph);
|
|
9
|
+
}
|
|
10
|
+
get defaultValue() {
|
|
11
|
+
return this.resource
|
|
12
|
+
.value(sh.defaultValue)
|
|
13
|
+
.map((value) => value.toTerm())
|
|
14
|
+
.toMaybe();
|
|
15
|
+
}
|
|
16
|
+
get editor() {
|
|
17
|
+
return this.resource
|
|
18
|
+
.value(dash.editor)
|
|
19
|
+
.chain((value) => value.toIri())
|
|
20
|
+
.toMaybe();
|
|
21
|
+
}
|
|
22
|
+
get group() {
|
|
23
|
+
return this.resource
|
|
24
|
+
.value(sh.group)
|
|
25
|
+
.chain((value) => value.toIri())
|
|
26
|
+
.toMaybe()
|
|
27
|
+
.chain((node) => this.shapesGraph.propertyGroupByNode(node));
|
|
28
|
+
}
|
|
29
|
+
get order() {
|
|
30
|
+
return this.resource
|
|
31
|
+
.value(sh.maxCount)
|
|
32
|
+
.chain((value) => value.toNumber())
|
|
33
|
+
.toMaybe();
|
|
34
|
+
}
|
|
35
|
+
get path() {
|
|
36
|
+
return this.resource
|
|
37
|
+
.value(sh.path)
|
|
38
|
+
.chain((value) => value.toResource())
|
|
39
|
+
.chain(PropertyPath.fromResource)
|
|
40
|
+
.unsafeCoerce();
|
|
41
|
+
}
|
|
42
|
+
get singleLine() {
|
|
43
|
+
return this.resource
|
|
44
|
+
.value(dash.singleLine)
|
|
45
|
+
.chain((value) => value.toBoolean())
|
|
46
|
+
.toMaybe();
|
|
47
|
+
}
|
|
48
|
+
get viewer() {
|
|
49
|
+
return this.resource
|
|
50
|
+
.value(dash.viewer)
|
|
51
|
+
.chain((value) => value.toIri())
|
|
52
|
+
.toMaybe();
|
|
53
|
+
}
|
|
54
|
+
toString() {
|
|
55
|
+
const keyValues = [`node=${this.resource.identifier.value}`];
|
|
56
|
+
const path = this.path;
|
|
57
|
+
if (path.kind === "PredicatePath") {
|
|
58
|
+
keyValues.push(`path=${path.iri.value}`);
|
|
59
|
+
}
|
|
60
|
+
return `PropertyShape(${keyValues.join(", ")})`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=PropertyShape.js.map
|
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# shacl-ast
|
|
2
|
+
|
|
3
|
+
Build an Abstract Syntax Tree (AST) of [Shapes Constraint Language (SHACL)](https://www.w3.org/TR/shacl/) shapes in an [RDF/JS Dataset](https://rdf.js.org/dataset-spec/).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
npm i @shaclmate/shacl-ast
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { ShapesGraph } from "@shaclmate/shacl-ast";
|
|
13
|
+
|
|
14
|
+
const shapesGraph = ShapesGraph.fromDataset(testShapesGraph);
|
|
15
|
+
for (const nodeShape of shapesGraph.nodeShapes) {
|
|
16
|
+
console.info("Node shape: ", nodeShape.node.value);
|
|
17
|
+
for (const propertyShape of shapesGraph.propertyShapes) {
|
|
18
|
+
console.info(
|
|
19
|
+
" Property shape: ",
|
|
20
|
+
propertyShape.node.value,
|
|
21
|
+
propertyShape.path.value,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
package/Shape.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { BlankNode, Literal, NamedNode } from "@rdfjs/types";
|
|
2
|
+
import type { Maybe } from "purify-ts";
|
|
3
|
+
import type { Resource } from "rdfjs-resource";
|
|
4
|
+
import { NodeKind } from "./NodeKind.js";
|
|
5
|
+
import type { NodeShape } from "./NodeShape.js";
|
|
6
|
+
import type { ShapesGraph } from "./ShapesGraph.js";
|
|
7
|
+
export declare abstract class Shape {
|
|
8
|
+
readonly resource: Resource;
|
|
9
|
+
abstract readonly constraints: Shape.Constraints;
|
|
10
|
+
readonly targets: Shape.Targets;
|
|
11
|
+
protected constructor(resource: Resource);
|
|
12
|
+
get description(): Maybe<Literal>;
|
|
13
|
+
get name(): Maybe<Literal>;
|
|
14
|
+
}
|
|
15
|
+
export declare namespace Shape {
|
|
16
|
+
class Constraints {
|
|
17
|
+
protected readonly resource: Resource;
|
|
18
|
+
protected readonly shapesGraph: ShapesGraph;
|
|
19
|
+
constructor(resource: Resource, shapesGraph: ShapesGraph);
|
|
20
|
+
get and(): readonly Shape[];
|
|
21
|
+
get classes(): readonly NamedNode[];
|
|
22
|
+
get datatype(): Maybe<NamedNode>;
|
|
23
|
+
get hasValue(): Maybe<BlankNode | Literal | NamedNode>;
|
|
24
|
+
get in_(): Maybe<readonly (BlankNode | Literal | NamedNode)[]>;
|
|
25
|
+
get maxCount(): Maybe<number>;
|
|
26
|
+
get maxExclusive(): Maybe<Literal>;
|
|
27
|
+
get maxInclusive(): Maybe<Literal>;
|
|
28
|
+
get minCount(): Maybe<number>;
|
|
29
|
+
get minExclusive(): Maybe<Literal>;
|
|
30
|
+
get minInclusive(): Maybe<Literal>;
|
|
31
|
+
get nodeKinds(): Set<NodeKind>;
|
|
32
|
+
get nodes(): readonly NodeShape[];
|
|
33
|
+
get not(): readonly Shape[];
|
|
34
|
+
get or(): readonly Shape[];
|
|
35
|
+
get xone(): readonly Shape[];
|
|
36
|
+
private listTakingLogicalConstraint;
|
|
37
|
+
}
|
|
38
|
+
class Targets {
|
|
39
|
+
protected readonly resource: Resource;
|
|
40
|
+
constructor(resource: Resource);
|
|
41
|
+
get targetClasses(): readonly NamedNode[];
|
|
42
|
+
get targetNodes(): readonly (Literal | NamedNode)[];
|
|
43
|
+
get targetObjectsOf(): readonly NamedNode[];
|
|
44
|
+
get targetSubjectsOf(): readonly NamedNode[];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=Shape.d.ts.map
|
package/Shape.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { sh } from "@tpluscode/rdf-ns-builders";
|
|
2
|
+
import { NodeKind } from "./NodeKind.js";
|
|
3
|
+
export class Shape {
|
|
4
|
+
constructor(resource) {
|
|
5
|
+
this.resource = resource;
|
|
6
|
+
this.targets = new Shape.Targets(resource);
|
|
7
|
+
}
|
|
8
|
+
get description() {
|
|
9
|
+
return this.resource
|
|
10
|
+
.value(sh.description)
|
|
11
|
+
.chain((value) => value.toLiteral())
|
|
12
|
+
.toMaybe();
|
|
13
|
+
}
|
|
14
|
+
get name() {
|
|
15
|
+
return this.resource
|
|
16
|
+
.value(sh.name)
|
|
17
|
+
.chain((value) => value.toLiteral())
|
|
18
|
+
.toMaybe();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
(function (Shape) {
|
|
22
|
+
class Constraints {
|
|
23
|
+
constructor(resource, shapesGraph) {
|
|
24
|
+
this.resource = resource;
|
|
25
|
+
this.shapesGraph = shapesGraph;
|
|
26
|
+
}
|
|
27
|
+
get and() {
|
|
28
|
+
return this.listTakingLogicalConstraint(sh.and);
|
|
29
|
+
}
|
|
30
|
+
get classes() {
|
|
31
|
+
return [...this.resource.values(sh.class)].flatMap((value) => value.toIri().toMaybe().toList());
|
|
32
|
+
}
|
|
33
|
+
get datatype() {
|
|
34
|
+
return this.resource
|
|
35
|
+
.value(sh.datatype)
|
|
36
|
+
.chain((value) => value.toIri())
|
|
37
|
+
.toMaybe();
|
|
38
|
+
}
|
|
39
|
+
get hasValue() {
|
|
40
|
+
return this.resource
|
|
41
|
+
.value(sh.hasValue)
|
|
42
|
+
.map((value) => value.toTerm())
|
|
43
|
+
.toMaybe();
|
|
44
|
+
}
|
|
45
|
+
get in_() {
|
|
46
|
+
return this.resource
|
|
47
|
+
.value(sh.in)
|
|
48
|
+
.chain((value) => value.toList())
|
|
49
|
+
.map((values) => values.map((value) => value.toTerm()))
|
|
50
|
+
.toMaybe();
|
|
51
|
+
}
|
|
52
|
+
get maxCount() {
|
|
53
|
+
return this.resource
|
|
54
|
+
.value(sh.maxCount)
|
|
55
|
+
.chain((value) => value.toNumber())
|
|
56
|
+
.toMaybe();
|
|
57
|
+
}
|
|
58
|
+
get maxExclusive() {
|
|
59
|
+
return this.resource
|
|
60
|
+
.value(sh.maxExclusive)
|
|
61
|
+
.chain((value) => value.toLiteral())
|
|
62
|
+
.toMaybe();
|
|
63
|
+
}
|
|
64
|
+
get maxInclusive() {
|
|
65
|
+
return this.resource
|
|
66
|
+
.value(sh.maxInclusive)
|
|
67
|
+
.chain((value) => value.toLiteral())
|
|
68
|
+
.toMaybe();
|
|
69
|
+
}
|
|
70
|
+
get minCount() {
|
|
71
|
+
return this.resource
|
|
72
|
+
.value(sh.minCount)
|
|
73
|
+
.chain((value) => value.toNumber())
|
|
74
|
+
.toMaybe();
|
|
75
|
+
}
|
|
76
|
+
get minExclusive() {
|
|
77
|
+
return this.resource
|
|
78
|
+
.value(sh.minExclusive)
|
|
79
|
+
.chain((value) => value.toLiteral())
|
|
80
|
+
.toMaybe();
|
|
81
|
+
}
|
|
82
|
+
get minInclusive() {
|
|
83
|
+
return this.resource
|
|
84
|
+
.value(sh.minInclusive)
|
|
85
|
+
.chain((value) => value.toLiteral())
|
|
86
|
+
.toMaybe();
|
|
87
|
+
}
|
|
88
|
+
get nodeKinds() {
|
|
89
|
+
const nodeKinds = new Set();
|
|
90
|
+
for (const nodeKindValue of this.resource.values(sh.nodeKind)) {
|
|
91
|
+
nodeKindValue.toIri().ifRight((nodeKindIri) => {
|
|
92
|
+
if (nodeKindIri.equals(sh.BlankNode)) {
|
|
93
|
+
nodeKinds.add(NodeKind.BLANK_NODE);
|
|
94
|
+
}
|
|
95
|
+
else if (nodeKindIri.equals(sh.BlankNodeOrIRI)) {
|
|
96
|
+
nodeKinds.add(NodeKind.BLANK_NODE);
|
|
97
|
+
nodeKinds.add(NodeKind.IRI);
|
|
98
|
+
}
|
|
99
|
+
else if (nodeKindIri.equals(sh.BlankNodeOrLiteral)) {
|
|
100
|
+
nodeKinds.add(NodeKind.BLANK_NODE);
|
|
101
|
+
nodeKinds.add(NodeKind.LITERAL);
|
|
102
|
+
}
|
|
103
|
+
else if (nodeKindIri.equals(sh.IRI)) {
|
|
104
|
+
nodeKinds.add(NodeKind.IRI);
|
|
105
|
+
}
|
|
106
|
+
else if (nodeKindIri.equals(sh.IRIOrLiteral)) {
|
|
107
|
+
nodeKinds.add(NodeKind.IRI);
|
|
108
|
+
nodeKinds.add(NodeKind.LITERAL);
|
|
109
|
+
}
|
|
110
|
+
else if (nodeKindIri.equals(sh.Literal)) {
|
|
111
|
+
nodeKinds.add(NodeKind.LITERAL);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return nodeKinds;
|
|
116
|
+
}
|
|
117
|
+
get nodes() {
|
|
118
|
+
return [...this.resource.values(sh.node)].flatMap((value) => value
|
|
119
|
+
.toIdentifier()
|
|
120
|
+
.toMaybe()
|
|
121
|
+
.chain((shapeNode) => this.shapesGraph.nodeShapeByNode(shapeNode))
|
|
122
|
+
.toList());
|
|
123
|
+
}
|
|
124
|
+
get not() {
|
|
125
|
+
return [...this.resource.values(sh.not)].flatMap((value) => value
|
|
126
|
+
.toIdentifier()
|
|
127
|
+
.toMaybe()
|
|
128
|
+
.chain((shapeNode) => this.shapesGraph.shapeByNode(shapeNode))
|
|
129
|
+
.toList());
|
|
130
|
+
}
|
|
131
|
+
get or() {
|
|
132
|
+
return this.listTakingLogicalConstraint(sh.or);
|
|
133
|
+
}
|
|
134
|
+
get xone() {
|
|
135
|
+
return this.listTakingLogicalConstraint(sh.xone);
|
|
136
|
+
}
|
|
137
|
+
listTakingLogicalConstraint(predicate) {
|
|
138
|
+
return this.resource
|
|
139
|
+
.value(predicate)
|
|
140
|
+
.chain((value) => value.toList())
|
|
141
|
+
.map((values) => values.flatMap((value) => value
|
|
142
|
+
.toIdentifier()
|
|
143
|
+
.toMaybe()
|
|
144
|
+
.chain((shapeNode) => this.shapesGraph.shapeByNode(shapeNode))
|
|
145
|
+
.toList()))
|
|
146
|
+
.orDefault([]);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
Shape.Constraints = Constraints;
|
|
150
|
+
class Targets {
|
|
151
|
+
constructor(resource) {
|
|
152
|
+
this.resource = resource;
|
|
153
|
+
}
|
|
154
|
+
get targetClasses() {
|
|
155
|
+
return [...this.resource.values(sh.targetClass)].flatMap((value) => value.toIri().toMaybe().toList());
|
|
156
|
+
}
|
|
157
|
+
get targetNodes() {
|
|
158
|
+
return [...this.resource.values(sh.targetNode)].flatMap((value) => value.toLiteral().toMaybe()
|
|
159
|
+
.altLazy(() => value.toIri().toMaybe())
|
|
160
|
+
.toList());
|
|
161
|
+
}
|
|
162
|
+
get targetObjectsOf() {
|
|
163
|
+
return [...this.resource.values(sh.targetObjectsOf)].flatMap((value) => value.toIri().toMaybe().toList());
|
|
164
|
+
}
|
|
165
|
+
get targetSubjectsOf() {
|
|
166
|
+
return [...this.resource.values(sh.targetSubjectsOf)].flatMap((value) => value.toIri().toMaybe().toList());
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
Shape.Targets = Targets;
|
|
170
|
+
})(Shape || (Shape = {}));
|
|
171
|
+
//# sourceMappingURL=Shape.js.map
|
package/ShapesGraph.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BlankNode, DatasetCore, DefaultGraph, NamedNode } from "@rdfjs/types";
|
|
2
|
+
import { Maybe } from "purify-ts";
|
|
3
|
+
import { NodeShape } from "./NodeShape.js";
|
|
4
|
+
import { PropertyGroup } from "./PropertyGroup.js";
|
|
5
|
+
import { PropertyShape } from "./PropertyShape.js";
|
|
6
|
+
import type { Shape } from "./Shape.js";
|
|
7
|
+
export declare class ShapesGraph {
|
|
8
|
+
readonly dataset: DatasetCore;
|
|
9
|
+
readonly node: BlankNode | DefaultGraph | NamedNode | null;
|
|
10
|
+
readonly nodeShapes: readonly NodeShape[];
|
|
11
|
+
readonly propertyGroups: readonly PropertyGroup[];
|
|
12
|
+
readonly propertyShapes: readonly PropertyShape[];
|
|
13
|
+
private readonly nodeShapesByNode;
|
|
14
|
+
private readonly propertyGroupsByNode;
|
|
15
|
+
private readonly propertyShapesByNode;
|
|
16
|
+
private constructor();
|
|
17
|
+
static fromDataset(dataset: DatasetCore): ShapesGraph;
|
|
18
|
+
nodeShapeByNode(nodeShapeNode: BlankNode | NamedNode): Maybe<NodeShape>;
|
|
19
|
+
propertyGroupByNode(propertyGroupNode: NamedNode): Maybe<PropertyGroup>;
|
|
20
|
+
propertyShapeByNode(propertyShapeNode: BlankNode | NamedNode): Maybe<PropertyShape>;
|
|
21
|
+
shapeByNode(node: BlankNode | NamedNode): Maybe<Shape>;
|
|
22
|
+
private readGraph;
|
|
23
|
+
private readPropertyGroups;
|
|
24
|
+
private readShapes;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ShapesGraph.d.ts.map
|
package/ShapesGraph.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import TermMap from "@rdfjs/term-map";
|
|
2
|
+
import TermSet from "@rdfjs/term-set";
|
|
3
|
+
import { rdf, sh } from "@tpluscode/rdf-ns-builders";
|
|
4
|
+
import { Maybe } from "purify-ts";
|
|
5
|
+
import { Resource, ResourceSet } from "rdfjs-resource";
|
|
6
|
+
import { NodeShape } from "./NodeShape.js";
|
|
7
|
+
import { PropertyGroup } from "./PropertyGroup.js";
|
|
8
|
+
import { PropertyShape } from "./PropertyShape.js";
|
|
9
|
+
export class ShapesGraph {
|
|
10
|
+
constructor(dataset) {
|
|
11
|
+
this.dataset = dataset;
|
|
12
|
+
this.node = this.readGraph();
|
|
13
|
+
const { nodeShapes, nodeShapesByNode, propertyShapes, propertyShapesByNode, } = this.readShapes();
|
|
14
|
+
this.nodeShapes = nodeShapes;
|
|
15
|
+
this.nodeShapesByNode = nodeShapesByNode;
|
|
16
|
+
this.propertyShapes = propertyShapes;
|
|
17
|
+
this.propertyShapesByNode = propertyShapesByNode;
|
|
18
|
+
const { propertyGroups, propertyGroupsByNode } = this.readPropertyGroups();
|
|
19
|
+
this.propertyGroups = propertyGroups;
|
|
20
|
+
this.propertyGroupsByNode = propertyGroupsByNode;
|
|
21
|
+
}
|
|
22
|
+
static fromDataset(dataset) {
|
|
23
|
+
return new ShapesGraph(dataset);
|
|
24
|
+
}
|
|
25
|
+
nodeShapeByNode(nodeShapeNode) {
|
|
26
|
+
return Maybe.fromNullable(this.nodeShapesByNode.get(nodeShapeNode));
|
|
27
|
+
}
|
|
28
|
+
propertyGroupByNode(propertyGroupNode) {
|
|
29
|
+
return Maybe.fromNullable(this.propertyGroupsByNode.get(propertyGroupNode));
|
|
30
|
+
}
|
|
31
|
+
propertyShapeByNode(propertyShapeNode) {
|
|
32
|
+
return Maybe.fromNullable(this.propertyShapesByNode.get(propertyShapeNode));
|
|
33
|
+
}
|
|
34
|
+
shapeByNode(node) {
|
|
35
|
+
const nodeShape = this.nodeShapeByNode(node);
|
|
36
|
+
if (nodeShape.isJust()) {
|
|
37
|
+
return nodeShape;
|
|
38
|
+
}
|
|
39
|
+
return this.propertyShapeByNode(node);
|
|
40
|
+
}
|
|
41
|
+
readGraph() {
|
|
42
|
+
const graphs = new TermSet();
|
|
43
|
+
for (const quad of this.dataset) {
|
|
44
|
+
graphs.add(quad.graph);
|
|
45
|
+
}
|
|
46
|
+
if (graphs.size !== 1) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const graph = [...graphs.values()][0];
|
|
50
|
+
switch (graph.termType) {
|
|
51
|
+
case "BlankNode":
|
|
52
|
+
case "DefaultGraph":
|
|
53
|
+
case "NamedNode":
|
|
54
|
+
return graph;
|
|
55
|
+
default:
|
|
56
|
+
throw new RangeError(`expected NamedNode or default graph, actual ${graph.termType}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
readPropertyGroups() {
|
|
60
|
+
const propertyGroups = [];
|
|
61
|
+
const propertyGroupsByNode = new TermMap();
|
|
62
|
+
for (const quad of this.dataset.match(null, rdf.type, sh.PropertyGroup, this.node)) {
|
|
63
|
+
const subject = quad.subject;
|
|
64
|
+
if (subject.termType !== "NamedNode") {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (propertyGroupsByNode.has(subject)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const propertyGroup = new PropertyGroup(new Resource({ dataset: this.dataset, identifier: subject }));
|
|
71
|
+
propertyGroups.push(propertyGroup);
|
|
72
|
+
propertyGroupsByNode.set(subject, propertyGroup);
|
|
73
|
+
}
|
|
74
|
+
return { propertyGroups, propertyGroupsByNode };
|
|
75
|
+
}
|
|
76
|
+
readShapes() {
|
|
77
|
+
const resourceSet = new ResourceSet({ dataset: this.dataset });
|
|
78
|
+
// Collect the shape identifiers in sets
|
|
79
|
+
const shapeNodeSet = new TermSet();
|
|
80
|
+
// Utility function for doing the collection
|
|
81
|
+
const addShapeNode = (shapeNode) => {
|
|
82
|
+
switch (shapeNode.termType) {
|
|
83
|
+
case "BlankNode":
|
|
84
|
+
case "NamedNode":
|
|
85
|
+
shapeNodeSet.add(shapeNode);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
// Test each shape condition
|
|
90
|
+
// https://www.w3.org/TR/shacl/#shapes
|
|
91
|
+
// Subject is a SHACL instance of sh:NodeShape or sh:PropertyShape
|
|
92
|
+
for (const rdfType of [sh.NodeShape, sh.PropertyShape]) {
|
|
93
|
+
for (const resource of resourceSet.instancesOf(rdfType, {
|
|
94
|
+
graph: this.node,
|
|
95
|
+
})) {
|
|
96
|
+
addShapeNode(resource.identifier);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Subject of a triple with sh:targetClass, sh:targetNode, sh:targetObjectsOf, or sh:targetSubjectsOf predicate
|
|
100
|
+
for (const predicate of [
|
|
101
|
+
sh.targetClass,
|
|
102
|
+
sh.targetNode,
|
|
103
|
+
sh.targetObjectsOf,
|
|
104
|
+
sh.targetSubjectsOf,
|
|
105
|
+
]) {
|
|
106
|
+
for (const quad of this.dataset.match(null, predicate, null, this.node)) {
|
|
107
|
+
addShapeNode(quad.subject);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Subject of a triple that has a parameter as predicate
|
|
111
|
+
// https://www.w3.org/TR/shacl/#constraints
|
|
112
|
+
// https://www.w3.org/TR/shacl/#core-components
|
|
113
|
+
for (const predicate of [
|
|
114
|
+
sh.class,
|
|
115
|
+
sh.datatype,
|
|
116
|
+
sh.nodeKind,
|
|
117
|
+
sh.minCount,
|
|
118
|
+
sh.maxCount,
|
|
119
|
+
sh.minExclusive,
|
|
120
|
+
sh.minInclusive,
|
|
121
|
+
sh.maxExclusive,
|
|
122
|
+
sh.maxInclusive,
|
|
123
|
+
sh.minLength,
|
|
124
|
+
sh.maxLength,
|
|
125
|
+
sh.pattern,
|
|
126
|
+
sh.languageIn,
|
|
127
|
+
sh.uniqueLang,
|
|
128
|
+
sh.equals,
|
|
129
|
+
sh.disjoint,
|
|
130
|
+
sh.lessThan,
|
|
131
|
+
sh.lessThanOrEquals,
|
|
132
|
+
sh.not,
|
|
133
|
+
sh.and,
|
|
134
|
+
sh.or,
|
|
135
|
+
sh.xone,
|
|
136
|
+
sh.node,
|
|
137
|
+
sh.property,
|
|
138
|
+
sh.qualifiedValueShape,
|
|
139
|
+
sh.qualifiedMinCount,
|
|
140
|
+
sh.qualifiedMaxCount,
|
|
141
|
+
sh.closed,
|
|
142
|
+
sh.ignoredProperties,
|
|
143
|
+
sh.hasValue,
|
|
144
|
+
sh.in,
|
|
145
|
+
]) {
|
|
146
|
+
for (const quad of this.dataset.match(null, predicate, null, this.node)) {
|
|
147
|
+
addShapeNode(quad.subject);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Object of a shape-expecting, non-list-taking parameter such as sh:node
|
|
151
|
+
for (const predicate of [sh.node, sh.property]) {
|
|
152
|
+
for (const quad of this.dataset.match(null, predicate, null, this.node)) {
|
|
153
|
+
addShapeNode(quad.object);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Member of a SHACL list that is a value of a shape-expecting and list-taking parameter such as sh:or
|
|
157
|
+
for (const predicate of [sh.and, sh["in"], sh.languageIn, sh.or, sh.xone]) {
|
|
158
|
+
for (const quad of this.dataset.match(null, predicate, null, this.node)) {
|
|
159
|
+
switch (quad.object.termType) {
|
|
160
|
+
case "BlankNode":
|
|
161
|
+
case "NamedNode":
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
for (const value of resourceSet
|
|
167
|
+
.resource(quad.object)
|
|
168
|
+
.toList()
|
|
169
|
+
.orDefault([])) {
|
|
170
|
+
value.toIdentifier().ifRight(addShapeNode);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Separate shapes into node and property shapes.
|
|
175
|
+
const nodeShapes = [];
|
|
176
|
+
const nodeShapesByNode = new TermMap();
|
|
177
|
+
const propertyShapes = [];
|
|
178
|
+
const propertyShapesByNode = new TermMap();
|
|
179
|
+
for (const shapeNode of shapeNodeSet) {
|
|
180
|
+
if (this.dataset.match(shapeNode, sh.path, null, this.node).size > 0) {
|
|
181
|
+
// 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.
|
|
182
|
+
const propertyShape = new PropertyShape(resourceSet.resource(shapeNode), this);
|
|
183
|
+
propertyShapes.push(propertyShape);
|
|
184
|
+
propertyShapesByNode.set(shapeNode, propertyShape);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
// 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.
|
|
188
|
+
const nodeShape = new NodeShape(resourceSet.resource(shapeNode), this);
|
|
189
|
+
nodeShapes.push(nodeShape);
|
|
190
|
+
nodeShapesByNode.set(shapeNode, nodeShape);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
nodeShapes,
|
|
195
|
+
nodeShapesByNode,
|
|
196
|
+
propertyShapes,
|
|
197
|
+
propertyShapesByNode,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=ShapesGraph.js.map
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./NodeKind.js";
|
|
2
|
+
export * from "./NodeShape.js";
|
|
3
|
+
export * from "./PropertyGroup.js";
|
|
4
|
+
export * from "./PropertyPath.js";
|
|
5
|
+
export * from "./PropertyShape.js";
|
|
6
|
+
export * from "./Shape.js";
|
|
7
|
+
export * from "./ShapesGraph.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
package/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./NodeKind.js";
|
|
2
|
+
export * from "./NodeShape.js";
|
|
3
|
+
export * from "./PropertyGroup.js";
|
|
4
|
+
export * from "./PropertyPath.js";
|
|
5
|
+
export * from "./PropertyShape.js";
|
|
6
|
+
export * from "./Shape.js";
|
|
7
|
+
export * from "./ShapesGraph.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@rdfjs/term-map": "^2.0.2",
|
|
4
|
+
"@rdfjs/term-set": "^2.0.3",
|
|
5
|
+
"@rdfjs/types": "^1.1.0",
|
|
6
|
+
"@tpluscode/rdf-ns-builders": "^4.3.0",
|
|
7
|
+
"@types/rdfjs__term-map": "^2.0.10",
|
|
8
|
+
"@types/rdfjs__term-set": "^2.0.9",
|
|
9
|
+
"purify-ts": "^2.1.0",
|
|
10
|
+
"rdfjs-resource": "1.0.12"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@types/n3": "^1.21.1",
|
|
14
|
+
"n3": "^1.21.3"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"*.d.ts",
|
|
18
|
+
"*.js"
|
|
19
|
+
],
|
|
20
|
+
"main": "index.js",
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"name": "@shaclmate/shacl-ast",
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc -b",
|
|
25
|
+
"check": "biome check",
|
|
26
|
+
"check:write": "biome check --write",
|
|
27
|
+
"check:write:unsafe": "biome check --write --unsafe",
|
|
28
|
+
"clean": "rimraf -g **/*.d.ts* **/*.js **/*.js.map tsconfig.tsbuildinfo",
|
|
29
|
+
"format": "biome format",
|
|
30
|
+
"format:write": "biome format --write",
|
|
31
|
+
"format:write:unsafe": "biome format --write --unsafe",
|
|
32
|
+
"rebuild": "run-s clean build",
|
|
33
|
+
"link-dependencies": "npm link purify-ts-helpers rdfjs-resource",
|
|
34
|
+
"lint": "biome lint",
|
|
35
|
+
"lint:write": "biome lint --write",
|
|
36
|
+
"lint:write:unsafe": "biome lint --write --unsafe",
|
|
37
|
+
"test": "biome check && vitest run",
|
|
38
|
+
"test:coverage": "biome check && vitest run --coverage",
|
|
39
|
+
"test:watch": "vitest watch",
|
|
40
|
+
"unlink": "npm unlink -g @shaclmate/shacl-ast",
|
|
41
|
+
"watch": "tsc -w --preserveWatchOutput"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/minorg/shaclmate"
|
|
46
|
+
},
|
|
47
|
+
"type": "module",
|
|
48
|
+
"types": "index.d.ts",
|
|
49
|
+
"version": "2.0.13"
|
|
50
|
+
}
|