@shaclmate/compiler 4.0.14 → 4.0.15

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.
Files changed (31) hide show
  1. package/dist/Compiler.d.ts +4 -1
  2. package/dist/Compiler.js +3 -1
  3. package/dist/ShapesGraphToAstTransformer.d.ts +10 -2
  4. package/dist/ShapesGraphToAstTransformer.js +72 -1
  5. package/dist/_ShapesGraphToAstTransformer/nodeShapeIdentifierMintingStrategy.js +14 -13
  6. package/dist/_ShapesGraphToAstTransformer/shapeNodeKinds.js +18 -17
  7. package/dist/_ShapesGraphToAstTransformer/transformShapeToAstCompoundType.js +6 -2
  8. package/dist/_ShapesGraphToAstTransformer/transformShapeToAstListType.js +8 -8
  9. package/dist/_ShapesGraphToAstTransformer/transformShapeToAstObjectType.js +10 -5
  10. package/dist/generators/ts/AbstractCollectionType.js +1 -7
  11. package/dist/generators/ts/AbstractTermType.d.ts +1 -0
  12. package/dist/generators/ts/AbstractTermType.js +6 -0
  13. package/dist/generators/ts/AbstractUnionType.d.ts +31 -9
  14. package/dist/generators/ts/AbstractUnionType.js +252 -126
  15. package/dist/generators/ts/SetType.d.ts +1 -0
  16. package/dist/generators/ts/SetType.js +12 -0
  17. package/dist/input/ShapesGraph.d.ts +38 -21
  18. package/dist/input/ShapesGraph.js +56 -58
  19. package/dist/input/generated.d.ts +204 -39
  20. package/dist/input/generated.js +2281 -676
  21. package/dist/input/index.d.ts +1 -3
  22. package/dist/input/index.js +1 -3
  23. package/package.json +2 -2
  24. package/dist/input/NodeShape.d.ts +0 -11
  25. package/dist/input/NodeShape.js +0 -2
  26. package/dist/input/Shape.d.ts +0 -4
  27. package/dist/input/Shape.js +0 -2
  28. package/dist/input/ancestorClassIris.d.ts +0 -4
  29. package/dist/input/ancestorClassIris.js +0 -24
  30. package/dist/input/descendantClassIris.d.ts +0 -4
  31. package/dist/input/descendantClassIris.js +0 -27
@@ -1,10 +1,13 @@
1
1
  import type { Either } from "purify-ts";
2
+ import type { TsFeature } from "./enums/TsFeature.js";
2
3
  import type { Generator } from "./generators/Generator.js";
3
4
  import type { ShapesGraph } from "./input/ShapesGraph.js";
4
5
  export declare class Compiler {
5
6
  private readonly generator;
6
- constructor({ generator }: {
7
+ private readonly tsFeaturesDefault?;
8
+ constructor({ generator, }: {
7
9
  generator: Generator;
10
+ tsFeaturesDefault?: ReadonlySet<TsFeature>;
8
11
  });
9
12
  compile(shapesGraph: ShapesGraph): Either<Error, string>;
10
13
  }
package/dist/Compiler.js CHANGED
@@ -1,12 +1,14 @@
1
1
  import { ShapesGraphToAstTransformer } from "./ShapesGraphToAstTransformer.js";
2
2
  export class Compiler {
3
3
  generator;
4
- constructor({ generator }) {
4
+ tsFeaturesDefault;
5
+ constructor({ generator, }) {
5
6
  this.generator = generator;
6
7
  }
7
8
  compile(shapesGraph) {
8
9
  return new ShapesGraphToAstTransformer({
9
10
  shapesGraph,
11
+ tsFeaturesDefault: this.tsFeaturesDefault,
10
12
  })
11
13
  .transform()
12
14
  .map((ast) => this.generator.generate(ast));
@@ -1,12 +1,19 @@
1
1
  import TermMap from "@rdfjs/term-map";
2
- import type * as rdfjs from "@rdfjs/types";
2
+ import type { BlankNode, NamedNode } from "@rdfjs/types";
3
3
  import { Either } from "purify-ts";
4
4
  import type * as ast from "./ast/index.js";
5
5
  import type { TsFeature } from "./enums/TsFeature.js";
6
6
  import type * as input from "./input/index.js";
7
+ interface RelatedNodeShapes {
8
+ readonly ancestors: input.NodeShape[];
9
+ readonly children: input.NodeShape[];
10
+ readonly parents: input.NodeShape[];
11
+ readonly descendants: input.NodeShape[];
12
+ }
7
13
  export declare class ShapesGraphToAstTransformer {
8
- protected readonly cachedAstTypesByShapeIdentifier: TermMap<rdfjs.BlankNode | rdfjs.NamedNode, ast.Type>;
14
+ protected readonly cachedAstTypesByShapeIdentifier: TermMap<BlankNode | NamedNode, ast.Type>;
9
15
  protected readonly shapesGraph: input.ShapesGraph;
16
+ protected readonly relatedNodeShapesByIdentifier: TermMap<BlankNode | NamedNode, RelatedNodeShapes>;
10
17
  protected tsFeaturesDefault: ReadonlySet<TsFeature>;
11
18
  constructor({ shapesGraph, tsFeaturesDefault, }: {
12
19
  shapesGraph: input.ShapesGraph;
@@ -14,4 +21,5 @@ export declare class ShapesGraphToAstTransformer {
14
21
  });
15
22
  transform(): Either<Error, ast.Ast>;
16
23
  }
24
+ export {};
17
25
  //# sourceMappingURL=ShapesGraphToAstTransformer.d.ts.map
@@ -1,15 +1,86 @@
1
1
  import TermMap from "@rdfjs/term-map";
2
2
  import { dash } from "@tpluscode/rdf-ns-builders";
3
3
  import { Either } from "purify-ts";
4
+ import { Resource } from "rdfjs-resource";
4
5
  import { invariant } from "ts-invariant";
5
6
  import { ShapeStack } from "./_ShapesGraphToAstTransformer/ShapeStack.js";
6
7
  import { transformShapeToAstType } from "./_ShapesGraphToAstTransformer/transformShapeToAstType.js";
8
+ import { logger } from "./logger.js";
9
+ function relatedNodeShapes(shapesGraph) {
10
+ const immediateRelatedNodeShapes = new TermMap();
11
+ for (const childNodeShape of shapesGraph.nodeShapes) {
12
+ let childRelatedNodeShapes = immediateRelatedNodeShapes.get(childNodeShape.$identifier);
13
+ if (!childRelatedNodeShapes) {
14
+ childRelatedNodeShapes = {
15
+ children: new TermMap(),
16
+ parents: new TermMap(),
17
+ };
18
+ immediateRelatedNodeShapes.set(childNodeShape.$identifier, childRelatedNodeShapes);
19
+ }
20
+ for (const parentClassIdentifier of childNodeShape.subClassOf) {
21
+ shapesGraph
22
+ .nodeShape(parentClassIdentifier)
23
+ .ifLeft((error) => {
24
+ logger.error("%s is rdfs:subClassOf %s which is either missing or not a node shape: %s", childNodeShape, Resource.Identifier.toString(parentClassIdentifier), error.message);
25
+ })
26
+ .ifRight((parentNodeShape) => {
27
+ childRelatedNodeShapes.parents.set(parentNodeShape.$identifier, parentNodeShape);
28
+ let parentRelatedNodeShapes = immediateRelatedNodeShapes.get(parentNodeShape.$identifier);
29
+ if (!parentRelatedNodeShapes) {
30
+ parentRelatedNodeShapes = {
31
+ children: new TermMap(),
32
+ parents: new TermMap(),
33
+ };
34
+ immediateRelatedNodeShapes.set(parentNodeShape.$identifier, parentRelatedNodeShapes);
35
+ }
36
+ parentRelatedNodeShapes.children.set(childNodeShape.$identifier, childNodeShape);
37
+ });
38
+ }
39
+ }
40
+ const result = new TermMap();
41
+ for (const nodeShape of shapesGraph.nodeShapes) {
42
+ const { children: childNodeShapes, parents: parentNodeShapes } = immediateRelatedNodeShapes.get(nodeShape.$identifier);
43
+ const ancestorNodeShapes = new TermMap();
44
+ function recurseAncestorNodeShapes(nodeShape) {
45
+ for (const parentNodeShape of immediateRelatedNodeShapes
46
+ .get(nodeShape.$identifier)
47
+ .parents.values()) {
48
+ if (!ancestorNodeShapes.has(parentNodeShape.$identifier)) {
49
+ ancestorNodeShapes.set(parentNodeShape.$identifier, parentNodeShape);
50
+ recurseAncestorNodeShapes(parentNodeShape);
51
+ }
52
+ }
53
+ }
54
+ recurseAncestorNodeShapes(nodeShape);
55
+ const descendantNodeShapes = new TermMap();
56
+ function recurseDescendantNodeShapes(nodeShape) {
57
+ for (const childNodeShape of immediateRelatedNodeShapes
58
+ .get(nodeShape.$identifier)
59
+ .children.values()) {
60
+ if (!descendantNodeShapes.has(childNodeShape.$identifier)) {
61
+ descendantNodeShapes.set(childNodeShape.$identifier, childNodeShape);
62
+ recurseDescendantNodeShapes(childNodeShape);
63
+ }
64
+ }
65
+ }
66
+ recurseDescendantNodeShapes(nodeShape);
67
+ result.set(nodeShape.$identifier, {
68
+ ancestors: [...ancestorNodeShapes.values()],
69
+ children: [...childNodeShapes.values()],
70
+ descendants: [...descendantNodeShapes.values()],
71
+ parents: [...parentNodeShapes.values()],
72
+ });
73
+ }
74
+ return result;
75
+ }
7
76
  export class ShapesGraphToAstTransformer {
8
77
  // Members are protected so they're accessible to functions in other files
9
78
  cachedAstTypesByShapeIdentifier = new TermMap();
10
79
  shapesGraph;
80
+ relatedNodeShapesByIdentifier = new TermMap();
11
81
  tsFeaturesDefault;
12
82
  constructor({ shapesGraph, tsFeaturesDefault, }) {
83
+ this.relatedNodeShapesByIdentifier = relatedNodeShapes(shapesGraph);
13
84
  this.shapesGraph = shapesGraph;
14
85
  this.tsFeaturesDefault =
15
86
  tsFeaturesDefault ??
@@ -39,7 +110,7 @@ export class ShapesGraphToAstTransformer {
39
110
  }
40
111
  break;
41
112
  case "ObjectType": {
42
- invariant(nodeShapeAstType.name.isJust());
113
+ invariant(nodeShapeAstType.name.isJust(), `node shape missing name: ${nodeShapeAstType.shapeIdentifier}`);
43
114
  astObjectTypes.push(nodeShapeAstType);
44
115
  for (const property of nodeShapeAstType.properties) {
45
116
  switch (property.type.kind) {
@@ -12,20 +12,21 @@ export function nodeShapeIdentifierMintingStrategy(nodeShape) {
12
12
  }
13
13
  return Either.of(nodeShape.identifierMintingStrategy.map(IdentifierMintingStrategy.fromIri));
14
14
  }
15
- return Either.sequence(nodeShape.ancestorClassIris.map((nodeShapeIdentifier) => this.shapesGraph.nodeShape(nodeShapeIdentifier))).chain((ancestorNodeShapes) => {
16
- for (const ancestorNodeShape of ancestorNodeShapes) {
17
- if (ancestorNodeShape.identifierMintingStrategy.isJust()) {
18
- return Either.of(ancestorNodeShape.identifierMintingStrategy.map(IdentifierMintingStrategy.fromIri));
19
- }
15
+ // Recurse into parents
16
+ for (const parentNodeShape of this.relatedNodeShapesByIdentifier.get(nodeShape.$identifier).parents) {
17
+ const parentNodeShapeIdentifierMintingStrategy = nodeShapeIdentifierMintingStrategy.call(this, parentNodeShape);
18
+ if (parentNodeShapeIdentifierMintingStrategy.isRight() &&
19
+ parentNodeShapeIdentifierMintingStrategy.extract().isJust()) {
20
+ return parentNodeShapeIdentifierMintingStrategy;
20
21
  }
21
- return shapeNodeKinds
22
- .call(this, nodeShape, { defaultNodeShapeNodeKinds })
23
- .map((nodeKinds) => {
24
- if (nodeKinds.has("BlankNode")) {
25
- return Maybe.of("blankNode");
26
- }
27
- return Maybe.empty();
28
- });
22
+ }
23
+ return shapeNodeKinds
24
+ .call(this, nodeShape, { defaultNodeShapeNodeKinds })
25
+ .map((nodeKinds) => {
26
+ if (nodeKinds.has("BlankNode")) {
27
+ return Maybe.of("blankNode");
28
+ }
29
+ return Maybe.empty();
29
30
  });
30
31
  }
31
32
  //# sourceMappingURL=nodeShapeIdentifierMintingStrategy.js.map
@@ -10,28 +10,29 @@ function nodeShapeNodeKinds(nodeShape) {
10
10
  const thisNodeKinds = nodeShape.nodeKind
11
11
  .map(NodeKind.fromIri)
12
12
  .orDefault(new Set());
13
- return Either.sequence(nodeShape.parentClassIris.map((nodeShapeIdentifier) => this.shapesGraph.nodeShape(nodeShapeIdentifier))).chain((parentNodeShapes) => {
14
- const parentNodeKinds = new Set();
15
- for (const parentNodeShape of parentNodeShapes) {
16
- for (const parentNodeKind of parentNodeShape.nodeKind
17
- .map(NodeKind.fromIri)
18
- .orDefault(new Set())) {
13
+ // Recurse into parents
14
+ const parentNodeKinds = new Set();
15
+ for (const parentNodeShape of this.relatedNodeShapesByIdentifier.get(nodeShape.$identifier).parents) {
16
+ nodeShapeNodeKinds
17
+ .call(this, parentNodeShape)
18
+ .ifRight((parentNodeKinds_) => {
19
+ for (const parentNodeKind of parentNodeKinds_) {
19
20
  parentNodeKinds.add(parentNodeKind);
20
21
  }
22
+ });
23
+ }
24
+ if (parentNodeKinds.size > 0) {
25
+ if (thisNodeKinds.size === 0) {
26
+ return Either.of(parentNodeKinds);
21
27
  }
22
- if (parentNodeKinds.size > 0) {
23
- if (thisNodeKinds.size === 0) {
24
- return Either.of(parentNodeKinds);
25
- }
26
- // Check that thisNodeKinds doesn't conflict with parent node kinds
27
- for (const thisNodeKind of thisNodeKinds) {
28
- if (!parentNodeKinds.has(thisNodeKind)) {
29
- return Left(new Error(`${nodeShape} has a nodeKind ${thisNodeKind} that is not in its parent's node kinds`));
30
- }
28
+ // Check that thisNodeKinds doesn't conflict with parent node kinds
29
+ for (const thisNodeKind of thisNodeKinds) {
30
+ if (!parentNodeKinds.has(thisNodeKind)) {
31
+ return Left(new Error(`${nodeShape} has a nodeKind ${thisNodeKind} that is not in its parent's node kinds`));
31
32
  }
32
33
  }
33
- return Either.of(thisNodeKinds);
34
- });
34
+ }
35
+ return Either.of(thisNodeKinds);
35
36
  }
36
37
  function propertyShapeNodeKinds(propertyShape) {
37
38
  return Either.of(propertyShape.nodeKind.map(NodeKind.fromIri).orDefault(new Set()));
@@ -11,9 +11,13 @@ import { transformShapeToAstType } from "./transformShapeToAstType.js";
11
11
  export function transformShapeToAstCompoundType(shape, shapeStack) {
12
12
  shapeStack.push(shape);
13
13
  try {
14
- return Eithers.chain4(Either.sequence(shape.and.flatMap((and) => and.map((shapeIdentifier) => this.shapesGraph.shape(shapeIdentifier)))), Either.sequence(shape.nodes.map((nodeShapeIdentifier) => this.shapesGraph.nodeShape(nodeShapeIdentifier))), shape.$type === "NodeShape"
14
+ return Eithers.chain4(Either.sequence(shape.and
15
+ .orDefault([])
16
+ .map((shapeIdentifier) => this.shapesGraph.shape(shapeIdentifier))), Either.sequence(shape.nodes.map((nodeShapeIdentifier) => this.shapesGraph.nodeShape(nodeShapeIdentifier))), shape.$type === "NodeShape"
15
17
  ? nodeShapeTsFeatures.call(this, shape)
16
- : Either.of(new Set()), Either.sequence(shape.xone.flatMap((xone) => xone.map((shapeIdentifier) => this.shapesGraph.shape(shapeIdentifier))))).chain(([andConstraintShapes, nodeConstraintShapes, tsFeatures, xoneConstraintShapes,]) => {
18
+ : Either.of(new Set()), Either.sequence(shape.xone
19
+ .orDefault([])
20
+ .map((shapeIdentifier) => this.shapesGraph.shape(shapeIdentifier)))).chain(([andConstraintShapes, nodeConstraintShapes, tsFeatures, xoneConstraintShapes,]) => {
17
21
  let compoundTypeKind;
18
22
  // Distinguish constraints that take arbitrary shapes from those that only take node shapes
19
23
  // With the latter we'll do special transformations.
@@ -35,6 +35,7 @@ const astListTypePlaceholderItemType = new ast.BlankNodeType({
35
35
  name: Maybe.empty(),
36
36
  shapeIdentifier: dataFactory.blankNode(),
37
37
  });
38
+ const empty = Either.of(Maybe.empty());
38
39
  /**
39
40
  * Is an ast.ObjectType actually the shape of an RDF list?
40
41
  * If so, return the type of its rdf:first.
@@ -43,13 +44,12 @@ export function transformShapeToAstListType(shape, shapeStack) {
43
44
  shapeStack.push(shape);
44
45
  try {
45
46
  if (shape.$type !== "NodeShape") {
46
- return Either.of(Maybe.empty());
47
+ return empty;
47
48
  }
48
49
  const nodeShape = shape;
49
- if (!nodeShape.isList) {
50
- return Either.of(Maybe.empty());
51
- }
52
- return Eithers.chain3(nodeShapeIdentifierMintingStrategy.call(this, nodeShape), shapeNodeKinds.call(this, nodeShape, { defaultNodeShapeNodeKinds }), Either.sequence(nodeShape.xone.flatMap((xone) => xone.map((shapeIdentifier) => this.shapesGraph.shape(shapeIdentifier))))).chain(([identifierMintingStrategy, nodeKinds, xone]) => {
50
+ return Eithers.chain3(nodeShapeIdentifierMintingStrategy.call(this, nodeShape), shapeNodeKinds.call(this, nodeShape, { defaultNodeShapeNodeKinds }), Either.sequence(nodeShape.xone
51
+ .orDefault([])
52
+ .map((shapeIdentifier) => this.shapesGraph.shape(shapeIdentifier)))).chain(([identifierMintingStrategy, nodeKinds, xone]) => {
53
53
  // Put a placeholder in the cache to deal with cyclic references
54
54
  // Remove the placeholder if the transformation fails.
55
55
  const listType = new ast.ListType({
@@ -78,7 +78,7 @@ export function transformShapeToAstListType(shape, shapeStack) {
78
78
  }
79
79
  }
80
80
  if (!emptyListShape || !nonEmptyListShape) {
81
- return Left(new Error(`${nodeShape} does not have an sh:xone with exactly two shapes, one for the empty list and one for the non-empty list`));
81
+ return empty;
82
82
  }
83
83
  return Either.sequence(nonEmptyListShape.properties.map((propertyShapeIdentifier) => this.shapesGraph.propertyShape(propertyShapeIdentifier))).chain((nonEmptyListShapeProperties) => {
84
84
  let firstPropertyShape;
@@ -95,14 +95,14 @@ export function transformShapeToAstListType(shape, shapeStack) {
95
95
  }
96
96
  }
97
97
  if (!firstPropertyShape) {
98
- return Left(new Error(`${nodeShape} has a non-empty list shape without an sh:property shape whose sh:path is rdf:first`));
98
+ return empty;
99
99
  }
100
100
  if (firstPropertyShape.maxCount.extract() !== 1 ||
101
101
  firstPropertyShape.minCount.extract() !== 1) {
102
102
  return Left(new Error(`${nodeShape} non-empty list shape rdf:first property shape does not have sh:maxCount=1 and/or sh:minCount=1`));
103
103
  }
104
104
  if (!restPropertyShape) {
105
- return Left(new Error(`${nodeShape} has a non-empty list shape without an sh:property shape whose sh:path is rdf:rest`));
105
+ return empty;
106
106
  }
107
107
  if (restPropertyShape.maxCount.extract() !== 1 ||
108
108
  restPropertyShape.minCount.extract() !== 1) {
@@ -1,3 +1,4 @@
1
+ import { owl, rdfs } from "@tpluscode/rdf-ns-builders";
1
2
  import { Either, Left, Maybe } from "purify-ts";
2
3
  import { invariant } from "ts-invariant";
3
4
  import * as ast from "../ast/index.js";
@@ -49,24 +50,28 @@ export function transformShapeToAstObjectType(shape, shapeStack) {
49
50
  return Either.of(Maybe.empty());
50
51
  }
51
52
  const nodeShape = shape;
52
- if (nodeShape.and.length > 0 || nodeShape.xone.length > 0) {
53
+ if (nodeShape.and.orDefault([]).length > 0 ||
54
+ nodeShape.xone.orDefault([]).length > 0) {
53
55
  return Either.of(Maybe.empty());
54
56
  }
55
57
  if (nodeShape.$identifier.termType !== "NamedNode") {
56
58
  return Either.of(Maybe.empty());
57
59
  }
58
- return Eithers.chain9(Either.sequence(nodeShape.ancestorClassIris.map((nodeShapeIdentifier) => this.shapesGraph.nodeShape(nodeShapeIdentifier))), Either.sequence(nodeShape.childClassIris.map((nodeShapeIdentifier) => this.shapesGraph.nodeShape(nodeShapeIdentifier))), Either.sequence(nodeShape.descendantClassIris.map((nodeShapeIdentifier) => this.shapesGraph.nodeShape(nodeShapeIdentifier))), Either.sequence(nodeShape.parentClassIris.map((nodeShapeIdentifier) => this.shapesGraph.nodeShape(nodeShapeIdentifier))), nodeShapeIdentifierMintingStrategy.call(this, nodeShape), shapeNodeKinds.call(this, nodeShape, { defaultNodeShapeNodeKinds }), Either.sequence(nodeShape.properties.map((propertyShapeIdentifier) => this.shapesGraph.propertyShape(propertyShapeIdentifier))), nodeShapeTsFeatures.call(this, nodeShape), nodeShape.tsObjectDeclarationType.isJust()
60
+ return Eithers.chain5(nodeShapeIdentifierMintingStrategy.call(this, nodeShape), shapeNodeKinds.call(this, nodeShape, { defaultNodeShapeNodeKinds }), Either.sequence(nodeShape.properties.map((propertyShapeIdentifier) => this.shapesGraph.propertyShape(propertyShapeIdentifier))), nodeShapeTsFeatures.call(this, nodeShape), nodeShape.tsObjectDeclarationType.isJust()
59
61
  ? Either.of(nodeShape.tsObjectDeclarationType.map(TsObjectDeclarationType.fromIri))
60
62
  : shapeOntology
61
63
  .call(this, nodeShape)
62
- .map((ontology) => ontology.chain((ontology) => ontology.tsObjectDeclarationType.map(TsObjectDeclarationType.fromIri)))).chain(([ancestorNodeShapes, childNodeShapes, descendantNodeShapes, parentNodeShapes, identifierMintingStrategy, nodeKinds, propertyShapes, tsFeatures, tsObjectDeclarationType,]) => {
64
+ .map((ontology) => ontology.chain((ontology) => ontology.tsObjectDeclarationType.map(TsObjectDeclarationType.fromIri)))).chain(([identifierMintingStrategy, nodeKinds, propertyShapes, tsFeatures, tsObjectDeclarationType,]) => {
63
65
  const abstract = nodeShape.abstract.orDefault(false);
66
+ const { ancestors: ancestorNodeShapes, descendants: descendantNodeShapes, children: childNodeShapes, parents: parentNodeShapes, } = this.relatedNodeShapesByIdentifier.get(nodeShape.$identifier);
67
+ const isClass = nodeShape.subClassOf.length > 0 ||
68
+ descendantNodeShapes.length > 0 || // A node shape that is the object of an rdfs:subClassOf is itself an rdfs:Class
69
+ nodeShape.types.some((type) => type.equals(owl.Class) || type.equals(rdfs.Class));
64
70
  let fromRdfType;
65
71
  let toRdfTypes;
66
72
  if (!abstract) {
67
73
  fromRdfType = nodeShape.fromRdfType.alt(nodeShape.rdfType);
68
- if (nodeShape.isClass &&
69
- nodeShape.$identifier.termType === "NamedNode") {
74
+ if (isClass && nodeShape.$identifier.termType === "NamedNode") {
70
75
  fromRdfType = fromRdfType.alt(Maybe.of(nodeShape.$identifier));
71
76
  }
72
77
  toRdfTypes = nodeShape.toRdfTypes.concat();
@@ -55,12 +55,6 @@ export class AbstractCollectionType extends AbstractContainerType {
55
55
  }
56
56
  }
57
57
  if (this.minCount === 0) {
58
- conversions.push({
59
- conversionExpression: () => code `[]`,
60
- sourceTypeCheckExpression: (value) => code `${value} === undefined`,
61
- sourceTypeName: code `undefined`,
62
- sourceTypeof: "undefined",
63
- });
64
58
  if (Object.keys(itemTypeConversionsByTypeof).length <= 1) {
65
59
  // There were no additional conversions with different item typeof's, so we don't need to check .every or do .map
66
60
  // Just check that the original value is an array with typeof "object". Array.isArray() doesn't narrow types for some reason.
@@ -101,7 +95,7 @@ export class AbstractCollectionType extends AbstractContainerType {
101
95
  case "function":
102
96
  case "symbol":
103
97
  case "undefined":
104
- throw new Error("not implemented");
98
+ throw new Error(`source type check on ${itemTypeof} not implemented`);
105
99
  }
106
100
  },
107
101
  sourceTypeName: code `readonly (${itemTypeofConversion.sourceTypeName})[]`,
@@ -31,6 +31,7 @@ export declare abstract class AbstractTermType<ConstantTermT extends Literal | N
31
31
  get conversions(): readonly AbstractType.Conversion[];
32
32
  get discriminantProperty(): Maybe<AbstractType.DiscriminantProperty>;
33
33
  get schema(): Code;
34
+ get termTypes(): ReadonlySet<"BlankNode" | "Literal" | "NamedNode">;
34
35
  get valueSparqlConstructTriplesFunction(): Code;
35
36
  fromRdfResourceValuesExpression(parameters: Parameters<AbstractType["fromRdfResourceValuesExpression"]>[0]): Code;
36
37
  hashStatements({ variables, }: Parameters<AbstractType["hashStatements"]>[0]): readonly Code[];
@@ -90,6 +90,9 @@ export class AbstractTermType extends AbstractType {
90
90
  get schema() {
91
91
  return code `${removeUndefined(this.schemaObject)}`;
92
92
  }
93
+ get termTypes() {
94
+ return new Set([...this.nodeKinds].map(NodeKind.toTermType));
95
+ }
93
96
  get valueSparqlConstructTriplesFunction() {
94
97
  return code `((_: object) => [])`;
95
98
  }
@@ -164,6 +167,9 @@ __decorate([
164
167
  __decorate([
165
168
  Memoize()
166
169
  ], AbstractTermType.prototype, "schema", null);
170
+ __decorate([
171
+ Memoize()
172
+ ], AbstractTermType.prototype, "termTypes", null);
167
173
  __decorate([
168
174
  Memoize()
169
175
  ], AbstractTermType.prototype, "valueSparqlConstructTriplesFunction", null);
@@ -4,6 +4,7 @@ import type { BlankNodeType } from "./BlankNodeType.js";
4
4
  import type { IdentifierType } from "./IdentifierType.js";
5
5
  import type { IriType } from "./IriType.js";
6
6
  import type { Type } from "./Type.js";
7
+ import type { Typeof } from "./Typeof.js";
7
8
  import { type Code } from "./ts-poet-wrapper.js";
8
9
  export declare abstract class AbstractUnionType<MemberTypeT extends Type> extends AbstractType {
9
10
  private readonly discriminant;
@@ -45,18 +46,37 @@ export declare abstract class AbstractUnionType<MemberTypeT extends Type> extend
45
46
  jsonUiSchemaElement(): Maybe<Code>;
46
47
  protected inlineHashStatements({ depth, variables, }: Parameters<AbstractType["hashStatements"]>[0]): readonly Code[];
47
48
  }
48
- type Discriminant = EnvelopeDiscriminant | InlineDiscriminant | TypeofDiscriminant;
49
- type EnvelopeDiscriminant = {
50
- kind: "envelope";
51
- } & AbstractType.DiscriminantProperty;
52
- type InlineDiscriminant = {
53
- kind: "inline";
54
- } & AbstractType.DiscriminantProperty;
49
+ type Discriminant = ExtrinsicDiscriminant | HybridDiscriminant | IntrinsicDiscriminant | TypeofDiscriminant;
50
+ type ExtrinsicDiscriminant = {
51
+ readonly kind: "extrinsic";
52
+ readonly memberValues: readonly AbstractType.DiscriminantProperty.Value[];
53
+ readonly name: string;
54
+ };
55
+ type HybridDiscriminant = {
56
+ readonly kind: "hybrid";
57
+ readonly memberValues: readonly {
58
+ readonly kind: "extrinsic" | "intrinsic";
59
+ readonly ownValues: readonly AbstractType.DiscriminantProperty.Value[];
60
+ }[];
61
+ readonly name: string;
62
+ };
63
+ type IntrinsicDiscriminant = {
64
+ readonly kind: "intrinsic";
65
+ readonly memberValues: readonly {
66
+ readonly descendantValues: readonly AbstractType.DiscriminantProperty.Value[];
67
+ readonly ownValues: readonly AbstractType.DiscriminantProperty.Value[];
68
+ }[];
69
+ readonly name: string;
70
+ };
55
71
  type TypeofDiscriminant = {
56
- kind: "typeof";
72
+ readonly kind: "typeof";
73
+ readonly memberValues: readonly Typeof[];
57
74
  };
58
75
  export declare namespace Discriminant {
59
- function infer(memberTypes: readonly Type[]): Discriminant;
76
+ function infer(members: readonly {
77
+ readonly discriminantValue: Maybe<number | string>;
78
+ readonly type: Type;
79
+ }[]): Discriminant;
60
80
  }
61
81
  export declare namespace AbstractUnionType {
62
82
  interface AbstractMember<TypeT extends Type> {
@@ -67,10 +87,12 @@ export declare namespace AbstractUnionType {
67
87
  interface ConcreteMember<TypeT extends Type> {
68
88
  readonly abstract: false;
69
89
  readonly discriminantValues: readonly AbstractType.DiscriminantProperty.Value[];
90
+ readonly jsonType: Code | string;
70
91
  readonly jsonTypeCheck: (instance: Code) => Code;
71
92
  readonly primaryDiscriminantValue: AbstractType.DiscriminantProperty.Value;
72
93
  readonly type: TypeT;
73
94
  readonly typeCheck: (instance: Code) => Code;
95
+ readonly typeToJsonExpression: (valueVariable: Code) => Code;
74
96
  readonly unwrap: (instance: Code) => Code;
75
97
  readonly wrap: (instance: Code) => Code;
76
98
  }