diff --git a/lib/ajv.ts b/lib/ajv.ts index 5df36f414..4b001b783 100644 --- a/lib/ajv.ts +++ b/lib/ajv.ts @@ -3,6 +3,7 @@ export { FormatDefinition, AsyncFormatDefinition, KeywordDefinition, + KeywordErrorDefinition, CodeKeywordDefinition, MacroKeywordDefinition, FuncKeywordDefinition, diff --git a/lib/types/index.ts b/lib/types/index.ts index 14adce914..581f82dae 100644 --- a/lib/types/index.ts +++ b/lib/types/index.ts @@ -141,14 +141,14 @@ export interface AsyncValidateFunction extends ValidateFunction { export type AnyValidateFunction = ValidateFunction | AsyncValidateFunction -export interface ErrorObject { - keyword: string +export interface ErrorObject { + keyword: T dataPath: string schemaPath: string params: Record // TODO add interface - // Added to validation errors of propertyNames keyword schema + // Added to validation errors of "propertyNames" keyword schema propertyName?: string - // Excluded if messages set to false. + // Excluded if option `messages` set to false. message?: string // These are added with the `verbose` option. schema?: unknown diff --git a/lib/vocabularies/applicator/additionalItems.ts b/lib/vocabularies/applicator/additionalItems.ts index fc79b6b9b..92c7c423c 100644 --- a/lib/vocabularies/applicator/additionalItems.ts +++ b/lib/vocabularies/applicator/additionalItems.ts @@ -1,14 +1,20 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {alwaysValidSchema, checkStrictMode} from "../util" import {applySubschema, Type} from "../../compile/subschema" import {_, Name, str} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message: ({params: {len}}) => str`should NOT have more than ${len} items`, + params: ({params: {len}}) => _`{limit: ${len}}`, +} + const def: CodeKeywordDefinition = { keyword: "additionalItems", type: "array", schemaType: ["boolean", "object"], before: "uniqueItems", + error, code(cxt: KeywordCxt) { const {gen, schema, parentSchema, data, it} = cxt const len = gen.const("len", _`${data}.length`) @@ -33,10 +39,6 @@ const def: CodeKeywordDefinition = { }) } }, - error: { - message: ({params: {len}}) => str`should NOT have more than ${len} items`, - params: ({params: {len}}) => _`{limit: ${len}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/additionalProperties.ts b/lib/vocabularies/applicator/additionalProperties.ts index 109fe658a..7e4f55a91 100644 --- a/lib/vocabularies/applicator/additionalProperties.ts +++ b/lib/vocabularies/applicator/additionalProperties.ts @@ -1,14 +1,20 @@ -import type {CodeKeywordDefinition, KeywordErrorCxt} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import {allSchemaProperties, schemaRefOrVal, alwaysValidSchema, usePattern} from "../util" import {applySubschema, SubschemaApplication, Type} from "../../compile/subschema" import {_, nil, or, Code, Name} from "../../compile/codegen" import N from "../../compile/names" +const error: KeywordErrorDefinition = { + message: "should NOT have additional properties", + params: ({params}) => _`{additionalProperty: ${params.additionalProperty}}`, +} + const def: CodeKeywordDefinition = { keyword: "additionalProperties", type: "object", schemaType: ["boolean", "object", "undefined"], // "undefined" is needed to support option removeAdditional: "all" trackErrors: true, + error, code(cxt) { const {gen, schema, parentSchema, data, errsCount, it} = cxt if (!errsCount) throw new Error("ajv implementation error") @@ -91,13 +97,6 @@ const def: CodeKeywordDefinition = { applySubschema(it, subschema, valid) } }, - error: { - message: "should NOT have additional properties", - params: ({params}: KeywordErrorCxt): Code => - _`{additionalProperty: ${params.additionalProperty}}`, - }, } -module.exports = def - export default def diff --git a/lib/vocabularies/applicator/allOf.ts b/lib/vocabularies/applicator/allOf.ts index 33aa3cc7c..540a012b2 100644 --- a/lib/vocabularies/applicator/allOf.ts +++ b/lib/vocabularies/applicator/allOf.ts @@ -18,4 +18,4 @@ const def: CodeKeywordDefinition = { }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/anyOf.ts b/lib/vocabularies/applicator/anyOf.ts index a7f3a6ce0..d9beac300 100644 --- a/lib/vocabularies/applicator/anyOf.ts +++ b/lib/vocabularies/applicator/anyOf.ts @@ -44,4 +44,4 @@ const def: CodeKeywordDefinition = { }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/contains.ts b/lib/vocabularies/applicator/contains.ts index e4b0aa28b..28b29c405 100644 --- a/lib/vocabularies/applicator/contains.ts +++ b/lib/vocabularies/applicator/contains.ts @@ -40,4 +40,4 @@ const def: CodeKeywordDefinition = { }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/dependencies.ts b/lib/vocabularies/applicator/dependencies.ts index 5efb26782..da279861b 100644 --- a/lib/vocabularies/applicator/dependencies.ts +++ b/lib/vocabularies/applicator/dependencies.ts @@ -1,4 +1,4 @@ -import type {CodeKeywordDefinition, SchemaMap, AnySchema} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition, SchemaMap, AnySchema} from "../../types" import type KeywordCxt from "../../compile/context" import {alwaysValidSchema, propertyInData} from "../util" import {applySubschema} from "../../compile/subschema" @@ -11,10 +11,23 @@ interface PropertyDependencies { type SchemaDependencies = SchemaMap +const error: KeywordErrorDefinition = { + message: ({params: {property, depsCount, deps}}) => { + const property_ies = depsCount === 1 ? "property" : "properties" + return str`should have ${property_ies} ${deps} when property ${property} is present` + }, + params: ({params: {property, depsCount, deps, missingProperty}}) => + _`{property: ${property}, + missingProperty: ${missingProperty}, + depsCount: ${depsCount}, + deps: ${deps}}`, // TODO change to reference? +} + const def: CodeKeywordDefinition = { keyword: "dependencies", type: "object", schemaType: "object", + error, code(cxt: KeywordCxt) { const {gen, schema, data, it} = cxt const [propDeps, schDeps] = splitDependencies() @@ -71,17 +84,6 @@ const def: CodeKeywordDefinition = { } } }, - error: { - message: ({params: {property, depsCount, deps}}) => { - const property_ies = depsCount === 1 ? "property" : "properties" - return str`should have ${property_ies} ${deps} when property ${property} is present` - }, - params: ({params: {property, depsCount, deps, missingProperty}}) => - _`{property: ${property}, - missingProperty: ${missingProperty}, - depsCount: ${depsCount}, - deps: ${deps}}`, // TODO change to reference? - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/if.ts b/lib/vocabularies/applicator/if.ts index af8997c20..4bcd3654c 100644 --- a/lib/vocabularies/applicator/if.ts +++ b/lib/vocabularies/applicator/if.ts @@ -1,13 +1,19 @@ -import type {CodeKeywordDefinition, SchemaObjCxt} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition, SchemaObjCxt} from "../../types" import type KeywordCxt from "../../compile/context" import {alwaysValidSchema, checkStrictMode} from "../util" import {applySubschema} from "../../compile/subschema" import {_, str, Name} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message: ({params}) => str`should match "${params.ifClause}" schema`, + params: ({params}) => _`{failingKeyword: ${params.ifClause}}`, +} + const def: CodeKeywordDefinition = { keyword: "if", schemaType: ["object", "boolean"], trackErrors: true, + error, code(cxt: KeywordCxt) { const {gen, parentSchema, it} = cxt if (parentSchema.then === undefined && parentSchema.else === undefined) { @@ -56,15 +62,11 @@ const def: CodeKeywordDefinition = { } } }, - error: { - message: ({params}) => str`should match "${params.ifClause}" schema`, - params: ({params}) => _`{failingKeyword: ${params.ifClause}}`, - }, } -module.exports = def - function hasSchema(it: SchemaObjCxt, keyword: string): boolean { const schema = it.schema[keyword] return schema !== undefined && !alwaysValidSchema(it, schema) } + +export default def diff --git a/lib/vocabularies/applicator/index.ts b/lib/vocabularies/applicator/index.ts index 086c1ad13..15abf1fdf 100644 --- a/lib/vocabularies/applicator/index.ts +++ b/lib/vocabularies/applicator/index.ts @@ -1,23 +1,37 @@ import type {Vocabulary} from "../../types" +import additionalItems from "./additionalItems" +import items from "./items" +import contains from "./contains" +import dependencies from "./dependencies" +import propertyNames from "./propertyNames" +import additionalProperties from "./additionalProperties" +import properties from "./properties" +import patternProperties from "./patternProperties" +import notKeyword from "./not" +import anyOf from "./anyOf" +import oneOf from "./oneOf" +import allOf from "./allOf" +import ifKeyword from "./if" +import thenElse from "./thenElse" const applicator: Vocabulary = [ // array - require("./additionalItems"), - require("./items"), - require("./contains"), + additionalItems, + items, + contains, // object - require("./dependencies"), - require("./propertyNames"), - require("./additionalProperties"), - require("./properties"), - require("./patternProperties"), + dependencies, + propertyNames, + additionalProperties, + properties, + patternProperties, // any - require("./not"), - require("./anyOf"), - require("./oneOf"), - require("./allOf"), - require("./if"), - require("./thenElse"), + notKeyword, + anyOf, + oneOf, + allOf, + ifKeyword, + thenElse, ] export default applicator diff --git a/lib/vocabularies/applicator/items.ts b/lib/vocabularies/applicator/items.ts index 15a89db1e..68cba36d1 100644 --- a/lib/vocabularies/applicator/items.ts +++ b/lib/vocabularies/applicator/items.ts @@ -48,4 +48,4 @@ const def: CodeKeywordDefinition = { }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/not.ts b/lib/vocabularies/applicator/not.ts index bb183fa77..4c2deabfc 100644 --- a/lib/vocabularies/applicator/not.ts +++ b/lib/vocabularies/applicator/not.ts @@ -37,4 +37,4 @@ const def: CodeKeywordDefinition = { }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/oneOf.ts b/lib/vocabularies/applicator/oneOf.ts index 8c17f6bfc..cc4c74d54 100644 --- a/lib/vocabularies/applicator/oneOf.ts +++ b/lib/vocabularies/applicator/oneOf.ts @@ -1,13 +1,19 @@ -import type {CodeKeywordDefinition, AnySchema} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition, AnySchema} from "../../types" import type KeywordCxt from "../../compile/context" import {alwaysValidSchema} from "../util" import {applySubschema} from "../../compile/subschema" import {_} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message: "should match exactly one schema in oneOf", + params: ({params}) => _`{passingSchemas: ${params.passing}}`, +} + const def: CodeKeywordDefinition = { keyword: "oneOf", schemaType: "array", trackErrors: true, + error, code(cxt: KeywordCxt) { const {gen, schema, it} = cxt if (!Array.isArray(schema)) throw new Error("ajv implementation error") @@ -54,10 +60,6 @@ const def: CodeKeywordDefinition = { }) } }, - error: { - message: "should match exactly one schema in oneOf", - params: ({params}) => _`{passingSchemas: ${params.passing}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/patternProperties.ts b/lib/vocabularies/applicator/patternProperties.ts index 7d11ea4cc..c8ffa2e3c 100644 --- a/lib/vocabularies/applicator/patternProperties.ts +++ b/lib/vocabularies/applicator/patternProperties.ts @@ -61,4 +61,4 @@ const def: CodeKeywordDefinition = { }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/properties.ts b/lib/vocabularies/applicator/properties.ts index 493af3b1c..76926a343 100644 --- a/lib/vocabularies/applicator/properties.ts +++ b/lib/vocabularies/applicator/properties.ts @@ -47,4 +47,4 @@ const def: CodeKeywordDefinition = { }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/propertyNames.ts b/lib/vocabularies/applicator/propertyNames.ts index 42e8638df..72d67c4f0 100644 --- a/lib/vocabularies/applicator/propertyNames.ts +++ b/lib/vocabularies/applicator/propertyNames.ts @@ -1,13 +1,19 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {alwaysValidSchema} from "../util" import {applySubschema} from "../../compile/subschema" import {_, str} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message: ({params}) => str`property name '${params.propertyName}' is invalid`, // TODO double quotes? + params: ({params}) => _`{propertyName: ${params.propertyName}}`, +} + const def: CodeKeywordDefinition = { keyword: "propertyNames", type: "object", schemaType: ["object", "boolean"], + error, code(cxt: KeywordCxt) { const {gen, schema, data, it} = cxt if (alwaysValidSchema(it, schema)) return @@ -28,10 +34,6 @@ const def: CodeKeywordDefinition = { cxt.ok(valid) }, - error: { - message: ({params}) => str`property name '${params.propertyName}' is invalid`, // TODO double quotes? - params: ({params}) => _`{propertyName: ${params.propertyName}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/applicator/thenElse.ts b/lib/vocabularies/applicator/thenElse.ts index ba0541a19..e3002a015 100644 --- a/lib/vocabularies/applicator/thenElse.ts +++ b/lib/vocabularies/applicator/thenElse.ts @@ -10,4 +10,4 @@ const def: CodeKeywordDefinition = { }, } -module.exports = def +export default def diff --git a/lib/vocabularies/core/index.ts b/lib/vocabularies/core/index.ts index 5845d0384..5b8fb6f36 100644 --- a/lib/vocabularies/core/index.ts +++ b/lib/vocabularies/core/index.ts @@ -1,5 +1,6 @@ import type {Vocabulary} from "../../types" +import refKeyword from "./ref" -const core: Vocabulary = ["$schema", "$id", "$defs", "definitions", require("./ref")] +const core: Vocabulary = ["$schema", "$id", "$defs", "definitions", refKeyword] export default core diff --git a/lib/vocabularies/core/ref.ts b/lib/vocabularies/core/ref.ts index d76b5ad89..ea316a0d0 100644 --- a/lib/vocabularies/core/ref.ts +++ b/lib/vocabularies/core/ref.ts @@ -1,4 +1,4 @@ -import type {CodeKeywordDefinition, AnySchema} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition, AnySchema} from "../../types" import type KeywordCxt from "../../compile/context" import {MissingRefError} from "../../compile/error_classes" import {applySubschema} from "../../compile/subschema" @@ -7,9 +7,15 @@ import {_, str, nil, Code, Name} from "../../compile/codegen" import N from "../../compile/names" import {SchemaEnv, resolveRef} from "../../compile" +const error: KeywordErrorDefinition = { + message: ({schema}) => str`can't resolve reference ${schema}`, + params: ({schema}) => _`{ref: ${schema}}`, +} + const def: CodeKeywordDefinition = { keyword: "$ref", schemaType: "string", + error, code(cxt: KeywordCxt) { const {gen, schema, it} = cxt const {allErrors, baseId, schemaEnv: env, opts, validateName, self} = it @@ -101,11 +107,6 @@ const def: CodeKeywordDefinition = { gen.assign(N.errors, _`${N.vErrors}.length`) } }, - // TODO incorrect error message - error: { - message: ({schema}) => str`can't resolve reference ${schema}`, - params: ({schema}) => _`{ref: ${schema}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/format/format.ts b/lib/vocabularies/format/format.ts index 22b6e4ca2..437af8477 100644 --- a/lib/vocabularies/format/format.ts +++ b/lib/vocabularies/format/format.ts @@ -3,6 +3,7 @@ import type { FormatValidator, AsyncFormatValidator, CodeKeywordDefinition, + KeywordErrorDefinition, } from "../../types" import type KeywordCxt from "../../compile/context" import {_, str, nil, or, Code, getProperty} from "../../compile/codegen" @@ -16,11 +17,17 @@ type FormatValidate = | RegExp | string +const error: KeywordErrorDefinition = { + message: ({schemaCode}) => str`should match format "${schemaCode}"`, + params: ({schemaCode}) => _`{format: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: "format", type: ["number", "string"], schemaType: "string", $data: true, + error, code(cxt: KeywordCxt, ruleType?: string) { const {gen, data, $data, schema, schemaCode, it} = cxt const {opts, errSchemaPath, schemaEnv, self} = it @@ -107,10 +114,6 @@ const def: CodeKeywordDefinition = { } } }, - error: { - message: ({schemaCode}) => str`should match format "${schemaCode}"`, - params: ({schemaCode}) => _`{format: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/format/index.ts b/lib/vocabularies/format/index.ts index 9763393d6..bca2f5b3d 100644 --- a/lib/vocabularies/format/index.ts +++ b/lib/vocabularies/format/index.ts @@ -1,5 +1,6 @@ import type {Vocabulary} from "../../types" +import formatKeyword from "./format" -const format: Vocabulary = [require("./format")] +const format: Vocabulary = [formatKeyword] export default format diff --git a/lib/vocabularies/validation/const.ts b/lib/vocabularies/validation/const.ts index 648ae97a6..f44d7b9b1 100644 --- a/lib/vocabularies/validation/const.ts +++ b/lib/vocabularies/validation/const.ts @@ -1,11 +1,17 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {_} from "../../compile/codegen" import equal from "fast-deep-equal" +const error: KeywordErrorDefinition = { + message: "should be equal to constant", + params: ({schemaCode}) => _`{allowedValue: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: "const", $data: true, + error, code(cxt: KeywordCxt) { const eql = cxt.gen.scopeValue("func", { ref: equal, @@ -13,10 +19,6 @@ const def: CodeKeywordDefinition = { }) cxt.fail$data(_`!${eql}(${cxt.data}, ${cxt.schemaCode})`) }, - error: { - message: "should be equal to constant", - params: ({schemaCode}) => _`{allowedValue: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/enum.ts b/lib/vocabularies/validation/enum.ts index 84e973e85..f2bfb302e 100644 --- a/lib/vocabularies/validation/enum.ts +++ b/lib/vocabularies/validation/enum.ts @@ -1,12 +1,18 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {_, or, Name, Code} from "../../compile/codegen" import equal from "fast-deep-equal" +const error: KeywordErrorDefinition = { + message: "should be equal to one of the allowed values", + params: ({schemaCode}) => _`{allowedValues: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: "enum", schemaType: "array", $data: true, + error, code(cxt: KeywordCxt) { const {gen, data, $data, schema, schemaCode, it} = cxt if (!$data && schema.length === 0) throw new Error("enum must have non-empty array") @@ -41,10 +47,6 @@ const def: CodeKeywordDefinition = { return _`${data} === ${sch}` } }, - error: { - message: "should be equal to one of the allowed values", - params: ({schemaCode}) => _`{allowedValues: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/index.ts b/lib/vocabularies/validation/index.ts index 116ce1759..1c555ec41 100644 --- a/lib/vocabularies/validation/index.ts +++ b/lib/vocabularies/validation/index.ts @@ -1,22 +1,32 @@ import type {Vocabulary} from "../../types" +import limit from "./limit" +import multipleOf from "./multipleOf" +import limitLength from "./limitLength" +import pattern from "./pattern" +import limitProperties from "./limitProperties" +import required from "./required" +import limitItems from "./limitItems" +import uniqueItems from "./uniqueItems" +import constKeyword from "./const" +import enumKeyword from "./enum" const validation: Vocabulary = [ // number - require("./limit"), - require("./multipleOf"), + limit, + multipleOf, // string - require("./limitLength"), - require("./pattern"), + limitLength, + pattern, // object - require("./limitProperties"), - require("./required"), + limitProperties, + required, // array - require("./limitItems"), - require("./uniqueItems"), + limitItems, + uniqueItems, // any {keyword: "nullable", schemaType: "boolean"}, - require("./const"), - require("./enum"), + constKeyword, + enumKeyword, ] export default validation diff --git a/lib/vocabularies/validation/limit.ts b/lib/vocabularies/validation/limit.ts index a5bf82de2..22086f1eb 100644 --- a/lib/vocabularies/validation/limit.ts +++ b/lib/vocabularies/validation/limit.ts @@ -1,4 +1,4 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {_, str, operators, Code} from "../../compile/codegen" @@ -11,20 +11,22 @@ const OPS: {[index: string]: {fail: Code; ok: Code; okStr: string}} = { exclusiveMinimum: {okStr: ">", ok: ops.GT, fail: ops.LTE}, } +const error: KeywordErrorDefinition = { + message: ({keyword, schemaCode}) => str`should be ${OPS[keyword].okStr} ${schemaCode}`, + params: ({keyword, schemaCode}) => _`{comparison: ${OPS[keyword].okStr}, limit: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: ["maximum", "minimum", "exclusiveMaximum", "exclusiveMinimum"], type: "number", schemaType: "number", $data: true, + error, code(cxt: KeywordCxt) { const {keyword, data, schemaCode} = cxt // const bdt = bad$DataType(schemaCode, def.schemaType, $data) cxt.fail$data(_`(${data} ${OPS[keyword].fail} ${schemaCode} || isNaN(${data}))`) }, - error: { - message: ({keyword, schemaCode}) => str`should be ${OPS[keyword].okStr} ${schemaCode}`, - params: ({keyword, schemaCode}) => _`{comparison: ${OPS[keyword].okStr}, limit: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/limitItems.ts b/lib/vocabularies/validation/limitItems.ts index e7615fb3a..9bf865eb6 100644 --- a/lib/vocabularies/validation/limitItems.ts +++ b/lib/vocabularies/validation/limitItems.ts @@ -1,24 +1,26 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {_, str, operators} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message({keyword, schemaCode}) { + const comp = keyword === "maxItems" ? "more" : "fewer" + return str`should NOT have ${comp} than ${schemaCode} items` + }, + params: ({schemaCode}) => _`{limit: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: ["maxItems", "minItems"], type: "array", schemaType: "number", $data: true, + error, code(cxt: KeywordCxt) { const {keyword, data, schemaCode} = cxt const op = keyword === "maxItems" ? operators.GT : operators.LT cxt.fail$data(_`${data}.length ${op} ${schemaCode}`) }, - error: { - message({keyword, schemaCode}) { - const comp = keyword === "maxItems" ? "more" : "fewer" - return str`should NOT have ${comp} than ${schemaCode} items` - }, - params: ({schemaCode}) => _`{limit: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/limitLength.ts b/lib/vocabularies/validation/limitLength.ts index 448b63dc1..04bf9f734 100644 --- a/lib/vocabularies/validation/limitLength.ts +++ b/lib/vocabularies/validation/limitLength.ts @@ -1,13 +1,22 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {_, str, operators} from "../../compile/codegen" import ucs2length from "../../compile/ucs2length" +const error: KeywordErrorDefinition = { + message({keyword, schemaCode}) { + const comp = keyword === "maxLength" ? "more" : "fewer" + return str`should NOT have ${comp} than ${schemaCode} items` + }, + params: ({schemaCode}) => _`{limit: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: ["maxLength", "minLength"], type: "string", schemaType: "number", $data: true, + error, code(cxt: KeywordCxt) { const {keyword, data, schemaCode, it} = cxt const op = keyword === "maxLength" ? operators.GT : operators.LT @@ -23,13 +32,6 @@ const def: CodeKeywordDefinition = { } cxt.fail$data(_`${len} ${op} ${schemaCode}`) }, - error: { - message({keyword, schemaCode}) { - const comp = keyword === "maxLength" ? "more" : "fewer" - return str`should NOT have ${comp} than ${schemaCode} items` - }, - params: ({schemaCode}) => _`{limit: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/limitProperties.ts b/lib/vocabularies/validation/limitProperties.ts index 04e7e8ba8..ec5943deb 100644 --- a/lib/vocabularies/validation/limitProperties.ts +++ b/lib/vocabularies/validation/limitProperties.ts @@ -1,24 +1,26 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {_, str, operators} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message({keyword, schemaCode}) { + const comp = keyword === "maxProperties" ? "more" : "fewer" + return str`should NOT have ${comp} than ${schemaCode} items` + }, + params: ({schemaCode}) => _`{limit: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: ["maxProperties", "minProperties"], type: "object", schemaType: "number", $data: true, + error, code(cxt: KeywordCxt) { const {keyword, data, schemaCode} = cxt const op = keyword === "maxProperties" ? operators.GT : operators.LT cxt.fail$data(_`Object.keys(${data}).length ${op} ${schemaCode}`) }, - error: { - message({keyword, schemaCode}) { - const comp = keyword === "maxProperties" ? "more" : "fewer" - return str`should NOT have ${comp} than ${schemaCode} items` - }, - params: ({schemaCode}) => _`{limit: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/multipleOf.ts b/lib/vocabularies/validation/multipleOf.ts index c4298dfc7..d1a763e7a 100644 --- a/lib/vocabularies/validation/multipleOf.ts +++ b/lib/vocabularies/validation/multipleOf.ts @@ -1,12 +1,18 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {_, str} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message: ({schemaCode}) => str`should be multiple of ${schemaCode}`, + params: ({schemaCode}) => _`{multipleOf: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: "multipleOf", type: "number", schemaType: "number", $data: true, + error, code(cxt: KeywordCxt) { const {gen, data, schemaCode, it} = cxt // const bdt = bad$DataType(schemaCode, def.schemaType, $data) @@ -17,10 +23,6 @@ const def: CodeKeywordDefinition = { : _`${res} !== parseInt(${res})` cxt.fail$data(_`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid}))`) }, - error: { - message: ({schemaCode}) => str`should be multiple of ${schemaCode}`, - params: ({schemaCode}) => _`{multipleOf: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/pattern.ts b/lib/vocabularies/validation/pattern.ts index e4ceefce9..0d41aab58 100644 --- a/lib/vocabularies/validation/pattern.ts +++ b/lib/vocabularies/validation/pattern.ts @@ -1,22 +1,24 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {usePattern} from "../util" import {_, str} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message: ({schemaCode}) => str`should match pattern "${schemaCode}"`, + params: ({schemaCode}) => _`{pattern: ${schemaCode}}`, +} + const def: CodeKeywordDefinition = { keyword: "pattern", type: "string", schemaType: "string", $data: true, + error, code(cxt: KeywordCxt) { const {gen, data, $data, schema, schemaCode} = cxt const regExp = $data ? _`(new RegExp(${schemaCode}, "u"))` : usePattern(gen, schema) // TODO regexp should be wrapped in try/catch cxt.fail$data(_`!${regExp}.test(${data})`) }, - error: { - message: ({schemaCode}) => str`should match pattern "${schemaCode}"`, - params: ({schemaCode}) => _`{pattern: ${schemaCode}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/required.ts b/lib/vocabularies/validation/required.ts index 85a3b8528..dc66ff15b 100644 --- a/lib/vocabularies/validation/required.ts +++ b/lib/vocabularies/validation/required.ts @@ -1,14 +1,20 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {propertyInData, noPropertyInData} from "../util" import {checkReportMissingProp, checkMissingProp, reportMissingProp} from "../missing" import {_, str, nil, Name} from "../../compile/codegen" +const error: KeywordErrorDefinition = { + message: ({params: {missingProperty}}) => str`should have required property '${missingProperty}'`, + params: ({params: {missingProperty}}) => _`{missingProperty: ${missingProperty}}`, +} + const def: CodeKeywordDefinition = { keyword: "required", type: "object", schemaType: "array", $data: true, + error, code(cxt: KeywordCxt) { const {gen, schema, schemaCode, data, $data, it} = cxt if (!$data && schema.length === 0) return @@ -62,11 +68,6 @@ const def: CodeKeywordDefinition = { ) } }, - error: { - message: ({params: {missingProperty}}) => - str`should have required property '${missingProperty}'`, - params: ({params: {missingProperty}}) => _`{missingProperty: ${missingProperty}}`, - }, } -module.exports = def +export default def diff --git a/lib/vocabularies/validation/uniqueItems.ts b/lib/vocabularies/validation/uniqueItems.ts index 02da60860..53f065efe 100644 --- a/lib/vocabularies/validation/uniqueItems.ts +++ b/lib/vocabularies/validation/uniqueItems.ts @@ -1,15 +1,22 @@ -import type {CodeKeywordDefinition} from "../../types" +import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" import type KeywordCxt from "../../compile/context" import {getSchemaTypes} from "../../compile/validate/dataType" import {checkDataTypes, DataType} from "../../compile/util" import {_, str, Name} from "../../compile/codegen" import equal from "fast-deep-equal" +const error: KeywordErrorDefinition = { + message: ({params: {i, j}}) => + str`should NOT have duplicate items (items ## ${j} and ${i} are identical)`, + params: ({params: {i, j}}) => _`{i: ${i}, j: ${j}}`, +} + const def: CodeKeywordDefinition = { keyword: "uniqueItems", type: "array", schemaType: "boolean", $data: true, + error, code(cxt: KeywordCxt) { const {gen, data, $data, schema, parentSchema, schemaCode, it} = cxt if (!$data && !schema) return @@ -64,11 +71,6 @@ const def: CodeKeywordDefinition = { ) } }, - error: { - message: ({params: {i, j}}) => - str`should NOT have duplicate items (items ## ${j} and ${i} are identical)`, - params: ({params: {i, j}}) => _`{i: ${i}, j: ${j}}`, - }, } -module.exports = def +export default def