[FEAT] Add ajv-errors support
See original GitHub issueInformation
Add ajv-errors message customization support.
Ref: https://www.npmjs.com/package/ajv-errors Related: #833
Example
Configuration:
const Ajv = require("ajv").default
const ajv = new Ajv({allErrors: true})
// Ajv option allErrors is required
require("ajv-errors")(ajv /*, {singleError: true} */)
const schema = {
type: "object",
required: ["foo"],
properties: {
foo: {type: "integer"},
},
additionalProperties: false,
errorMessage: "should be an object with an integer property foo only",
}
const validate = ajv.compile(schema)
console.log(validate({foo: "a", bar: 2})) // false
console.log(validate.errors) // processed errors
Output:
[
{
keyword: "errorMessage",
message: "should be an object with an integer property foo only",
// ...
params: {
errors: [
{keyword: "additionalProperties", dataPath: "" /* , ... */},
{keyword: "type", dataPath: ".foo" /* , ... */},
],
},
},
]
Solution
Example 1:
Expected json-schema:
{
type: "object",
required: ["foo"],
properties: {
foo: {type: "integer"},
},
additionalProperties: false,
errorMessage: {
type: "should be an object", // will not replace internal "type" error for the property "foo"
required: "should have property foo",
additionalProperties: "should not have properties other than foo",
},
}
Solution using decorator:
import {ErrorMsg} from "@tsed/ajv";
@ErrorMsg({
type: "should be an object",
required: "should have property foo",
additionalProperties: "should not have properties other than foo"
})
export class MyModel {
@Required()
@Integer()
foo: number;
}
Example 2
For keywords “required” and “dependencies” it is possible to specify different messages for different properties.
Expected json-schema:
{
type: "object",
required: ["foo", "bar"],
properties: {
foo: {type: "integer"},
bar: {type: "string"},
},
errorMessage: {
type: "should be an object", // will not replace internal "type" error for the property "foo"
required: {
foo: 'should have an integer property "foo"',
bar: 'should have a string property "bar"',
},
},
}
Solution using decorator:
import {ErrorMsg, TypeMsg, RequiredMsg} from "@tsed/ajv";
@TypeMsg("should be an object") // shortcut to ErrorMessage({type: 'msg'})
export class MyModel {
@Required()
@Integer()
@RequiredError('integer', 'should have an integer property "foo"')
foo: number;
@Required()
@RequiredError("required", 'should have a string property "bar"')
bar: string;
}
alternative that need a huge rework, but which is more elegant:
import {ErrorMsg, TypeMsg, RequiredMsg} from "@tsed/ajv";
@TypeError("should be an object") // shortcut to ErrorMessage({type: 'msg'})
export class MyModel {
@Required()
@Integer().Error( 'should have an integer property "foo"')
foo: number;
@Required().Error('is required')
bar: string;
}
Example 3 - Default message
When the value of keyword errorMessage is an object you can specify a message that will be used if any error appears that is not specified by keywords/properties/items using _
property:
const schema = {
type: "object",
required: ["foo", "bar"],
properties: {
foo: {type: "integer", minimum: 2},
bar: {type: "string", minLength: 2},
},
additionalProperties: false,
errorMessage: {
properties: {
foo: "data.foo should be integer >= 2",
bar: "data.bar should be string with length >= 2",
},
_: 'data should have properties "foo" and "bar" only',
},
}
Solution using decorator:
import {TypeError, RequiredError, DefaultError} from "@tsed/ajv";
@DefaultMsg('data should have properties "foo" and "bar" only') // eq: ErrorMsg({_: "message"})
export class MyModel {
@Required()
@Integer()
@RequiredError('should have an integer property "foo"')
foo: number;
@Required()
@RequiredError('should have a string property "bar"')
bar: string;
}
Acceptance criteria
- Decorators works on class and properties
- Decorators are correctly exported:
- ErrorMsg
- TypeError
- RequiredError
- DefaultError
- Ajv is correctly configured with ajv-errors (Edit https://github.com/TypedProject/tsed/blob/production/packages/ajv/src/services/Ajv.ts#L48)
- Documentation is up-to-date (model.md and ajv.md)
- Unit test cover correctly the decorators.
- Integration test cover the success and error cases.
Issue Analytics
- State:
- Created 3 years ago
- Comments:10 (1 by maintainers)
Top Results From Across the Web
@sidvind/better-ajv-errors | Yarn - Package Manager
PR-84: feat: support json option to get accurate line/column listings · PR-92: feat: ajv 8 support. Installation. $ npm i @sidvind/ ...
Read more >ajv-errors - Ajv JSON schema validator
Templates; Options; Supporters, Enterprise support, Security contact ... npm install ajv-errors. # Usage. Add the keyword errorMessages to Ajv instance:.
Read more >@stoplight/better-ajv-errors v1.0.3 Bundlephobia
A simple and composable way to validate data in JavaScript (and TypeScript). 55 %. Larger. 3.42 kB. Min + Gzip. yup. Dead simple...
Read more >better-ajv-errors | JSON Schema validation for Human
npm i better-ajv-errors $ # Or $ yarn add better-ajv-errors. Also make sure that you installed ajv package to validate data against JSON...
Read more >stoplightio/spectral v6.1.1 on GitHub - NewReleases.io
feat (core): support scoped aliases by @P0lip in #1840; feat(functions): ... feat(rulesets): add validation rule for oas2 discriminator by @mkistler in #1921 ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@silveoj PR to add
@CustomKeys
decorator https://github.com/TypedProject/tsed/pull/1238@silveoj Can you review this issue. You have more experience with the ajv-errors module 😃. Maybe I miss something!
@flexwie This story after reviewed by @silveoj can be implemented 😉. It’s a complete story. Here is the Ts.ED slack to discuss: https://join.slack.com/t/tsed-framework/shared_invite/zt-ljtmbq2u-ln3FoEd4m4Oe8rIJ1~WjdQ
See you Romain