|
|
|
@ -2,23 +2,34 @@ import type { ObjectLiteral } from "@ldo/traverser-shexj"; |
|
|
|
|
import ShexJTraverser from "@ldo/traverser-shexj"; |
|
|
|
|
|
|
|
|
|
export interface CompactShape { |
|
|
|
|
schemaUri: string; |
|
|
|
|
iri: string; |
|
|
|
|
predicates: CompactSchemaProperty[]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type NodeConstraintRet = { |
|
|
|
|
type CompactSchemaValue = { |
|
|
|
|
literals?: number[] | string[] | boolean; |
|
|
|
|
type: "number" | "string" | "boolean" | "literal"; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
interface CompactSchemaProperty { |
|
|
|
|
type: "number" | "string" | "boolean" | "nested" | "literal"; |
|
|
|
|
/** Type of property. */ |
|
|
|
|
type: "number" | "string" | "boolean" | "literal" | "nested" | "eitherOf"; |
|
|
|
|
/** The RDF predicate URI. */ |
|
|
|
|
predicateUri: string; |
|
|
|
|
/** The alias of the `predicateUri` when serialized to a JSON object. */ |
|
|
|
|
readablePredicate: string; |
|
|
|
|
/** The required literal value(s), if type is `literal`. Others are allowed, if `extra` is true. */ |
|
|
|
|
literalValue?: number | string | boolean | number[] | string[]; |
|
|
|
|
/** If type is `nested`, the shape or its IRI. */ |
|
|
|
|
nestedSchema?: string | CompactShape; |
|
|
|
|
/** Maximum allowed number of values. `-1` means infinite. */ |
|
|
|
|
maxCardinality: number; |
|
|
|
|
/** Minimum required number of values */ |
|
|
|
|
minCardinality: number; |
|
|
|
|
/** If type is `eitherOf`, specifies multiple allowed types (CompactSchemaValue, shapes, or shape IRI). */ |
|
|
|
|
eitherOf?: (CompactSchemaValue | CompactShape | string)[]; |
|
|
|
|
/** If other (additional) values are permitted. Useful for literals. */ |
|
|
|
|
extra?: boolean; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export const ShexJSchemaTransformerCompact = ShexJTraverser.createTransformer< |
|
|
|
@ -28,15 +39,14 @@ export const ShexJSchemaTransformerCompact = ShexJTraverser.createTransformer< |
|
|
|
|
Shape: { return: CompactShape }; |
|
|
|
|
EachOf: { return: CompactShape }; |
|
|
|
|
TripleConstraint: { return: CompactSchemaProperty }; |
|
|
|
|
NodeConstraint: { return: NodeConstraintRet }; |
|
|
|
|
ShapeOr: { return: never }; |
|
|
|
|
NodeConstraint: { return: CompactSchemaValue }; |
|
|
|
|
ShapeOr: { return: (CompactSchemaValue | CompactShape | string)[] }; |
|
|
|
|
ShapeAnd: { return: never }; |
|
|
|
|
ShapeNot: { return: never }; |
|
|
|
|
ShapeExternal: { return: never }; |
|
|
|
|
}, |
|
|
|
|
null |
|
|
|
|
>({ |
|
|
|
|
// Transformer from Schema to interfaces
|
|
|
|
|
Schema: { |
|
|
|
|
transformer: async (_schema, getTransformedChildren) => { |
|
|
|
|
const transformedChildren = await getTransformedChildren(); |
|
|
|
@ -45,35 +55,41 @@ export const ShexJSchemaTransformerCompact = ShexJTraverser.createTransformer< |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from ShapeDecl to interface
|
|
|
|
|
ShapeDecl: { |
|
|
|
|
transformer: async (shapeDecl, getTransformedChildren) => { |
|
|
|
|
const schema = await getTransformedChildren(); |
|
|
|
|
const shape = schema.shapeExpr as CompactShape; |
|
|
|
|
|
|
|
|
|
return { ...schema.shapeExpr, schemaUri: shapeDecl.id } as CompactShape; |
|
|
|
|
return { ...shape, iri: shapeDecl.id } as CompactShape; |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from Shape to interface
|
|
|
|
|
Shape: { |
|
|
|
|
transformer: async (_shape, getTransformedChildren, setReturnPointer) => { |
|
|
|
|
transformer: async (_shape, getTransformedChildren) => { |
|
|
|
|
// TODO: We don't handles those
|
|
|
|
|
_shape.closed; |
|
|
|
|
_shape.extra; |
|
|
|
|
|
|
|
|
|
const transformedChildren = await getTransformedChildren(); |
|
|
|
|
// Return prelim or expression or assign things?
|
|
|
|
|
return transformedChildren.expression as CompactShape; |
|
|
|
|
const compactShape = transformedChildren.expression as CompactShape; |
|
|
|
|
|
|
|
|
|
for (const extra of _shape.extra || []) { |
|
|
|
|
const extraPredicate = compactShape.predicates.find( |
|
|
|
|
(p) => p.predicateUri === extra, |
|
|
|
|
); |
|
|
|
|
if (extraPredicate) extraPredicate.extra = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return compactShape; |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from EachOf to object type. EachOf contains the `expressions` array of properties (TripleConstraint)
|
|
|
|
|
// EachOf contains the `expressions` array of properties (TripleConstraint)
|
|
|
|
|
EachOf: { |
|
|
|
|
transformer: async (eachOf, getTransformedChildren, setReturnPointer) => { |
|
|
|
|
transformer: async (eachOf, getTransformedChildren) => { |
|
|
|
|
const transformedChildren = await getTransformedChildren(); |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
schemaUri: "", |
|
|
|
|
iri: "", |
|
|
|
|
predicates: transformedChildren.expressions.map( |
|
|
|
|
// We disregard cases where properties are referenced (strings)
|
|
|
|
|
// or where they consist of Unions or Intersections (not supported).
|
|
|
|
@ -83,7 +99,6 @@ export const ShexJSchemaTransformerCompact = ShexJTraverser.createTransformer< |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from triple constraints to type properties.
|
|
|
|
|
TripleConstraint: { |
|
|
|
|
transformer: async ( |
|
|
|
|
tripleConstraint, |
|
|
|
@ -116,10 +131,16 @@ export const ShexJSchemaTransformerCompact = ShexJTraverser.createTransformer< |
|
|
|
|
nestedSchema: transformedChildren.valueExpr as CompactShape, |
|
|
|
|
...commonProperties, |
|
|
|
|
} satisfies CompactSchemaProperty; |
|
|
|
|
} else if (Array.isArray(transformedChildren.valueExpr)) { |
|
|
|
|
return { |
|
|
|
|
type: "eitherOf", |
|
|
|
|
eitherOf: transformedChildren.valueExpr, |
|
|
|
|
...commonProperties, |
|
|
|
|
}; |
|
|
|
|
} else { |
|
|
|
|
// type or literal
|
|
|
|
|
const nodeConstraint = |
|
|
|
|
transformedChildren.valueExpr as NodeConstraintRet; |
|
|
|
|
transformedChildren.valueExpr as CompactSchemaValue; |
|
|
|
|
return { |
|
|
|
|
type: nodeConstraint.type, |
|
|
|
|
literalValue: nodeConstraint.literals, |
|
|
|
@ -129,7 +150,6 @@ export const ShexJSchemaTransformerCompact = ShexJTraverser.createTransformer< |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from node constraint to type
|
|
|
|
|
NodeConstraint: { |
|
|
|
|
transformer: async (nodeConstraint) => { |
|
|
|
|
if (nodeConstraint.datatype) { |
|
|
|
@ -179,28 +199,34 @@ export const ShexJSchemaTransformerCompact = ShexJTraverser.createTransformer< |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from ShapeOr to union type
|
|
|
|
|
// Transformer from ShapeOr
|
|
|
|
|
ShapeOr: { |
|
|
|
|
transformer: async () => { |
|
|
|
|
throw new Error("ShapeOr not supported (compact)"); |
|
|
|
|
transformer: async (shapeOr, getTransformedChildren) => { |
|
|
|
|
const tc = await getTransformedChildren(); |
|
|
|
|
// Either a shape IRI, a nested shape or a node CompactSchemaValue (node constraint).
|
|
|
|
|
return (Array.isArray(tc) ? tc : [tc]) as ( |
|
|
|
|
| string |
|
|
|
|
| CompactShape |
|
|
|
|
| CompactSchemaValue |
|
|
|
|
)[]; |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from ShapeAnd to intersection type
|
|
|
|
|
// Transformer from ShapeAnd
|
|
|
|
|
ShapeAnd: { |
|
|
|
|
transformer: async () => { |
|
|
|
|
throw new Error("ShapeAnd not supported (compact)"); |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from ShapeNot to type - not supported.
|
|
|
|
|
// Transformer from ShapeNot - not supported.
|
|
|
|
|
ShapeNot: { |
|
|
|
|
transformer: async () => { |
|
|
|
|
throw new Error("ShapeNot not supported (compact)"); |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Transformer from ShapeExternal to type - not supported.
|
|
|
|
|
// Transformer from ShapeExternal - not supported.
|
|
|
|
|
ShapeExternal: { |
|
|
|
|
transformer: async () => { |
|
|
|
|
throw new Error("ShapeExternal not supported (compact)"); |
|
|
|
|