|
import { compile, getSchema } from "@hyperjump/json-schema/experimental"; |
|
import { toAbsoluteIri } from "@hyperjump/uri"; |
|
|
|
|
|
export const foo = async (schemaId, instance) => { |
|
const schemaDocument = await getSchema(schemaId); |
|
const { ast, schemaUri } = await compile(schemaDocument); |
|
|
|
return evaluateSchema(schemaUri, instance, ast, {}); |
|
}; |
|
|
|
const evaluateSchema = (schemaUri, instance, ast, dynamicAnchors) => { |
|
let schemaEvaluationResult; |
|
|
|
if (typeof ast[schemaUri] !== "boolean") { |
|
dynamicAnchors = { ...ast.metaData[toAbsoluteIri(schemaUri)].dynamicAnchors, ...dynamicAnchors }; |
|
|
|
for (const [keywordId, , keywordValue] of ast[schemaUri]) { |
|
const handler = getKeywordHandler(keywordId); |
|
const keywordEvaluationResult = handler(keywordValue, instance, ast, dynamicAnchors); |
|
// schemaEvaluationResult = ... |
|
} |
|
} |
|
|
|
return schemaEvaluationResult; |
|
}; |
|
|
|
const getKeywordHandler = (keywordId) => { |
|
const normalizedKeywordId = toAbsoluteIri(keywordId); |
|
if (!(normalizedKeywordId in keywordHandlers)) { |
|
throw Error(`No handler found for Keyword: ${normalizedKeywordId}`); |
|
} |
|
|
|
return keywordHandlers[normalizedKeywordId]; |
|
}; |
|
|
|
const noopKeywordHandler = () => {}; |
|
const keywordHandlers = { |
|
// Core |
|
"https://json-schema.org/keyword/comment": noopKeywordHandler, |
|
"https://json-schema.org/keyword/definitions": noopKeywordHandler, |
|
"https://json-schema.org/keyword/dynamicRef": (dynamicAnchor, instance, ast, dynamicAnchors) => { |
|
if (!(dynamicAnchor in dynamicAnchors)) { |
|
throw Error(`No dynamic anchor found for "${dynamicAnchor}"`); |
|
} |
|
return evaluateSchema(dynamicAnchors[dynamicAnchor], instance, ast, dynamicAnchors); |
|
}, |
|
"https://json-schema.org/keyword/draft-2020-12/dynamicRef": ([id, fragment, ref], instance, ast, dynamicAnchors) => { |
|
if (fragment in ast.metaData[id].dynamicAnchors) { |
|
dynamicAnchors = { ...ast.metaData[id].dynamicAnchors, ...dynamicAnchors }; |
|
return evaluateSchema(dynamicAnchors[fragment], instance, ast, dynamicAnchors); |
|
} else { |
|
return evaluateSchema(ref, instance, ast, dynamicAnchors); |
|
} |
|
}, |
|
"https://json-schema.org/keyword/ref": evaluateSchema, |
|
|
|
// Applicators |
|
"https://json-schema.org/keyword/draft-04/additionalItems": ([numberOfItems, additionalItems], instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/additionalProperties": ([isDefinedProperty, additionalProperties], instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/allOf": (allOf, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/anyOf": (anyOf, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/draft-06/contains": (contains, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/contains": ({ contains, minContains, maxContains }, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/draft-04/dependencies": (dependencies, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/dependentSchemas": (dependentSchemas, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/if": (ifSchema, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/then": ([ifSchema, thenSchema], instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/else": ([ifSchema, elseSchema], instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/draft-04/items": (items, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/items": ([numberOfPrefixItems, items], instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/not": (not, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/oneOf": (oneOf, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/patternProperties": (patternProperties, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/prefixItems": (prefixItems, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/properties": (properties, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/propertyDependencies": (propertyDependencies, instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/propertyNames": (propertyNames, instance, ast, dynamicAnchors) => { |
|
}, |
|
|
|
// Unevaluated |
|
"https://json-schema.org/keyword/unevaluatedItems": ([parentSchema, unevaluatedItems], instance, ast, dynamicAnchors) => { |
|
}, |
|
"https://json-schema.org/keyword/unevaluatedProperties": ([parentSchema, unevaluatedProperties], instance, ast, dynamicAnchors) => { |
|
}, |
|
|
|
// Validators |
|
"https://json-schema.org/keyword/const": (constValue, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/dependentRequired": (dependentRequired, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/enum": (enumValues, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/draft-04/exclusiveMaximum": (exclusiveMaximum, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/exclusiveMaximum": (exclusiveMaximum, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/draft-04/exclusiveMinimum": (exclusiveMinimum, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/exclusiveMinimum": (exclusiveMinimum, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/maxItems": (maxItems, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/maxLength": (maxLength, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/maxProperties": (maxProperties, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/draft-04/maximum": (maximum, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/maximum": (maximum, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/minItems": (minItems, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/minLength": (minLength, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/minProperties": (minProperties, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/draft-04/minimum": (maximum, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/minimum": (minimum, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/multipleOf": (multipleOf, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/pattern": (pattern, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/required": (required, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/type": (type, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/uniqueItems": (uniqueItems, instance) => { |
|
}, |
|
|
|
// Meta-data |
|
"https://json-schema.org/keyword/default": (defaultValue, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/deprecated": (deprecated, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/description": (description, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/examples": (examples, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/readOnly": (examples, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/title": (title, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/writeOnly": (writeOnly, instance) => { |
|
}, |
|
|
|
// Format Annotation |
|
"https://json-schema.org/keyword/format": (format, instance) => { |
|
}, |
|
|
|
// Format Assertion |
|
"https://json-schema.org/keyword/format-assertion": (format, instance) => { |
|
}, |
|
|
|
// Content |
|
"https://json-schema.org/keyword/contentEncoding": (contentEncoding, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/contentMediaType": (contentMediaType, instance) => { |
|
}, |
|
"https://json-schema.org/keyword/contentSchema": (contentSchema, instance) => { |
|
}, |
|
|
|
// Unknown keywords |
|
"https://json-schema.org/keyword/unknown": (keywordValue, instance) => { |
|
} |
|
}; |
|
|
|
// Provide a way for users to add support for additional keywords |
|
export const addKeywordHandler(keywordId, keywordHandler) => { |
|
keywordHandlers[keywordId] = keywordHandler; |
|
} |
@AgniveshChaubey For filling default values, I would expect that your keyword handlers return the instance with any defaults applied as appropriate for each of the keyword's semantics. You should just need to implement the applicators (including the "unevaluated" keywords) and the
default
keyword and everything else should be a no-op (just pass back the instance unchanged).