83 lines
2.5 KiB
TypeScript
83 lines
2.5 KiB
TypeScript
![]() |
import getTypeOf, { JSType } from "./getTypeOf";
|
||
|
import { errorOrPromise } from "./utils/filter";
|
||
|
import flattenArray from "./utils/flattenArray";
|
||
|
import { JsonSchema, JsonPointer, JsonError, isJsonError } from "./types";
|
||
|
import { Draft } from "./draft";
|
||
|
import equal from "fast-deep-equal";
|
||
|
|
||
|
function getJsonSchemaType(value: unknown, expectedType: string | string[]): JSType | "integer" {
|
||
|
const jsType = getTypeOf(value);
|
||
|
if (
|
||
|
jsType === "number" &&
|
||
|
(expectedType === "integer" ||
|
||
|
(Array.isArray(expectedType) && expectedType.includes("integer")))
|
||
|
) {
|
||
|
return Number.isInteger(value) || isNaN(value as any) ? "integer" : "number";
|
||
|
}
|
||
|
return jsType;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Validates data with json schema
|
||
|
*
|
||
|
* @param draft - validator
|
||
|
* @param value - value to validate
|
||
|
* @param [schema] - json schema, defaults to rootSchema
|
||
|
* @param [pointer] - json pointer pointing to value (used for error-messages only)
|
||
|
* @return list of errors or empty
|
||
|
*/
|
||
|
export default function validate(
|
||
|
draft: Draft,
|
||
|
value: unknown,
|
||
|
schema: JsonSchema = draft.rootSchema,
|
||
|
pointer: JsonPointer = "#"
|
||
|
): Array<JsonError> {
|
||
|
schema = draft.resolveRef(schema);
|
||
|
|
||
|
// @draft >= 07
|
||
|
if (getTypeOf(schema) === "boolean") {
|
||
|
if (schema) {
|
||
|
return [];
|
||
|
}
|
||
|
return [draft.errors.invalidDataError({ pointer, schema, value })];
|
||
|
}
|
||
|
|
||
|
if (isJsonError(schema)) {
|
||
|
return [schema as JsonError];
|
||
|
}
|
||
|
|
||
|
// @draft >= 6 const
|
||
|
if (schema.const !== undefined) {
|
||
|
if (equal(schema.const, value)) {
|
||
|
return [];
|
||
|
}
|
||
|
return [draft.errors.constError({ pointer, schema, value, expected: schema.const })];
|
||
|
}
|
||
|
|
||
|
const receivedType = getJsonSchemaType(value, schema.type);
|
||
|
const expectedType = schema.type || receivedType;
|
||
|
|
||
|
if (
|
||
|
receivedType !== expectedType &&
|
||
|
(!Array.isArray(expectedType) || !expectedType.includes(receivedType))
|
||
|
) {
|
||
|
return [
|
||
|
draft.errors.typeError({
|
||
|
pointer,
|
||
|
schema,
|
||
|
value,
|
||
|
received: receivedType,
|
||
|
expected: expectedType
|
||
|
})
|
||
|
];
|
||
|
}
|
||
|
|
||
|
if (draft.validateType[receivedType] == null) {
|
||
|
return [draft.errors.invalidTypeError({ pointer, schema, value, receivedType })];
|
||
|
}
|
||
|
|
||
|
// get type validation results
|
||
|
const errors = flattenArray(draft.validateType[receivedType](draft, schema, value, pointer));
|
||
|
return errors.filter(errorOrPromise) as JsonError[]; // ignore promises here
|
||
|
}
|