|
| 1 | +import { getSchema } from "@hyperjump/json-schema/experimental"; |
| 2 | +import * as Schema from "@hyperjump/browser"; |
| 3 | +import * as Instance from "@hyperjump/json-schema/instance/experimental"; |
| 4 | +import { getErrors } from "../error-handling.js"; |
| 5 | + |
| 6 | +/** |
| 7 | + * @import { ErrorHandler, ErrorObject, NormalizedOutput } from "../index.d.ts" |
| 8 | + */ |
| 9 | + |
| 10 | +/** @type ErrorHandler */ |
| 11 | +const anyOf = async (normalizedErrors, instance, localization) => { |
| 12 | + /** @type ErrorObject[] */ |
| 13 | + const errors = []; |
| 14 | + |
| 15 | + if (normalizedErrors["https://json-schema.org/keyword/anyOf"]) { |
| 16 | + for (const schemaLocation in normalizedErrors["https://json-schema.org/keyword/anyOf"]) { |
| 17 | + /** @type NormalizedOutput[] */ |
| 18 | + const alternatives = []; |
| 19 | + const allAlternatives = /** @type NormalizedOutput[] */ (normalizedErrors["https://json-schema.org/keyword/anyOf"][schemaLocation]); |
| 20 | + for (const alternative of allAlternatives) { |
| 21 | + if (Object.values(alternative[Instance.uri(instance)]["https://json-schema.org/keyword/type"]).every((valid) => valid)) { |
| 22 | + alternatives.push(alternative); |
| 23 | + } |
| 24 | + } |
| 25 | + // case 1 where no. alternative matched the type of the instance. |
| 26 | + if (alternatives.length === 0) { |
| 27 | + /** @type Set<string> */ |
| 28 | + const expectedTypes = new Set(); |
| 29 | + for (const alternative of allAlternatives) { |
| 30 | + for (const instanceLocation in alternative) { |
| 31 | + if (instanceLocation === Instance.uri(instance)) { |
| 32 | + for (const schemaLocation in alternative[instanceLocation]["https://json-schema.org/keyword/type"]) { |
| 33 | + const keyword = await getSchema(schemaLocation); |
| 34 | + const expectedType = /** @type string */ (Schema.value(keyword)); |
| 35 | + expectedTypes.add(expectedType); |
| 36 | + } |
| 37 | + } |
| 38 | + } |
| 39 | + } |
| 40 | + errors.push({ |
| 41 | + message: localization.getTypeErrorMessage([...expectedTypes], Instance.typeOf(instance)), |
| 42 | + instanceLocation: Instance.uri(instance), |
| 43 | + schemaLocation: schemaLocation |
| 44 | + }); |
| 45 | + } else if (alternatives.length === 1) { // case 2 when only one type match |
| 46 | + return getErrors(alternatives[0], instance, localization); |
| 47 | + } else if (instance.type === "object") { |
| 48 | + let targetAlternativeIndex = -1; |
| 49 | + for (const alternative of alternatives) { |
| 50 | + targetAlternativeIndex++; |
| 51 | + for (const instanceLocation in alternative) { |
| 52 | + if (instanceLocation !== "#") { |
| 53 | + return getErrors(alternatives[targetAlternativeIndex], instance, localization); |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + return errors; |
| 62 | +}; |
| 63 | + |
| 64 | +export default anyOf; |
0 commit comments