Skip to content

Validators

Ajv is the default JSON Schema validator used by @feathersjs/schema. We chose it because it's fully compliant with the JSON Schema spec and it's the fastest JSON Schema validator because it has its own compiler. It pre-compiles code for each validator, instead of dynamically creating validators from schemas during runtime.

Important

Ajv and most other validation libraries are only used for ensuring data is valid and are not designed to convert data to different types. Type conversions and populating data can be done using resolvers. This ensures a clean separation of concern between validating and populating data.

Usage

The following is the standard validators.ts file that sets up a validator for data and queries (for which string types will be coerced automatically). It also sets up a collection of additional formats using ajv-formats. The validators in this file can be customized according to the Ajv documentation and its plugins. You can find the available Ajv options in the Ajv class API docs.

ts
import { Ajv, addFormats } from '@feathersjs/schema'
import type { FormatsPluginOptions } from '@feathersjs/schema'

const formats: FormatsPluginOptions = [
  'date-time',
  'time',
  'date',
  'email',
  'hostname',
  'ipv4',
  'ipv6',
  'uri',
  'uri-reference',
  'uuid',
  'uri-template',
  'json-pointer',
  'relative-json-pointer',
  'regex'
]

export const dataValidator = addFormats(new Ajv({}), formats)

export const queryValidator = addFormats(
  new Ajv({
    coerceTypes: true
  }),
  formats
)

Validation functions

A validation function takes data and validates them against a schema using a validator. They can be used with any validation library. Currently the getValidator functions are available for:

  • TypeBox schema to validate a TypeBox definition using an Ajv validator instance
  • JSON schema to validate a JSON schema object using an Ajv validator instance

Hooks

The following hooks take a validation function and validate parts of the hook context.

validateData

schemaHooks.validateData takes a validation function and allows to validate the data in a create, update and patch request as well as custom service methods. It can be used as an around or before hook.

ts
import { Ajv, schemaHooks } from '@feathersjs/schema'
import { Type, getValidator } from '@feathersjs/typebox'
import type { Static } from '@feathersjs/typebox'
import { dataValidator } from '../validators'

const userSchema = Type.Object(
  {
    id: Type.Number(),
    email: Type.String(),
    password: Type.String(),
    avatar: Type.Optional(Type.String())
  },
  { $id: 'User', additionalProperties: false }
)
type User = Static<typeof userSchema>

const userDataSchema = Type.Pick(userSchema, ['email', 'password'])

// Returns validation functions for `create`, `update` and `patch`
const userDataValidator = getValidator(userDataSchema, dataValidator)

app.service('users').hooks({
  before: {
    all: [schemaHooks.validateData(userDataValidator)]
  }
})

validateQuery

schemaHooks.validateQuery takes a validation function and validates the query of a request. It can be used as an around or before hook. When using the queryValidator from the usage section, strings will automatically be converted to the right type using Ajv's type coercion rules.

ts
import { Ajv, schemaHooks } from '@feathersjs/schema'
import { Type, getValidator } from '@feathersjs/typebox'
import { queryValidator } from '../validators'

// Schema for allowed query properties
const messageQueryProperties = Type.Pick(messageSchema, ['id', 'text', 'createdAt', 'userId'], {
  additionalProperties: false
})
const messageQuerySchema = querySyntax(messageQueryProperties)
type MessageQuery = Static<typeof messageQuerySchema>

const messageQueryValidator = getValidator(messageQuerySchema, queryValidator)

app.service('messages').hooks({
  around: {
    all: [schemaHooks.validateQuery(messageQueryValidator)]
  }
})

Released under the MIT License.