Merge pull request #63 from o-development/feat/and-or-shex

Shape AND and Shape OR support
main
jaxoncreed 9 months ago committed by GitHub
commit 5f4d4559d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 44
      packages/schema-converter-shex/src/typing/ShexJTypingTransformer.ts
  2. 2
      packages/schema-converter-shex/test/context.test.ts
  3. 47
      packages/schema-converter-shex/test/testData/andSimple.ts
  4. 53
      packages/schema-converter-shex/test/testData/orSimple.ts
  5. 4
      packages/schema-converter-shex/test/testData/testData.ts
  6. 3
      packages/schema-converter-shex/test/typing.test.ts

@ -45,6 +45,18 @@ export const ShexJTypingTransformer = ShexJTraverser.createTransformer<
NodeConstraint: { NodeConstraint: {
return: dom.Type; return: dom.Type;
}; };
ShapeOr: {
return: dom.UnionType;
};
ShapeAnd: {
return: dom.IntersectionType;
};
ShapeNot: {
return: never;
};
ShapeExternal: {
return: never;
};
}, },
ShexJTypeTransformerContext ShexJTypeTransformerContext
>({ >({
@ -82,7 +94,7 @@ export const ShexJTypingTransformer = ShexJTraverser.createTransformer<
} else { } else {
// TODO: Handle other items // TODO: Handle other items
throw new Error( throw new Error(
"Cannot handle ShapeOr, ShapeAnd, ShapeNot, ShapeExternal, or NodeConstraint", "Cannot handle ShapeOr, ShapeAnd, ShapeNot, ShapeExternal, or NodeConstraint direcly on ShapeDecl.",
); );
} }
}, },
@ -330,4 +342,34 @@ export const ShexJTypingTransformer = ShexJTraverser.createTransformer<
return dom.type.undefined; return dom.type.undefined;
}, },
}, },
ShapeOr: {
transformer: async (shapeOr, getTransformedChildren) => {
const transformedChildren = await getTransformedChildren();
const validTypes: dom.Type[] = [];
transformedChildren.shapeExprs.forEach((type) => {
if (typeof type === "object") validTypes.push(type);
});
return dom.create.union(validTypes);
},
},
ShapeAnd: {
transformer: async (shapeAnd, getTransformedChildren) => {
const transformedChildren = await getTransformedChildren();
const validTypes: dom.Type[] = [];
transformedChildren.shapeExprs.forEach((type) => {
if (typeof type === "object") validTypes.push(type);
});
return dom.create.intersection(validTypes);
},
},
ShapeNot: {
transformer: async () => {
throw new Error("ShapeNot is not supported");
},
},
ShapeExternal: {
transformer: async () => {
throw new Error("ShapeExternal is not supported");
},
},
}); });

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

@ -0,0 +1,47 @@
import type { TestData } from "./testData";
/**
* AND SIMPLE
*/
export const andSimple: TestData = {
name: "andSimple",
shexc: `
PREFIX ex: <https://example.com/>
ex:MediaContainerShape {
a [ ex:MediaContainer ];
ex:videoImage (@ex:VideoShape AND @ex:ImageShape) ;
}
ex:VideoShape {
a [ ex:Video ];
}
ex:ImageShape {
a [ ex:Image ];
}
`,
sampleTurtle: "",
baseNode: "",
successfulContext: {
MediaContainer: {
"@id": "https://example.com/MediaContainer",
"@context": {
type: {
"@id": "@type",
},
videoImage: {
"@id": "https://example.com/videoImage",
"@type": "@id",
},
},
},
type: {
"@id": "@type",
},
Video: "https://example.com/Video",
Image: "https://example.com/Image",
},
successfulTypings:
'import {ContextDefinition} from "jsonld"\n\nexport interface MediaContainerShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "MediaContainer";\n };\n videoImage: VideoShape & ImageShape;\n}\n\nexport interface VideoShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Video";\n };\n}\n\nexport interface ImageShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Image";\n };\n}\n\n',
};

@ -0,0 +1,53 @@
import type { TestData } from "./testData";
/**
* OR SIMPLE
*/
export const orSimple: TestData = {
name: "orSimple",
shexc: `
PREFIX ex: <https://example.com/>
ex:MediaContainerShape {
a [ ex:MediaContainer ];
ex:primaryMedia (@ex:VideoShape OR @ex:ImageShape) ;
ex:media (@ex:VideoShape OR @ex:ImageShape) * ;
}
ex:VideoShape {
a [ ex:Video ];
}
ex:ImageShape {
a [ ex:Image ];
}
`,
sampleTurtle: "",
baseNode: "",
successfulContext: {
MediaContainer: {
"@id": "https://example.com/MediaContainer",
"@context": {
type: {
"@id": "@type",
},
primaryMedia: {
"@id": "https://example.com/primaryMedia",
"@type": "@id",
},
media: {
"@id": "https://example.com/media",
"@type": "@id",
"@isCollection": true,
},
},
},
type: {
"@id": "@type",
},
Video: "https://example.com/Video",
Image: "https://example.com/Image",
},
successfulTypings:
'import {ContextDefinition} from "jsonld"\n\nexport interface MediaContainerShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "MediaContainer";\n };\n primaryMedia: VideoShape | ImageShape;\n media?: (VideoShape | ImageShape)[];\n}\n\nexport interface VideoShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Video";\n };\n}\n\nexport interface ImageShape {\n "@id"?: string;\n "@context"?: ContextDefinition;\n type: {\n "@id": "Image";\n };\n}\n\n',
};

@ -7,6 +7,8 @@ import { simple } from "./simple";
import { extendsSimple } from "./extendsSimple"; import { extendsSimple } from "./extendsSimple";
import { reusedPredicates } from "./reusedPredicates"; import { reusedPredicates } from "./reusedPredicates";
import { oldExtends } from "./oldExtends"; import { oldExtends } from "./oldExtends";
import { orSimple } from "./orSimple";
import { andSimple } from "./andSimple";
export interface TestData { export interface TestData {
name: string; name: string;
@ -26,4 +28,6 @@ export const testData: TestData[] = [
extendsSimple, extendsSimple,
oldExtends, oldExtends,
reusedPredicates, reusedPredicates,
orSimple,
andSimple,
]; ];

@ -9,7 +9,10 @@ describe("typing", () => {
const schema: Schema = parser const schema: Schema = parser
.construct("https://ldo.js.org/") .construct("https://ldo.js.org/")
.parse(shexc); .parse(shexc);
// console.log("SCHEMA:", JSON.stringify(schema, null, 2));
const [typings] = await shexjToTyping(schema); const [typings] = await shexjToTyping(schema);
// console.log(typings.typingsString);
// console.log(JSON.stringify(typings.typingsString));
expect(typings.typingsString).toBe(successfulTypings); expect(typings.typingsString).toBe(successfulTypings);
}); });
}); });

Loading…
Cancel
Save