https://github.com/jcoreio/sequelize-validate-subfields
simple framework for validating subfields of JSON attributes of Sequelize models
https://github.com/jcoreio/sequelize-validate-subfields
es2015
Last synced: about 1 year ago
JSON representation
simple framework for validating subfields of JSON attributes of Sequelize models
- Host: GitHub
- URL: https://github.com/jcoreio/sequelize-validate-subfields
- Owner: jcoreio
- License: mit
- Created: 2018-01-17T04:29:21.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2023-11-28T19:04:26.000Z (over 2 years ago)
- Last Synced: 2025-03-23T15:41:06.673Z (about 1 year ago)
- Topics: es2015
- Language: JavaScript
- Size: 3.47 MB
- Stars: 0
- Watchers: 3
- Forks: 1
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# sequelize-validate-subfields
[](https://circleci.com/gh/jcoreio/sequelize-validate-subfields)
[](https://codecov.io/gh/jcoreio/sequelize-validate-subfields)
[](https://github.com/semantic-release/semantic-release)
[](http://commitizen.github.io/cz-cli/)
[](https://badge.fury.io/js/sequelize-validate-subfields)
simple framework for validating subfields of JSON attributes of Sequelize models
# Introduction
If you ever use JSON attributes in Sequelize models, you'll probably want to validate that the JSON matches some
schema. And if values within the JSON come from a form filled out by a user, you'll probably want to be able to
show validation errors from the server associated with the correct form field on the client.
But Sequelize `ValidationError`s be default only identify the top-level attribute of each validation error. For
example if you have the following validator:
```js
address: {
type: Sequelize.JSON,
validate: {
isValid(address) {
if (/^\d{5}$/.test(address.postalCode)) throw new Error('invalid postal code')
}
}
}
```
You'll get an error including the following information:
```js
ValidationError {
errors: [
ValidationErrorItem {
message: 'invalid postal code',
type: 'Validation error',
path: 'address',
__raw: Error {
message: 'invalid postal code',
},
...
}
]
}
```
If you use this package to perform validation, you can tag each validation error with a specific field path instead:
```js
address: {
type: Sequelize.JSON,
validate: {
isValid: validateSubfields(function * (address) {
if (/^\d{5}$/.test(address.postalCode)) yield {path: ['postalCode'], message: 'invalid postal code'}
if (states.has(address.state)) yield {path: ['state'], message: 'invalid state'}
// etc.
})
}
}
```
And you'll get an error including those paths:
```
ValidationError {
errors: [
ValidationErrorItem {
message: 'validation failed',
type: 'Validation error',
path: 'address',
__raw: Error {
message: 'validation failed',
validation: {
errors: [
{path: ['postalCode'], message: 'invalid postal code'},
{path: ['state'], message: 'invalid state'},
]
}
}
}
]
}
```
This package also provides a `flattenValidationErrors` function to combine subfield validation errors like in the
example above with normal validation errors on non-JSON fields:
```js
;[
{ path: ['address', 'postalCode'], message: 'invalid postal code' },
{ path: ['address', 'state'], message: 'invalid state' },
]
```
# Installation
```sh
npm install --save sequelize-validate-subfields
```
# API
## `validateSubfields(validator)`
```js
const { validateSubfields } = require('sequelize-validate-subfields')
```
### Arguments
#### `validator: (value: any) => Iterable`
a generator function which receives the attribute `value` and may `yield` as many validation
`FieldValidation` objects as you wish, each specifying a validation error in the following form:
```js
{
path: Array,
message: string,
}
```
`path` is the `lodash.get`-style path within the attribute (i.e. not including the attribute name itself) that
`message` is associated with. For example if you define an `address` attribute and validator on a model like this:
```js
address: {
type: Sequelize.JSON,
validate: {
isValid: validateSubfields(function * (address) {
if (/^\d{5}$/.test(address.postalCode)) yield {path: ['postalCode'], message: 'invalid postal code'}
if (states.has(address.state)) yield {path: ['state'], message: 'invalid state'}
// etc.
})
}
}
```
Notice that the yielded `path`s don't contain `'address'` (the name of the attribute) themselves; they must be relative
to the root of the attribute, instead of the root of the model instance.
### Returns: `(value: any) => void`
A Sequelize custom validator function that delegates to your `validator` function and combines any `FieldValidation`s
it `yield`ed into the appropriate thrown error.
## `flattenValidationErrors(error, [options])`
```js
const { flattenValidationErrors } = require('sequelize-validate-subfields')
```
### Arguments
#### `error: Sequelize.ValidationError`
A `ValidationError` hich may contain zero or more `ValidationErrorItems` -- some may be from non-JSON field
validation errors, and some may contain `FieldValidation`s from `validateSubfields`.
#### `options?: {formatItemMessage?: (item: ValidationErrorItem) => string}`
`formatItemMessage` allows you to override the error `message`s output for `ValidationErrorItem`s that don't
contain `FieldValidation`s using your own custom function.
### Returns: `Array`
A flattened array of `FieldValidation`s with `path`s relative to the root of the model instance instead of
being relative to specific attributes. For instance, if you have the following model:
```js
const User = sequelize.define('User', {
username: {
type: Sequelize.STRING,
validate: {
notEmpty: {
msg: 'required',
},
},
},
address: {
type: Sequelize.JSON,
validate: {
isValid: validateSubfields(function* (address) {
if (/^\d{5}$/.test(address.postalCode))
yield { path: ['postalCode'], message: 'invalid postal code' }
if (states.has(address.state))
yield { path: ['state'], message: 'invalid state' }
// etc.
}),
},
},
})
```
And you validate the following fields:
```js
{
username: '',
address: {
postalCode: '123',
state: 'KG',
}
}
```
You will get a `ValidationError` with the following structure:
```
ValidationError {
errors: [
ValidationErrorItem {
message: 'required',
type: 'Validation error',
path: 'username',
},
ValidationErrorItem {
message: 'validation failed',
type: 'Validation error',
path: 'address',
__raw: Error {
message: 'validation failed',
validation: {
errors: [
{path: ['postalCode'], message: 'invalid postal code'},
{path: ['state'], message: 'invalid state'},
]
}
}
}
]
}
```
Calling `flattenValidationErrors` on this will produce:
```js
;[
{ path: ['username'], message: 'required' },
{ path: ['address', 'postalCode'], message: 'invalid postal code' },
{ path: ['address', 'state'], message: 'invalid state' },
]
```