Parses types correctly

main
Jackson Morgan 9 months ago
parent 3316818633
commit b33571b547
  1. 14
      package-lock.json
  2. 1
      packages/jsonld-dataset-proxy/src/index.ts
  3. 3
      packages/schema-converter-shex/package.json
  4. 15
      packages/schema-converter-shex/src/context/JsonLdContextBuilder.ts
  5. 96
      packages/schema-converter-shex/src/context/ShexJContextVisitor.ts
  6. 1
      packages/schema-converter-shex/src/context/shexjToContext.ts
  7. 80
      packages/schema-converter-shex/src/typing/ShexJTypingTransformer.ts
  8. 2
      packages/schema-converter-shex/src/typing/shexjToTyping.ts
  9. 44
      packages/schema-converter-shex/src/typing/util/dedupeObjectTypeMembers.ts
  10. 110
      packages/schema-converter-shex/src/util/getRdfTypesForTripleConstraint.ts
  11. 1
      packages/schema-converter-shex/test/context.test.ts
  12. 8839
      packages/schema-converter-shex/test/testData/activityPub.ts
  13. 6
      packages/schema-converter-shex/test/testData/circular.ts
  14. 38
      packages/schema-converter-shex/test/testData/extendsSimple.ts
  15. 46
      packages/schema-converter-shex/test/testData/oldExtends.ts
  16. 404
      packages/schema-converter-shex/test/testData/profile.ts
  17. 188
      packages/schema-converter-shex/test/testData/reducedProfile.ts
  18. 76
      packages/schema-converter-shex/test/testData/reusedPredicates.ts
  19. 6
      packages/schema-converter-shex/test/testData/simple.ts
  20. 18
      packages/schema-converter-shex/test/testData/testData.ts
  21. 35
      packages/schema-converter-shex/test/testData/testIfLegal.ts
  22. 1
      packages/traverser-shexj/package.json
  23. 13
      packages/traverser-shexj/src/ShexJTraverserDefinition.ts
  24. 4
      packages/traverser-shexj/src/ShexJTraverserTypes.ts
  25. 602
      packages/traverser-shexj/src/ShexJTypes.ts
  26. 9
      packages/type-traverser/src/index.ts
  27. 2
      packages/type-traverser/src/instanceGraph/nodes/InstanceNode.ts
  28. 12
      packages/type-traverser/src/instanceGraph/nodes/InterfaceInstanceNode.ts

14
package-lock.json generated

@ -12592,10 +12592,6 @@
"node": ">=12"
}
},
"node_modules/dts-dom": {
"version": "3.7.0",
"license": "Apache-2.0"
},
"node_modules/duplexer": {
"version": "0.1.2",
"license": "MIT"
@ -29352,10 +29348,11 @@
"license": "MIT",
"dependencies": {
"@ldo/traverser-shexj": "^0.0.1-alpha.24",
"dts-dom": "^3.6.0",
"dts-dom": "~3.6.0",
"jsonld2graphobject": "^0.0.5"
},
"devDependencies": {
"@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.24",
"@shexjs/parser": "^1.0.0-alpha.24",
"@types/jest": "^27.0.3",
"@types/jsonld": "^1.5.6",
@ -29366,6 +29363,12 @@
"ts-jest": "^27.1.2"
}
},
"packages/schema-converter-shex/node_modules/dts-dom": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/dts-dom/-/dts-dom-3.6.0.tgz",
"integrity": "sha512-on5jxTgt+A6r0Zyyz6ZRHXaAO7J1VPnOd6+AmvI1vH440AlAZZNc5rUHzgPuTjGlrVr1rOWQYNl7ZJK6rDohbw==",
"license": "Apache-2.0"
},
"packages/schema-converter-shex/node_modules/jsonld2graphobject": {
"version": "0.0.5",
"license": "MIT",
@ -29735,7 +29738,6 @@
},
"devDependencies": {
"@types/jest": "^27.0.3",
"@types/shexj": "^2.1.3",
"jest": "^27.4.5",
"ts-jest": "^27.1.2"
}

@ -9,6 +9,7 @@ export * from "./jsonldDatasetProxy";
export * from "./write";
export * from "./graphOf";
export * from "./setLanguagePreferences";
export * from "./LdoJsonldContext";
export * from "./language/languagesOf";
export * from "./language/languageMapProxy";

@ -20,6 +20,7 @@
},
"homepage": "https://github.com/o-development/ldobjects/tree/main/packages/schema-converter-shex#readme",
"devDependencies": {
"@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.24",
"@shexjs/parser": "^1.0.0-alpha.24",
"@types/jest": "^27.0.3",
"@types/jsonld": "^1.5.6",
@ -34,7 +35,7 @@
],
"dependencies": {
"@ldo/traverser-shexj": "^0.0.1-alpha.24",
"dts-dom": "^3.6.0",
"dts-dom": "~3.6.0",
"jsonld2graphobject": "^0.0.5"
},
"publishConfig": {

@ -97,7 +97,7 @@ export class JsonLdContextBuilder {
if (!relevantBuilder.iriTypes[iri]) {
relevantBuilder.iriTypes[iri] = expandedTermDefinition;
if (isContainer) {
relevantBuilder.iriTypes[iri]["@isContainer"] = true;
relevantBuilder.iriTypes[iri]["@isCollection"] = true;
}
} else {
const curDef = relevantBuilder.iriTypes[iri];
@ -106,7 +106,7 @@ export class JsonLdContextBuilder {
// it will overwrite the past cardinality. Perhapse we might want to
// split contexts in the various shapes.
if (isContainer) {
curDef["@isContainer"] = true;
curDef["@isCollection"] = true;
}
// If the old and new versions both have types
if (curDef["@type"] && newDef["@type"]) {
@ -172,12 +172,13 @@ export class JsonLdContextBuilder {
return generatedNames;
}
getNameFromIri(iri: string) {
if (!this.generatedNames) {
this.generatedNames = this.generateNames();
getNameFromIri(iri: string, rdfType?: string) {
const relevantBuilder = this.getRelevantBuilder(rdfType);
if (!relevantBuilder.generatedNames) {
relevantBuilder.generatedNames = relevantBuilder.generateNames();
}
if (this.generatedNames[iri]) {
return this.generatedNames[iri];
if (relevantBuilder.generatedNames[iri]) {
return relevantBuilder.generatedNames[iri];
} else {
return iri;
}

@ -1,5 +1,6 @@
import ShexJTraverser from "@ldo/traverser-shexj";
import type { JsonLdContextBuilder } from "./JsonLdContextBuilder";
import { getRdfTypesForTripleConstraint } from "../util/getRdfTypesForTripleConstraint";
/**
* Visitor
@ -10,67 +11,72 @@ export const ShexJNameVisitor =
visitor: async (_shape, _context) => {},
},
TripleConstraint: {
visitor: async (tripleConstraint, context) => {
// TODO: check that there's a triple constraint that is a type at the
visitor: async (tripleConstraint, node, context) => {
// Check that there's a triple constraint that is a type at the
// same level if there is, use that as an rdfType
if (tripleConstraint.valueExpr) {
const isContainer =
tripleConstraint.max !== undefined && tripleConstraint.max !== 1;
if (typeof tripleConstraint.valueExpr === "string") {
// TOOD handle string value expr
} else if (tripleConstraint.valueExpr.type === "NodeConstraint") {
if (tripleConstraint.valueExpr.datatype) {
const rdfTypes = getRdfTypesForTripleConstraint(node);
// For Each RDF Type, add it
rdfTypes.forEach((rdfType) => {
if (tripleConstraint.valueExpr) {
const isContainer =
tripleConstraint.max !== undefined && tripleConstraint.max !== 1;
if (typeof tripleConstraint.valueExpr === "string") {
// TOOD handle string value expr
} else if (tripleConstraint.valueExpr.type === "NodeConstraint") {
if (tripleConstraint.valueExpr.datatype) {
context.addPredicate(
tripleConstraint.predicate,
{
"@type": tripleConstraint.valueExpr.datatype,
},
isContainer,
rdfType,
tripleConstraint.annotations,
);
} else if (
tripleConstraint.valueExpr.nodeKind &&
tripleConstraint.valueExpr.nodeKind !== "literal"
) {
context.addPredicate(
tripleConstraint.predicate,
{ "@type": "@id" },
isContainer,
rdfType,
tripleConstraint.annotations,
);
} else {
context.addPredicate(
tripleConstraint.predicate,
{},
isContainer,
rdfType,
tripleConstraint.annotations,
);
}
} else {
context.addPredicate(
tripleConstraint.predicate,
{
"@type": tripleConstraint.valueExpr.datatype,
"@type": "@id",
},
isContainer,
undefined,
tripleConstraint.annotations,
);
} else if (
tripleConstraint.valueExpr.nodeKind &&
tripleConstraint.valueExpr.nodeKind !== "literal"
) {
context.addPredicate(
tripleConstraint.predicate,
{ "@type": "@id" },
isContainer,
undefined,
tripleConstraint.annotations,
);
} else {
context.addPredicate(
tripleConstraint.predicate,
{},
isContainer,
undefined,
rdfType,
tripleConstraint.annotations,
);
}
} else {
context.addPredicate(
context.addSubject(
tripleConstraint.predicate,
{
"@type": "@id",
},
isContainer,
undefined,
rdfType,
tripleConstraint.annotations,
);
}
} else {
context.addSubject(
tripleConstraint.predicate,
undefined,
tripleConstraint.annotations,
);
}
});
},
},
NodeConstraint: {
visitor: async (nodeConstraint, context) => {
visitor: async (nodeConstraint, node, context) => {
if (nodeConstraint.values) {
nodeConstraint.values.forEach((value) => {
if (typeof value === "string") {
@ -81,7 +87,7 @@ export const ShexJNameVisitor =
},
},
IriStem: {
visitor: async (iriStem, context) => {
visitor: async (iriStem, node, context) => {
context.addSubject(iriStem.stem);
},
},

@ -14,6 +14,7 @@ export async function shexjToContext(
"@context": "http://www.w3.org/ns/shex.jsonld",
},
"SCHEMA",
{ excludeContext: true },
)) as unknown as Schema;
const jsonLdContextBuilder = new JsonLdContextBuilder();
await ShexJNameVisitor.visit(processedShexj, "Schema", jsonLdContextBuilder);

@ -3,9 +3,11 @@ import * as dom from "dts-dom";
import type { Annotation } from "shexj";
import { nameFromObject } from "../context/JsonLdContextBuilder";
import type { ShapeInterfaceDeclaration } from "./ShapeInterfaceDeclaration";
import { getRdfTypesForTripleConstraint } from "../util/getRdfTypesForTripleConstraint";
import { dedupeObjectTypeMembers } from "./util/dedupeObjectTypeMembers";
export interface ShexJTypeTransformerContext {
getNameFromIri: (iri: string) => string;
getNameFromIri: (iri: string, rdfType?: string) => string;
}
export function commentFromAnnotations(
@ -125,12 +127,19 @@ export const ShexJTypingTransformer = ShexJTraverser.createTransformer<
}
// Use EXTENDS
if (transformedChildren.extends) {
newInterface.baseTypes = [];
transformedChildren.extends.forEach((extendsItem) => {
if ((extendsItem as dom.InterfaceDeclaration).kind === "interface") {
newInterface.baseTypes?.push(
extendsItem as dom.InterfaceDeclaration,
);
const extendsInterface = extendsItem as dom.InterfaceDeclaration;
if (extendsInterface.kind === "interface") {
// NOTE: This is how you would use the actual typescript "extends"
// feature, but as ShEx extend doesn't work the same way as ts
// extends, we just dedupe and push members.
// newInterface.baseTypes?.push(
// extendsItem as dom.InterfaceDeclaration,
// );
newInterface.members = dedupeObjectTypeMembers([
...extendsInterface.members,
...newInterface.members,
]);
}
});
}
@ -144,7 +153,6 @@ export const ShexJTypingTransformer = ShexJTraverser.createTransformer<
const objectType = name
? dom.create.interface(name)
: dom.create.objectType([]);
const eachOfComment = commentFromAnnotations(eachOf.annotations);
setReturnPointer(objectType);
// Get Input property expressions
const inputPropertyExpressions: dom.PropertyDeclaration[] = [];
@ -178,49 +186,9 @@ export const ShexJTypingTransformer = ShexJTraverser.createTransformer<
}
},
);
// Merge property expressions
const properties: Record<string, dom.PropertyDeclaration> = {};
inputPropertyExpressions.forEach((expression) => {
const propertyDeclaration = expression as dom.PropertyDeclaration;
// Combine properties if they're duplicates
if (properties[propertyDeclaration.name]) {
const oldPropertyDeclaration = properties[propertyDeclaration.name];
const oldPropertyTypeAsArray =
oldPropertyDeclaration.type as dom.ArrayTypeReference;
const oldProeprtyType =
oldPropertyTypeAsArray.kind === "array"
? oldPropertyTypeAsArray.type
: oldPropertyDeclaration.type;
const propertyTypeAsArray =
propertyDeclaration.type as dom.ArrayTypeReference;
const propertyType =
propertyTypeAsArray.kind === "array"
? propertyTypeAsArray.type
: propertyDeclaration.type;
const isOptional =
propertyDeclaration.flags === dom.DeclarationFlags.Optional ||
oldPropertyDeclaration.flags === dom.DeclarationFlags.Optional;
properties[propertyDeclaration.name] = dom.create.property(
propertyDeclaration.name,
dom.type.array(dom.create.union([oldProeprtyType, propertyType])),
isOptional
? dom.DeclarationFlags.Optional
: dom.DeclarationFlags.None,
);
// Set JS Comment
properties[propertyDeclaration.name].jsDocComment =
oldPropertyDeclaration.jsDocComment &&
propertyDeclaration.jsDocComment
? `${oldPropertyDeclaration.jsDocComment} | ${propertyDeclaration.jsDocComment}`
: oldPropertyDeclaration.jsDocComment ||
propertyDeclaration.jsDocComment ||
eachOfComment;
} else {
properties[propertyDeclaration.name] = propertyDeclaration;
}
});
objectType.members.push(...Object.values(properties));
objectType.members.push(
...dedupeObjectTypeMembers(inputPropertyExpressions),
);
return objectType;
},
},
@ -229,10 +197,19 @@ export const ShexJTypingTransformer = ShexJTraverser.createTransformer<
tripleConstraint,
getTransformedChildren,
setReturnPointer,
node,
context,
) => {
const transformedChildren = await getTransformedChildren();
const propertyName = context.getNameFromIri(tripleConstraint.predicate);
const rdfTypes = getRdfTypesForTripleConstraint(node);
// HACK: Selecting only one RDFType might cause edge cases children in the
// heirarchy that have different predicate names.
const propertyName = context.getNameFromIri(
tripleConstraint.predicate,
rdfTypes[0],
);
const isArray =
tripleConstraint.max !== undefined && tripleConstraint.max !== 1;
const isOptional = tripleConstraint.min === 0;
@ -258,6 +235,7 @@ export const ShexJTypingTransformer = ShexJTraverser.createTransformer<
nodeConstraint,
_getTransformedChildren,
setReturnPointer,
node,
context,
) => {
if (nodeConstraint.datatype) {

@ -42,7 +42,7 @@ export async function shexjToTyping(
.emit(declaration, {
rootFlags: dom.ContextFlags.InAmbientNamespace,
})
.replace("\r\n", "\n"),
.replace(/\r\n/g, "\n"),
dts: declaration,
};
});

@ -0,0 +1,44 @@
import type { ObjectTypeMember } from "dts-dom";
import * as dom from "dts-dom";
export function dedupeObjectTypeMembers(
memberList: ObjectTypeMember[],
): ObjectTypeMember[] {
const properties: Record<string, dom.PropertyDeclaration> = {};
memberList.forEach((expression) => {
const propertyDeclaration = expression as dom.PropertyDeclaration;
// Combine properties if they're duplicates
if (properties[propertyDeclaration.name]) {
const oldPropertyDeclaration = properties[propertyDeclaration.name];
const oldPropertyTypeAsArray =
oldPropertyDeclaration.type as dom.ArrayTypeReference;
const oldProeprtyType =
oldPropertyTypeAsArray.kind === "array"
? oldPropertyTypeAsArray.type
: oldPropertyDeclaration.type;
const propertyTypeAsArray =
propertyDeclaration.type as dom.ArrayTypeReference;
const propertyType =
propertyTypeAsArray.kind === "array"
? propertyTypeAsArray.type
: propertyDeclaration.type;
const isOptional =
propertyDeclaration.flags === dom.DeclarationFlags.Optional ||
oldPropertyDeclaration.flags === dom.DeclarationFlags.Optional;
properties[propertyDeclaration.name] = dom.create.property(
propertyDeclaration.name,
dom.type.array(dom.create.union([oldProeprtyType, propertyType])),
isOptional ? dom.DeclarationFlags.Optional : dom.DeclarationFlags.None,
);
// Set JS Comment
properties[propertyDeclaration.name].jsDocComment =
oldPropertyDeclaration.jsDocComment && propertyDeclaration.jsDocComment
? `${oldPropertyDeclaration.jsDocComment} | ${propertyDeclaration.jsDocComment}`
: oldPropertyDeclaration.jsDocComment ||
propertyDeclaration.jsDocComment;
} else {
properties[propertyDeclaration.name] = propertyDeclaration;
}
});
return Object.values(properties);
}

@ -0,0 +1,110 @@
import type { ShexJTraverserTypes } from "@ldo/traverser-shexj";
import type { InterfaceInstanceNode } from "@ldo/type-traverser";
function recursivelyGatherTypesFromShapeNodes(
shapeNode: InterfaceInstanceNode<
ShexJTraverserTypes,
"Shape",
ShexJTraverserTypes["Shape"]
>,
rdfTypeSet: Set<string>,
): void {
shapeNode.parent("shapeExpr").forEach((parentShapeExpr) => {
parentShapeExpr
.parent("ShapeDecl", "shapeExpr")
.forEach((parentShapeDecl) => {
parentShapeDecl
.parent("shapeDeclRef")
.forEach((parentShapeDeclOrRef) => {
parentShapeDeclOrRef
.parent("shapeExprOrRef")
.forEach((parentShapeExprOrRef) => {
parentShapeExprOrRef
.parent("Shape", "extends")
.forEach((parentShape) => {
recursivelyGatherTypesFromShapeNodes(
parentShape,
rdfTypeSet,
);
const childExpressionNode = parentShape.child("expression");
if (!childExpressionNode) return;
const childEachOf = childExpressionNode.child().child();
if (childEachOf.typeName === "EachOf") {
recursivelyGatherTypesFromEachOfNodes(
childEachOf,
rdfTypeSet,
);
}
});
});
});
});
});
}
function recursivelyGatherTypesFromEachOfNodes(
eachOfNode: InterfaceInstanceNode<
ShexJTraverserTypes,
"EachOf",
ShexJTraverserTypes["EachOf"]
>,
rdfTypeSet: Set<string>,
): void {
const tripleExprs = eachOfNode.instance.expressions;
tripleExprs.forEach((tripleExpr) => {
if (
typeof tripleExpr === "object" &&
tripleExpr.type === "TripleConstraint" &&
tripleExpr.predicate ===
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type" &&
typeof tripleExpr.valueExpr === "object" &&
tripleExpr.valueExpr.type === "NodeConstraint" &&
tripleExpr.valueExpr.values
) {
tripleExpr.valueExpr.values.forEach((val) => {
if (typeof val === "string") rdfTypeSet.add(val);
// TODO handle other edge cases like IRIStem
});
}
});
eachOfNode.parent("tripleExpr").forEach((tripleExprNode) => {
const tripleExprOrRefNodes = tripleExprNode.parent("tripleExprOrRef");
tripleExprOrRefNodes.forEach((tripleExprOrRdfNode) => {
const parentEachOfs = tripleExprOrRdfNode.parent("EachOf", "expressions");
parentEachOfs.forEach((parentEachOf) => {
recursivelyGatherTypesFromEachOfNodes(parentEachOf, rdfTypeSet);
});
// Deal with shape extends
const parentShapes = tripleExprOrRdfNode.parent("Shape", "expression");
parentShapes.forEach((parentShape) =>
recursivelyGatherTypesFromShapeNodes(parentShape, rdfTypeSet),
);
});
});
}
export function getRdfTypesForTripleConstraint(
tripleConstraintNode: InterfaceInstanceNode<
ShexJTraverserTypes,
"TripleConstraint",
ShexJTraverserTypes["TripleConstraint"]
>,
): string[] | undefined[] {
// Check that there's a triple constraint that is a type at the
// same level if there is, use that as an rdfType
const rdfTypeSet = new Set<string>();
tripleConstraintNode.parent("tripleExpr").forEach((tripleExprParents) => {
tripleExprParents
.parent("tripleExprOrRef")
.forEach((tripleExprOrRefParent) => {
tripleExprOrRefParent
.parent("EachOf", "expressions")
.forEach((eachOfParent) => {
recursivelyGatherTypesFromEachOfNodes(eachOfParent, rdfTypeSet);
});
});
});
const rdfTypes = rdfTypeSet.size > 0 ? Array.from(rdfTypeSet) : [undefined];
return rdfTypes;
}

@ -9,7 +9,6 @@ describe("context", () => {
const schema: Schema = parser
.construct("https://ldo.js.org/")
.parse(shexc);
console.log(JSON.stringify(schema, null, 2));
const context = await shexjToContext(schema);
expect(context).toEqual(successfulContext);
});

File diff suppressed because one or more lines are too long

@ -31,14 +31,14 @@ export const circular: TestData = {
`,
baseNode: "http://example.com/SampleParent",
successfulContext: {
SampleParent: {
Parent: {
"@id": "http://example.com/Parent",
"@context": {
type: { "@id": "@type" },
hasChild: { "@id": "http://example.com/hasChild", "@type": "@id" },
},
},
SampleChild: {
Child: {
"@id": "http://example.com/Child",
"@context": {
type: { "@id": "@type" },
@ -47,5 +47,5 @@ export const circular: TestData = {
},
},
successfulTypings:
'import {ContextDefinition} from "jsonld"\n\nexport interface ParentShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n type?: {\r\n "@id": "Parent";\r\n };\r\n hasChild: ChildShape;\r\n}\r\n\r\nexport interface ChildShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n type?: {\r\n "@id": "Child";\r\n };\r\n hasParent: ParentShape;\r\n}\r\n\r\n',
'import {ContextDefinition} from "jsonld"\n\nexport interface ParentShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type?: {\n "@id": "Parent";\n };\n hasChild: ChildShape;\n}\n\nexport interface ChildShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type?: {\n "@id": "Child";\n };\n hasParent: ParentShape;\n}\n\n',
};

@ -10,14 +10,17 @@ export const extendsSimple: TestData = {
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
ex:EntityShape {
a [ ex:Entity ] ;
ex:entityId .
}
ex:PersonShape EXTENDS @ex:EntityShape {
a [ ex:Person ] ;
foaf:name .
}
ex:EmployeeShape EXTENDS @ex:PersonShape {
a [ ex:Employee ] ;
ex:employeeNumber .
}
`,
@ -34,10 +37,37 @@ export const extendsSimple: TestData = {
`,
baseNode: "http://example.com/SampleParent",
successfulContext: {
entityId: "https://example.com/entityId",
name: "http://xmlns.com/foaf/0.1/name",
employeeNumber: "https://example.com/employeeNumber",
Entity: {
"@id": "https://example.com/Entity",
"@context": {
type: {
"@id": "@type",
},
entityId: "https://example.com/entityId",
},
},
Person: {
"@id": "https://example.com/Person",
"@context": {
type: {
"@id": "@type",
},
entityId: "https://example.com/entityId",
name: "http://xmlns.com/foaf/0.1/name",
},
},
Employee: {
"@id": "https://example.com/Employee",
"@context": {
type: {
"@id": "@type",
},
entityId: "https://example.com/entityId",
name: "http://xmlns.com/foaf/0.1/name",
employeeNumber: "https://example.com/employeeNumber",
},
},
},
successfulTypings:
'import {ContextDefinition} from "jsonld"\n\nexport interface EntityShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n entityId: any;\r\n}\r\n\r\nexport interface PersonShapeextends EntityShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n name: any;\r\n}\r\n\r\nexport interface EmployeeShapeextends PersonShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n employeeNumber: any;\r\n}\r\n\r\n',
'import {ContextDefinition} from "jsonld"\n\nexport interface EntityShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Entity";\n };\n entityId: any;\n}\n\nexport interface PersonShape {\n "@id"?: (string | string)[];\n "@context"?: (ContextDefinition | ContextDefinition)[];\n type: ({\n "@id": "Entity";\n } | {\n "@id": "Person";\n })[];\n entityId: any;\n name: any;\n}\n\nexport interface EmployeeShape {\n "@id"?: (string | string | string)[];\n "@context"?: (ContextDefinition | ContextDefinition | ContextDefinition)[];\n type: ({\n "@id": "Entity";\n } | {\n "@id": "Person";\n } | {\n "@id": "Employee";\n })[];\n entityId: any;\n name: any;\n employeeNumber: any;\n}\n\n',
};

@ -1,7 +1,7 @@
import type { TestData } from "./testData";
/**
* Circular
* Old Extends
*/
export const oldExtends: TestData = {
name: "old extends",
@ -9,21 +9,24 @@ export const oldExtends: TestData = {
PREFIX ex: <https://example.com/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
ex:EntityShape {
ex:EntityShape EXTRA a {
$ex:EntityRef (
a [ ex:Entity ] ;
ex:entityId .
)
}
ex:PersonShape {
ex:PersonShape EXTRA a {
$ex:PersonRef (
&ex:EntityRef ;
a [ ex:Person ] ;
foaf:name .
)
}
ex:EmployeeShape EXTENDS @ex:PersonShape {
ex:EmployeeShape EXTRA a {
&ex:PersonRef ;
a [ ex:Employee ] ;
ex:employeeNumber .
}
`,
@ -39,10 +42,37 @@ export const oldExtends: TestData = {
`,
baseNode: "http://example.com/SampleParent",
successfulContext: {
entityId: "https://example.com/entityId",
name: "http://xmlns.com/foaf/0.1/name",
employeeNumber: "https://example.com/employeeNumber",
Entity: {
"@id": "https://example.com/Entity",
"@context": {
type: {
"@id": "@type",
},
entityId: "https://example.com/entityId",
},
},
Person: {
"@id": "https://example.com/Person",
"@context": {
type: {
"@id": "@type",
},
entityId: "https://example.com/entityId",
name: "http://xmlns.com/foaf/0.1/name",
},
},
Employee: {
"@id": "https://example.com/Employee",
"@context": {
type: {
"@id": "@type",
},
entityId: "https://example.com/entityId",
name: "http://xmlns.com/foaf/0.1/name",
employeeNumber: "https://example.com/employeeNumber",
},
},
},
successfulTypings:
'import {ContextDefinition} from "jsonld"\n\nexport interface EntityShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n entityId: any;\r\n}\r\n\r\nexport interface PersonShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n entityId: any;\r\n name: any;\r\n}\r\n\r\nexport interface EmployeeShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n entityId: any;\r\n name: any;\r\n employeeNumber: any;\r\n}\r\n\r\n',
'import {ContextDefinition} from "jsonld"\n\nexport interface EntityShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Entity";\n };\n entityId: any;\n}\n\nexport interface PersonShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: ({\n "@id": "Entity";\n } | {\n "@id": "Person";\n })[];\n entityId: any;\n name: any;\n}\n\nexport interface EmployeeShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: ({\n "@id": "Entity";\n } | {\n "@id": "Person";\n } | {\n "@id": "Employee";\n })[];\n entityId: any;\n name: any;\n employeeNumber: any;\n}\n\n',
};

File diff suppressed because one or more lines are too long

@ -51,31 +51,173 @@ srs:EmailShape EXTRA a {
sampleTurtle: ``,
baseNode: "",
successfulContext: {
type: { "@id": "@type" },
Person: "http://schema.org/Person",
Person2: "http://xmlns.com/foaf/0.1/Person",
hasEmail: {
"@id": "http://www.w3.org/2006/vcard/ns#hasEmail",
"@type": "@id",
"@container": "@set",
Person: {
"@id": "http://schema.org/Person",
"@context": {
type: {
"@id": "@type",
},
hasEmail: {
"@id": "http://www.w3.org/2006/vcard/ns#hasEmail",
"@type": "@id",
"@isCollection": true,
},
name: {
"@id": "http://xmlns.com/foaf/0.1/name",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
},
},
Dom: "http://www.w3.org/2006/vcard/ns#Dom",
Home: "http://www.w3.org/2006/vcard/ns#Home",
ISDN: "http://www.w3.org/2006/vcard/ns#ISDN",
Internet: "http://www.w3.org/2006/vcard/ns#Internet",
Intl: "http://www.w3.org/2006/vcard/ns#Intl",
Label: "http://www.w3.org/2006/vcard/ns#Label",
Parcel: "http://www.w3.org/2006/vcard/ns#Parcel",
Postal: "http://www.w3.org/2006/vcard/ns#Postal",
Pref: "http://www.w3.org/2006/vcard/ns#Pref",
Work: "http://www.w3.org/2006/vcard/ns#Work",
X400: "http://www.w3.org/2006/vcard/ns#X400",
value: { "@id": "http://www.w3.org/2006/vcard/ns#value", "@type": "@id" },
name: {
"@id": "http://xmlns.com/foaf/0.1/name",
"@type": "http://www.w3.org/2001/XMLSchema#string",
Person2: {
"@id": "http://xmlns.com/foaf/0.1/Person",
"@context": {
type: {
"@id": "@type",
},
hasEmail: {
"@id": "http://www.w3.org/2006/vcard/ns#hasEmail",
"@type": "@id",
"@isCollection": true,
},
name: {
"@id": "http://xmlns.com/foaf/0.1/name",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
},
},
Dom: {
"@id": "http://www.w3.org/2006/vcard/ns#Dom",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
Home: {
"@id": "http://www.w3.org/2006/vcard/ns#Home",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
ISDN: {
"@id": "http://www.w3.org/2006/vcard/ns#ISDN",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
Internet: {
"@id": "http://www.w3.org/2006/vcard/ns#Internet",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
Intl: {
"@id": "http://www.w3.org/2006/vcard/ns#Intl",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
Label: {
"@id": "http://www.w3.org/2006/vcard/ns#Label",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
Parcel: {
"@id": "http://www.w3.org/2006/vcard/ns#Parcel",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
Postal: {
"@id": "http://www.w3.org/2006/vcard/ns#Postal",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
Pref: {
"@id": "http://www.w3.org/2006/vcard/ns#Pref",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
Work: {
"@id": "http://www.w3.org/2006/vcard/ns#Work",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
X400: {
"@id": "http://www.w3.org/2006/vcard/ns#X400",
"@context": {
type: {
"@id": "@type",
},
value: {
"@id": "http://www.w3.org/2006/vcard/ns#value",
"@type": "@id",
},
},
},
},
successfulTypings:
'import {ContextDefinition} from "jsonld"\n\nexport interface SolidProfileShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n /**\r\n * Defines the node as a Person | Defines the node as a Person\r\n */\r\n type: ({\r\n "@id": "Person";\r\n } | {\r\n "@id": "Person2";\r\n })[];\r\n /**\r\n * The person\'s email.\r\n */\r\n hasEmail?: (EmailShape)[];\r\n /**\r\n * An alternate way to define a person\'s name\r\n */\r\n name?: string;\r\n}\r\n\r\nexport interface EmailShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n /**\r\n * The type of email.\r\n */\r\n type?: {\r\n "@id": "Dom";\r\n } | {\r\n "@id": "Home";\r\n } | {\r\n "@id": "ISDN";\r\n } | {\r\n "@id": "Internet";\r\n } | {\r\n "@id": "Intl";\r\n } | {\r\n "@id": "Label";\r\n } | {\r\n "@id": "Parcel";\r\n } | {\r\n "@id": "Postal";\r\n } | {\r\n "@id": "Pref";\r\n } | {\r\n "@id": "Work";\r\n } | {\r\n "@id": "X400";\r\n };\r\n /**\r\n * The value of an email as a mailto link (Example <mailto:jane@example.com>)\r\n */\r\n value: {\r\n "@id": string;\r\n };\r\n}\r\n\r\n',
'import {ContextDefinition} from "jsonld"\n\nexport interface SolidProfileShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n /**\n * Defines the node as a Person | Defines the node as a Person\n */\n type: ({\n "@id": "Person";\n } | {\n "@id": "Person2";\n })[];\n /**\n * The person\'s email.\n */\n hasEmail?: (EmailShape)[];\n /**\n * An alternate way to define a person\'s name\n */\n name?: string;\n}\n\nexport interface EmailShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n /**\n * The type of email.\n */\n type?: {\n "@id": "Dom";\n } | {\n "@id": "Home";\n } | {\n "@id": "ISDN";\n } | {\n "@id": "Internet";\n } | {\n "@id": "Intl";\n } | {\n "@id": "Label";\n } | {\n "@id": "Parcel";\n } | {\n "@id": "Postal";\n } | {\n "@id": "Pref";\n } | {\n "@id": "Work";\n } | {\n "@id": "X400";\n };\n /**\n * The value of an email as a mailto link (Example <mailto:jane@example.com>)\n */\n value: {\n "@id": string;\n };\n}\n\n',
};

@ -18,43 +18,73 @@ export const reusedPredicates: TestData = {
app:LawShape {
rdf:type [ app:Law ] ;
app:name xsd:string ;
app:name xsd:string *;
app:path IRI ;
}
app:VocabularyShape {
rdf:type [ app:Vocabulary ] ;
app:name xsd:string ;
app:path IRI ;
app:path IRI *;
}
`,
sampleTurtle: ``,
baseNode: "http://example.com/SampleParent",
successfulContext: {
type: { "@id": "@type" },
Document: "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#Document",
vocabulary: {
"@id":
"https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#vocabulary",
"@type": "@id",
"@container": "@set",
Document: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#Document",
"@context": {
type: {
"@id": "@type",
},
vocabulary: {
"@id":
"https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#vocabulary",
"@type": "@id",
"@isCollection": true,
},
law: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#law",
"@type": "@id",
},
},
},
Vocabulary:
"https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#Vocabulary",
name: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#name",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
path: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#path",
"@type": "@id",
Vocabulary: {
"@id":
"https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#Vocabulary",
"@context": {
type: {
"@id": "@type",
},
name: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#name",
"@type": "http://www.w3.org/2001/XMLSchema#string",
},
path: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#path",
"@type": "@id",
"@isCollection": true,
},
},
},
law: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#law",
"@type": "@id",
Law: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#Law",
"@context": {
type: {
"@id": "@type",
},
name: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#name",
"@type": "http://www.w3.org/2001/XMLSchema#string",
"@isCollection": true,
},
path: {
"@id": "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#path",
"@type": "@id",
},
},
},
Law: "https://www.forsakringskassan.se/vocabs/fk-sem-poc.ttl#Law",
},
successfulTypings:
'import {ContextDefinition} from "jsonld"\n\nexport interface DocumentShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n type: {\r\n "@id": "Document";\r\n };\r\n vocabulary?: (VocabularyShape)[];\r\n law: LawShape;\r\n}\r\n\r\nexport interface LawShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n type: {\r\n "@id": "Law";\r\n };\r\n name: string;\r\n path: {\r\n "@id": string;\r\n };\r\n}\r\n\r\nexport interface VocabularyShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n type: {\r\n "@id": "Vocabulary";\r\n };\r\n name: string;\r\n path: {\r\n "@id": string;\r\n };\r\n}\r\n\r\n',
'import {ContextDefinition} from "jsonld"\n\nexport interface DocumentShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Document";\n };\n vocabulary?: (VocabularyShape)[];\n law: LawShape;\n}\n\nexport interface LawShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Law";\n };\n name?: string[];\n path: {\n "@id": string;\n };\n}\n\nexport interface VocabularyShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Vocabulary";\n };\n name: string;\n path?: {\n "@id": string;\n }[];\n}\n\n',
};

@ -32,7 +32,7 @@ export const simple: TestData = {
givenName: {
"@id": "http://xmlns.com/foaf/0.1/givenName",
"@type": "http://www.w3.org/2001/XMLSchema#string",
"@container": "@set",
"@isCollection": true,
},
familyName: {
"@id": "http://xmlns.com/foaf/0.1/familyName",
@ -41,10 +41,10 @@ export const simple: TestData = {
phone: {
"@id": "http://xmlns.com/foaf/0.1/phone",
"@type": "@id",
"@container": "@set",
"@isCollection": true,
},
mbox: { "@id": "http://xmlns.com/foaf/0.1/mbox", "@type": "@id" },
},
successfulTypings:
'import {ContextDefinition} from "jsonld"\n\nexport interface EmployeeShape {\n "@id"?: string;\r\n "@context"?: ContextDefinition;\r\n givenName: string[];\r\n familyName: string;\r\n phone?: {\r\n "@id": string;\r\n }[];\r\n mbox: {\r\n "@id": string;\r\n };\r\n}\r\n\r\n',
'import {ContextDefinition} from "jsonld"\n\nexport interface EmployeeShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n givenName: string[];\n familyName: string;\n phone?: {\n "@id": string;\n }[];\n mbox: {\n "@id": string;\n };\n}\n\n',
};

@ -1,4 +1,4 @@
import type { ContextDefinition } from "jsonld";
import type { LdoJsonldContext } from "@ldo/jsonld-dataset-proxy";
import { activityPub } from "./activityPub";
import { circular } from "./circular";
import { profile } from "./profile";
@ -6,24 +6,24 @@ import { reducedProfile } from "./reducedProfile";
import { simple } from "./simple";
import { extendsSimple } from "./extendsSimple";
import { reusedPredicates } from "./reusedPredicates";
// import { oldExtends } from "./oldExtends";
import { oldExtends } from "./oldExtends";
export interface TestData {
name: string;
shexc: string;
sampleTurtle: string;
baseNode: string;
successfulContext: ContextDefinition;
successfulContext: LdoJsonldContext;
successfulTypings: string;
}
export const testData: TestData[] = [
simple,
circular,
// profile,
// reducedProfile,
// activityPub,
// extendsSimple,
// oldExtends,
// reusedPredicates,
profile,
reducedProfile,
activityPub,
extendsSimple,
oldExtends,
reusedPredicates,
];

@ -0,0 +1,35 @@
import type { ContextDefinition } from "jsonld";
export interface DocumentShape {
"@id"?: string;
"@context"?: ContextDefinition;
type: {
"@id": "Document";
};
vocabulary?: VocabularyShape[];
law: LawShape;
}
export interface LawShape {
"@id"?: string;
"@context"?: ContextDefinition;
type: {
"@id": "Law";
};
name?: string[];
path: {
"@id": string;
};
}
export interface VocabularyShape {
"@id"?: string;
"@context"?: ContextDefinition;
type: {
"@id": "Vocabulary";
};
name: string;
path?: {
"@id": string;
}[];
}

@ -21,7 +21,6 @@
"homepage": "https://github.com/o-development/ldobjects/tree/main/packages/traverser-shexj#readme",
"devDependencies": {
"@types/jest": "^27.0.3",
"@types/shexj": "^2.1.3",
"jest": "^27.4.5",
"ts-jest": "^27.1.2"
},

@ -1,8 +1,8 @@
import type { ShexJTraverserTypes } from ".";
import type { TraverserDefinition } from "@ldo/type-traverser";
import type { shapeExpr, valueSetValue } from "shexj";
import type { TraverserDefinitions } from "@ldo/type-traverser";
import type { shapeExpr, valueSetValue } from "./ShexJTypes";
export const ShexJTraverserDefinition: TraverserDefinition<ShexJTraverserTypes> =
export const ShexJTraverserDefinition: TraverserDefinitions<ShexJTraverserTypes> =
{
Schema: {
kind: "interface",
@ -29,7 +29,9 @@ export const ShexJTraverserDefinition: TraverserDefinition<ShexJTraverserTypes>
shapeExprOrRef: {
kind: "union",
selector: (item) =>
typeof item === "string" ? "shapeDeclRef" : "shapeExpr",
typeof item === "string" || item.type === "ShapeDecl"
? "shapeDeclRef"
: "shapeExpr",
},
ShapeOr: {
kind: "interface",
@ -55,7 +57,8 @@ export const ShexJTraverserDefinition: TraverserDefinition<ShexJTraverserTypes>
},
shapeDeclRef: {
kind: "union",
selector: () => "shapeDeclLabel",
selector: (value) =>
typeof value === "string" ? "shapeDeclLabel" : "ShapeDecl",
},
shapeDeclLabel: {
kind: "union",

@ -41,7 +41,7 @@ import type {
tripleExprRef,
valueSetValue,
Wildcard,
} from "shexj";
} from "./ShexJTypes";
import type { ValidateTraverserTypes } from "@ldo/type-traverser";
export type ShexJTraverserTypes = ValidateTraverserTypes<{
@ -110,7 +110,7 @@ export type ShexJTraverserTypes = ValidateTraverserTypes<{
shapeDeclRef: {
kind: "union";
type: shapeDeclRef;
typeNames: "shapeDeclLabel";
typeNames: "shapeDeclLabel" | "ShapeDecl";
};
shapeDeclLabel: {
kind: "union";

@ -0,0 +1,602 @@
// These type definitions are slightly modified to make up for the fact that the "extends" clause can loop back on itself
export {}; // only export specified symbols (strict-export-declare-modifiers)
/**
* Structure for expressing a Shape Expression schema.
* @see <a href="http://shex.io/shex-semantics/#dfn-shapes-schema">ShEx Schema definition</a>
*/
export interface Schema {
/**
* Mandatory type "Schema".
*/
type: "Schema";
/**
* JSON-LD <a href="https://www.w3.org/TR/json-ld11/#the-context">@context</a> for ShEx.
*/
"@context"?: "http://www.w3.org/ns/shex.jsonld" | undefined;
/**
* List of semantic actions to be executed when evaluating conformance.
*/
startActs?: SemAct[] | undefined; // +
/**
* Identifies default starting shape expression.
*/
start?: shapeExprOrRef | undefined;
/**
* List of ShEx schemas to <a href="http://shex.io/shex-semantics/#import">import</a> when processing this schema.
*/
imports?: IRIREF[] | undefined; // +
/**
* The list of {@link ShapeDecl}s defined in this schema. Each MUST include and {@link ShapeOr#id}.
*/
shapes?: ShapeDecl[] | undefined; // +
}
export interface semactsAndAnnotations {
/**
* List of semantic actions to be executed when evaluating conformance.
*/
semActs?: SemAct[] | undefined; // +;
/**
* List of {@link SemAct#predicate}/{@link SemAct#object} annotations.
*/
annotations?: Annotation[] | undefined; // +
}
/**
* A declaration for a shapeExpr with added inheritance constraints.
* @see <a href="http://shex.io/shex-semantics/#dfn-shapedecl">ShEx ShapeDecl definition</a>
*/
export interface ShapeDecl {
/**
* Mandatory type "ShapeDecl".
*/
type: "ShapeDecl";
/**
* The identifier is an <a href="https://www.w3.org/TR/json-ld11/#node-identifiers">IRI</a> or a <a href="https://www.w3.org/TR/json-ld11/#identifying-blank-nodes">BlankNode</a>
* as expressed in <a href="https://www.w3.org/TR/json-ld11/">JSON-LD 1.1</a>.
*/
id: shapeDeclLabel;
/**
* Whether this ShapeDecl participates in <a href="http://shex.io/shex-semantics/#dfn-inheritanceSubstitution">inheritance substitution</a>.
*/
abstract?: BOOL | undefined;
/**
* The list of {@link shapeExprOrRef}s that a neighborhood MUST conform to in order to conform to this ShapeDecl.
*/
restricts?: shapeExprOrRef[] | undefined; // +
/**
* The {@link shapeExpr} to which this neighborhood MUST also conform.
*/
shapeExpr: shapeExpr;
}
/**
* Union of shape expression types.
* @see <a href="http://shex.io/shex-semantics/#dfn-shapeexpr">ShEx shapeExpr definition</a>
*/
export type shapeExpr =
| ShapeOr
| ShapeAnd
| ShapeNot
| NodeConstraint
| Shape
| ShapeExternal;
/**
* Union of shapeExpr and shapeDeclRef.
* @see <a href="http://shex.io/shex-semantics/#dfn-shapeexpr">ShEx shapeExpr definition</a>
*/
export type shapeExprOrRef = shapeExpr | shapeDeclRef;
/**
* A non-exclusive choice of shape expressions; considered conformant if any of {@link #shapeExprs} conforms.
* @see <a href="http://shex.io/shex-semantics/#dfn-shapeor">ShEx shapeExpr definition</a>
*/
export interface ShapeOr {
/**
* Mandatory type "ShapeOr".
*/
type: "ShapeOr";
/**
* List of two or more {@link shapeExprOrRef}s in this disjunction.
*/
shapeExprs: shapeExprOrRef[]; // {2,}
}
/**
* A conjunction of shape expressions; considered conformant if each conjunct conforms.
* @see <a href="http://shex.io/shex-semantics/#dfn-shapeor">ShEx shapeExpr definition</a>
*/
export interface ShapeAnd {
/**
* Mandatory type "ShapeAnd".
*/
type: "ShapeAnd";
/**
* List of two or more {@link shapeExprOrRef}s in this conjunction.
*/
shapeExprs: shapeExprOrRef[]; // {2,}
}
/**
* A negated shape expressions; considered conformant if {@link #shapeExpr} is not conformant.
* @see <a href="http://shex.io/shex-semantics/#dfn-shapenot">ShEx shapeExpr definition</a>
*/
export interface ShapeNot {
/**
* Mandatory type "ShapeNot".
*/
type: "ShapeNot";
/**
* The {@link shapeExprOrRef} that must be non-conformant for this shape expression to be conformant.
*/
shapeExpr: shapeExprOrRef;
}
/**
* A shape expression not defined in this schema or in any imported schema. The definition of this shape expression is NOT defined by ShEx.
* @see <a href="http://shex.io/shex-semantics/#dfn-shapeexternal">ShEx shapeExpr definition</a>
*/
export interface ShapeExternal {
/**
* Mandatory type "ShapeExternal".
*/
type: "ShapeExternal";
}
/**
* A reference a shape expression.
* The reference is an <a href="https://www.w3.org/TR/json-ld11/#node-identifiers">IRI</a> or a <a href="https://www.w3.org/TR/json-ld11/#identifying-blank-nodes">BlankNode</a>
* as expressed in <a href="https://www.w3.org/TR/json-ld11/">JSON-LD 1.1</a>.
* This is modified to also include the possibility of ShapeDecl
*/
export type shapeDeclRef = shapeDeclLabel | ShapeDecl;
/**
* An identifier for a shape expression.
* The identifier is an <a href="https://www.w3.org/TR/json-ld11/#node-identifiers">IRI</a> or a <a href="https://www.w3.org/TR/json-ld11/#identifying-blank-nodes">BlankNode</a>
* as expressed in <a href="https://www.w3.org/TR/json-ld11/">JSON-LD 1.1</a>.
*/
export type shapeDeclLabel = IRIREF | BNODE;
export type nodeKind = "iri" | "bnode" | "nonliteral" | "literal";
/**
* A collection of constraints on <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-node">RDF Term</a>s expected for conformance.
* The identifier is an <a href="https://www.w3.org/TR/json-ld11/#node-identifiers">IRI</a> or a <a href="https://www.w3.org/TR/json-ld11/#identifying-blank-nodes">BlankNode</a>
* as expressed in <a href="https://www.w3.org/TR/json-ld11/">JSON-LD 1.1</a>.
*/
export interface NodeConstraint extends xsFacets, semactsAndAnnotations {
/**
* Mandatory type "NodeConstraint".
*/
type: "NodeConstraint";
/**
* Type of <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-node">RDF Term</a> expected for a conformant RDF node.
* @see <a href="http://shex.io/shex-semantics/#nodeKind">ShEx nodeKind definition</a>
*/
nodeKind?: nodeKind | undefined;
/**
* The <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri">RDF Literal datatype IRITerm</a> expected for a conformant RDF node.
* @see <a href="http://shex.io/shex-semantics/#datatype">ShEx datatype definition</a>
*/
datatype?: IRIREF | undefined;
/**
* The set of permissible values.
* @see <a href="http://shex.io/shex-semantics/#values">ShEx values definition</a>
*/
values?: valueSetValue[] | undefined;
}
/**
* The set of XML Schema Facets supported in ShEx; defers to {@link stringFacets} and {@link numericFacets}.
* @see <a href="http://shex.io/shex-semantics/#xs-string">ShEx String Facet Constraints</a> and <a href="http://shex.io/shex-semantics/#xs-numeric">ShEx Numeric Facet Constraints</a>.
*/
export interface xsFacets extends stringFacets, numericFacets {}
/**
* The set of <a href="https://www.w3.org/TR/xmlschema-2/#facets">XML Schema Facets</a> applying to <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form">lexical forms of RDF terms</a>.
* @see <a href="http://shex.io/shex-semantics/#xs-string">ShEx String Facet Constraints</a>.
*/
export interface stringFacets {
/**
* Expected length of the lexical form of an RDF Term.
*/
length?: INTEGER | undefined;
/**
* Expected minimum length of the lexical form of an RDF Term.
*/
minlength?: INTEGER | undefined;
/**
* Expected maximum length of the lexical form of an RDF Term.
*/
maxlength?: INTEGER | undefined;
/**
* Regular expression which the lexical forn of an RDF Term must match.
*/
pattern?: STRING | undefined;
/**
* Optional flags for the regular expression in {@link pattern}.
*/
flags?: STRING | undefined;
}
/**
* The set of <a href="https://www.w3.org/TR/xmlschema-2/#facets">XML Schema Facets</a> applying to <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-value-space">numeric values of RDF terms</a>.
* @see <a href="http://shex.io/shex-semantics/#xs-numeric">ShEx Numeric Facet Constraints</a>.
*/
export interface numericFacets {
/**
* Conformant <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a> has as a numeric value <= {@link mininclusive}.
*/
mininclusive?: numericLiteral | undefined;
/**
* Conformant <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a> has as a numeric value < {@link minexclusive}.
*/
minexclusive?: numericLiteral | undefined;
/**
* Conformant <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a> has as a numeric value > {@link maxinclusive}.
*/
maxinclusive?: numericLiteral | undefined;
/**
* Conformant <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a> has as a numeric value >= {@link maxexclusive}.
*/
maxexclusive?: numericLiteral | undefined;
/**
* Conformant <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a> has as a numeric value whose canonical form has {@link totaldigits} digits.
* @see <a href="http://shex.io/shex-semantics/#nodeSatisfies-totaldigits">ShEx totalDigits definition</a>
*/
totaldigits?: INTEGER | undefined;
/**
* Conformant <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a> has as a numeric value whose canonical form has {@link fractiondigits} digits.
* @see <a href="http://shex.io/shex-semantics/#nodeSatisfies-fractiondigits">ShEx fractionDigits definition</a>
*/
fractiondigits?: INTEGER | undefined;
}
/**
* Union of numeric types in ShEx used in {@link numericFacets}s.
*/
export type numericLiteral = INTEGER | DECIMAL | DOUBLE;
/**
* Union of numeric types that may appear in a value set.
* @see {@link NodeConstraint#values}.
*/
export type valueSetValue =
| objectValue
| IriStem
| IriStemRange
| LiteralStem
| LiteralStemRange
| Language
| LanguageStem
| LanguageStemRange;
/**
* JSON-LD representation of a URL or a Literal.
*/
export type objectValue = IRIREF | ObjectLiteral;
/**
* A <a href="https://www.w3.org/TR/json-ld11/#value-objects">JSON-LD Value Object</a> used to express an <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a>.
*/
export interface ObjectLiteral {
/**
* The <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form">lexical form</a> of an RDF Literal.
*/
value: STRING;
/**
* The <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag">language tag</a> of an RDF Literal.
*/
language?: STRING | undefined;
/**
* The <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-datatype">datatype</a> of an RDF Literal.
*/
type?: STRING | undefined;
}
/**
* Matchs an <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-iri">RDF IRI</a> starting with the character sequence in {@link stem}.
*/
export interface IriStem {
/**
* Mandatory type "IriStem".
*/
type: "IriStem";
/**
* substring of IRI to be matched.
*/
stem: IRIREF;
}
export type iriRangeStem = IRIREF | Wildcard;
export type iriRangeExclusion = IRIREF | IriStem;
/**
* Filters a matching <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-iri">RDF IRI</a>s through a list of exclusions.
* The initial match is made on an IRI stem per {@link IriStem} or a {@link Wildcard} to accept any IRI.
* The {@link exclusion}s are either specific IRIs or {@link IRIStem}s.
*/
export interface IriStemRange {
/**
* Mandatory type "IriStemRange".
*/
type: "IriStemRange";
/**
* substring of IRI to be matched or a {@link Wildcard} matching any IRI.
*/
stem: iriRangeStem;
/**
* IRIs or {@link IRIStem}s to exclude.
*/
exclusions: iriRangeExclusion[]; // +
}
/**
* Matchs an <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a> starting with the character sequence in {@link stem}.
*/
export interface LiteralStem {
/**
* Mandatory type "LiteralStem".
*/
type: "LiteralStem";
/**
* substring of Literal to be matched.
*/
stem: STRING;
}
export type literalRangeStem = string | Wildcard;
export type literalRangeExclusion = string | LiteralStem;
/**
* Filters a matching <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-literal">RDF Literal</a>s through a list of exclusions.
* The initial match is made on an Literal stem per {@link LiteralStem} or a {@link Wildcard} to accept any Literal.
* The {@link exclusion}s are either specific Literals or {@link LiteralStem}s.
*/
export interface LiteralStemRange {
/**
* Mandatory type "LiteralStemRange".
*/
type: "LiteralStemRange";
/**
* substring of Literal to be matched or a {@link Wildcard} matching any Literal.
*/
stem: literalRangeStem;
/**
* Literals or {@link LiteralStem}s to exclude.
*/
exclusions: literalRangeExclusion[]; // +
}
/**
* An <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag">RDF Language Tag</a>.
*/
export interface Language {
/**
* Mandatory type "Language".
*/
type: "Language";
/**
* The <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form">lexical representation</a> of an RDF Language Tag.
*/
languageTag: LANGTAG;
}
/**
* Matchs an <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-language-tag">RDF Language Tag</a> starting with the character sequence in {@link stem}.
*/
export interface LanguageStem {
/**
* Mandatory type "LanguageStem".
*/
type: "LanguageStem";
/**
* substring of Language Tag to be matched.
*/
stem: LANGTAG;
}
export type languageRangeStem = string | Wildcard;
export type languageRangeExclusion = string | LanguageStem;
/**
* Filters a matching <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-langugae-tag">RDF Language Tag</a>s through a list of exclusions.
* The initial match is made on an Language Tag stem per {@link Language TagStem} or a {@link Wildcard} to accept any Language Tag.
* The {@link exclusion}s are either specific Language Tags or {@link Language TagStem}s.
*/
export interface LanguageStemRange {
/**
* Mandatory type "LanguageStemRange".
*/
type: "LanguageStemRange";
/**
* substring of Language-Tag to be matched or a {@link Wildcard} matching any Language Tag.
*/
stem: languageRangeStem;
/**
* Language Tags or {@link LanguageStem}s to exclude.
*/
exclusions: languageRangeExclusion[]; // +
}
/**
* An empty object signifying than any item may be matched.
* This is used in {@link IriStemRange}, {@link LiteralStemRange} and {@link LanguageStemRange}.
*/
export interface Wildcard {
/**
* Mandatory type "Wildcard".
*/
type: "Wildcard";
}
/**
* A collection of {@link tripleExpr}s which must be matched by <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-triple">RDF Triple</a>s in conformance data.
*/
export interface Shape extends semactsAndAnnotations {
/**
* Mandatory type "Shape".
*/
type: "Shape";
/**
* Only the predicates mentioned in the {@link expression} may appear in conformant data.
*/
closed?: BOOL | undefined;
/**
* Permit extra triples with these predicates to appear in triples which don't match any {@link TripleConstraint}s mentioned in the {@link expression}.
*/
extra?: IRIREF[] | undefined;
/**
* List of one or more {@link shapeExprOrRef}s that a neighborhood must satisfy in order to conform to this shape.
*/
extends?: shapeExprOrRef[];
/**
* A tree of {@link tripleExpr}s specifying a set triples into or out of conformant <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-node">RDF Nodes</a>.
*/
expression?: tripleExprOrRef | undefined;
}
/**
* Union of triple expression types.
* @see <a href="http://shex.io/shex-semantics/#dfn-tripleexpr">ShEx tripleExpr definition</a>
*/
export type tripleExpr = EachOf | OneOf | TripleConstraint;
/**
* A tripleExpr or a label to one.
* @see <a href="http://shex.io/shex-semantics/#dfn-tripleexpr">ShEx tripleExpr definition</a>
*/
export type tripleExprOrRef = tripleExpr | tripleExprRef;
/**
* Common attributes appearing in every form of {@link tripleExpr}.
*/
export interface tripleExprBase extends semactsAndAnnotations {
/**
* Optional identifier for {@link tripleExpr}s for reference by {@link tripleExprRef}.
* The identifier is an <a href="https://www.w3.org/TR/json-ld11/#node-identifiers">IRI</a> or a <a href="https://www.w3.org/TR/json-ld11/#identifying-blank-nodes">BlankNode</a>
* as expressed in <a href="https://www.w3.org/TR/json-ld11/">JSON-LD 1.1</a>.
*/
id?: tripleExprLabel | undefined;
/**
* Minimum number of times matching triples must appear in conformant data.
*/
min?: INTEGER | undefined;
/**
* Maximum number of times matching triples must appear in conformant data.
*/
max?: INTEGER | undefined;
}
/**
* A list of of triple expressions; considered conformant if there is some conforming mapping of the examined triples to the {@link #tripleExprs}.
* @see <a href="http://shex.io/shex-semantics/#dfn-eachof">ShEx EachOf definition</a>
*/
export interface EachOf extends tripleExprBase {
/**
* Mandatory type "EachOf".
*/
type: "EachOf";
expressions: tripleExprOrRef[]; // {2,}
}
/**
* An exclusive choice of triple expressions; considered conformant if exactly one of {@link #shapeExprs} conforms.
* @see <a href="http://shex.io/shex-semantics/#dfn-oneof">ShEx OneOf definition</a>
*/
export interface OneOf extends tripleExprBase {
/**
* Mandatory type "OneOf".
*/
type: "OneOf";
expressions: tripleExprOrRef[]; // {2,}
}
/**
* A template matching a number of triples attached to the node being validated.
*/
export interface TripleConstraint extends tripleExprBase {
/**
* Mandatory type "TripleConstraint".
*/
type: "TripleConstraint";
/**
* If false, the TripleConstraint matches the a triple composed of a focus node, the {@link predicate} and an object matching the (optional) {@link shapeExpr}.
* If true, the TripleConstraint matches the a triple composed of a subject matching the (optional) {@link shapeExpr}, the {@link predicate} and focus node.
*/
inverse?: BOOL | undefined;
/**
* The predicate expected in a matching <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-triple">RDF Triple</a>.
*/
predicate: IRIREF;
/**
* A {@link shapeExpr} matching a conformant <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-triple">RDF Triple</a>s subject or object, depending on the value of {@link inverse}.
*/
valueExpr?: shapeExprOrRef | undefined;
}
/**
* A reference a triple expression.
* The reference is an <a href="https://www.w3.org/TR/json-ld11/#node-identifiers">IRI</a> or a <a href="https://www.w3.org/TR/json-ld11/#identifying-blank-nodes">BlankNode</a>
* as expressed in <a href="https://www.w3.org/TR/json-ld11/">JSON-LD 1.1</a>.
*/
export type tripleExprRef = tripleExprLabel;
/**
* An identifier for a triple expression.
* The identifier is an <a href="https://www.w3.org/TR/json-ld11/#node-identifiers">IRI</a> or a <a href="https://www.w3.org/TR/json-ld11/#identifying-blank-nodes">BlankNode</a>
* as expressed in <a href="https://www.w3.org/TR/json-ld11/">JSON-LD 1.1</a>.
*/
export type tripleExprLabel = IRIREF | BNODE;
/**
* An extension point for Shape Expressions allowing external code to be invoked during validation.
*/
export interface SemAct {
/**
* Mandatory type "SemAct".
*/
type: "SemAct";
/*
* Identifier of the language for this semantic action.
*/
name: IRIREF;
/*
* The actual code to be interpreted/executed.
* This may be kept separate from the ShEx containing the schema by including only {@link name}s in the schema.
*/
code?: STRING | undefined;
}
/**
* An assertion about some part of a ShEx schema which has no affect on conformance checking.
* These can be useful for documentation, provenance tracking, form generation, etch.
*/
export interface Annotation {
/**
* Mandatory type "Annotation".
*/
type: "Annotation";
/**
* The <a href="https://www.w3.org/TR/json-ld11/#node-identifiers">RDF Predicate</a> of the annotation.
*/
predicate: IRI;
/**
* A value for the above {@link predicate}.
*/
object: objectValue;
}
export type IRIREF = string;
export type BNODE = string;
export type INTEGER = number;
export type STRING = string;
export type DECIMAL = number;
export type DOUBLE = number;
export type LANGTAG = string;
export type BOOL = boolean;
export type IRI = string;

@ -1,9 +1,18 @@
export * from "./traverser/TraverserTypes";
export * from "./UtilTypes";
export * from "./traverser/TraverserDefinition";
export * from "./transformer/TransformerReturnTypes";
export * from "./transformer/TransformerReturnTypesDefaults";
export * from "./traverser/Traverser";
export * from "./transformer/Transformer";
export * from "./visitor/Visitor";
export * from "./visitor/Visitors";
export * from "./instanceGraph/InstanceGraph";
export * from "./instanceGraph/ReverseRelationshipTypes";
export * from "./instanceGraph/nodes/InstanceNode";
export * from "./instanceGraph/nodes/InterfaceInstanceNode";
export * from "./instanceGraph/nodes/PrimitiveInstanceNode";
export * from "./instanceGraph/nodes/UnionInstanceNode";

@ -2,7 +2,7 @@
import type { TraverserDefinition } from "../..";
import type { ParentIdentifiers } from "../../instanceGraph/ReverseRelationshipTypes";
import type { TraverserTypes } from "../../traverser/TraverserTypes";
import type { InstanceGraph } from "../instanceGraph";
import type { InstanceGraph } from "../InstanceGraph";
import type { InstanceNodeFor } from "./createInstanceNodeFor";
export abstract class InstanceNode<

@ -1,22 +1,24 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { ApplyArrayAndUndefined } from "../../transformer/TransformerReturnTypesDefaults";
import type {
InterfaceType,
TraverserTypes,
} from "../../traverser/TraverserTypes";
import type { InstanceGraph } from "../instanceGraph";
import type { InstanceGraph } from "../InstanceGraph";
import type { InstanceNodeFor } from "./createInstanceNodeFor";
import { InstanceNode } from "./InstanceNode";
/**
* Helper Function
*/
type InterfacePropertyNode<
export type InterfacePropertyNode<
Types extends TraverserTypes<any>,
Type extends InterfaceType<keyof Types>,
PropertyName extends keyof Type["properties"],
> = Type["type"][PropertyName] extends Array<any>
? InstanceNodeFor<Types, Type["properties"][PropertyName]>[]
: InstanceNodeFor<Types, Type["properties"][PropertyName]>;
> = ApplyArrayAndUndefined<
Type["type"][PropertyName],
InstanceNodeFor<Types, Type["properties"][PropertyName]>
>;
/**
* Class

Loading…
Cancel
Save