Skip to content

Commit fe701e4

Browse files
committed
feat: add validationErrors to schema mismatch errors
1 parent 920317f commit fe701e4

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,20 +122,24 @@ function build (schema, options) {
122122

123123
let contextFunctionCode
124124

125+
const resetValidatorErrors = (context.validatorSchemasIds.size > 0) ? 'validator.resetErrors();' : ''
126+
125127
// If we have only the invocation of the 'anonymous0' function, we would
126128
// basically just wrap the 'anonymous0' function in the 'main' function and
127129
// and the overhead of the intermediate variable 'json'. We can avoid the
128130
// wrapping and the unnecessary memory allocation by aliasing 'anonymous0' to
129131
// 'main'
130132
if (code === 'json += anonymous0(input)') {
131133
contextFunctionCode = `
134+
${resetValidatorErrors}
132135
${context.functions.join('\n')}
133136
const main = anonymous0
134137
return main
135138
`
136139
} else {
137140
contextFunctionCode = `
138141
function main (input) {
142+
${resetValidatorErrors}
139143
let json = ''
140144
${code}
141145
return json
@@ -896,7 +900,7 @@ function buildValue (context, location, input) {
896900
}
897901

898902
code += `
899-
else throw new TypeError(\`The value of '${schemaRef}' does not match schema definition.\`)
903+
else validator.throwAccumulatedErrors("${schemaRef}");
900904
`
901905
if (schema.type === 'object') {
902906
code += `

lib/validator.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class Validator {
2626
}
2727
})
2828

29+
this._errors = []
2930
this._ajvSchemas = {}
3031
this._ajvOptions = ajvOptions || {}
3132
}
@@ -47,8 +48,20 @@ class Validator {
4748
}
4849
}
4950

51+
resetErrors () {
52+
this._errors = []
53+
}
54+
5055
validate (schemaRef, data) {
51-
return this.ajv.validate(schemaRef, data)
56+
const result = this.ajv.validate(schemaRef, data)
57+
if (this.ajv.errors) this._errors.push(...this.ajv.errors)
58+
return result
59+
}
60+
61+
throwAccumulatedErrors (schemaRef) {
62+
const error = new TypeError(`The value of '${schemaRef}' does not match schema definition.`)
63+
error.validationErrors = this._errors
64+
throw error
5265
}
5366

5467
// Ajv does not support js date format. In order to properly validate objects containing a date,

test/any.test.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,12 @@ test('should throw a TypeError with the path to the key of the invalid value /1'
186186

187187
const stringify = build(schema)
188188

189-
t.throws(() => stringify({ kind: 'Baz', value: 1 }), new TypeError('The value of \'#\' does not match schema definition.'))
189+
t.throws(() => stringify({ kind: 'Baz', value: 1 }), Object.assign(new TypeError('The value of \'#\' does not match schema definition.'), {
190+
validationErrors: [
191+
{ message: 'must be equal to one of the allowed values', schemaPath: '#/properties/kind/enum', instancePath: '/kind' },
192+
{ message: 'must be equal to one of the allowed values', schemaPath: '#/properties/kind/enum', instancePath: '/kind' }
193+
]
194+
}))
190195
})
191196

192197
test('should throw a TypeError with the path to the key of the invalid value /2', (t) => {
@@ -227,5 +232,10 @@ test('should throw a TypeError with the path to the key of the invalid value /2'
227232

228233
const stringify = build(schema)
229234

230-
t.throws(() => stringify({ data: { kind: 'Baz', value: 1 } }), new TypeError('The value of \'#/properties/data\' does not match schema definition.'))
235+
t.throws(() => stringify({ data: { kind: 'Baz', value: 1 } }), Object.assign(new TypeError('The value of \'#/properties/data\' does not match schema definition.'), {
236+
validationErrors: [
237+
{ message: 'must be equal to one of the allowed values', schemaPath: '#/properties/kind/enum', instancePath: '/kind' },
238+
{ message: 'must be equal to one of the allowed values', schemaPath: '#/properties/kind/enum', instancePath: '/kind' }
239+
]
240+
}))
231241
})

0 commit comments

Comments
 (0)