Back to Objection Js

Types

doc/api/types/README.md

3.1.556.3 KB
Original Source

Types

This page contains the documentation of all other types and classes than Model and QueryBuilder. There are two types of items on this page:

  1. type: A type is just a POJO (Plain Old Javascript Object) with a set of properties.
  2. class: A class is a JavaScript class with properties and methods.

type RelationMapping

PropertyTypeDescription
relationfunctionThe relation type. One of Model.BelongsToOneRelation, Model.HasOneRelation, Model.HasManyRelation, Model.ManyToManyRelation and Model.HasOneThroughRelation.
modelClassModel
stringConstructor of the related model class, an absolute path to a module that exports one or a path relative to modelPaths that exports a model class.
joinRelationJoinDescribes how the models are related to each other. See RelationJoin.
modifyfunction(QueryBuilder)
string
objectOptional modifier for the relation query. If specified as a function, it will be called each time before fetching the relation. If specified as a string, modifier with specified name will be applied each time when fetching the relation. If specified as an object, it will be used as an additional query parameter - e. g. passing {name: 'Jenny'} would additionally narrow fetched rows to the ones with the name 'Jenny'.
filterfunction(QueryBuilder)
string
objectAlias for modify.
beforeInsertfunction(ModelQueryContext)Optional insert hook that is called for each inserted model instance. This function can be async.

type RelationJoin

PropertyTypeDescription
fromstring
ReferenceBuilder
ArrayThe relation column in the owner table. Must be given with the table name. For example persons.id. Composite key can be specified using an array of columns e.g. ['persons.a', 'persons.b']. Note that neither this nor to need to be foreign keys or primary keys. You can join any column to any column. You can even join nested json fields using the ref helper.
tostring
ReferenceBuilder
ArrayThe relation column in the related table. Must be given with the table name. For example movies.id. Composite key can be specified using an array of columns e.g. ['movies.a', 'movies.b']. Note that neither this nor from need to be foreign keys or primary keys. You can join any column to any column. You can even join nested json fields using the ref helper.
throughRelationThroughDescribes the join table if the models are related through one.

type RelationThrough

PropertyTypeDescription
fromstring
ReferenceBuilder
ArrayThe column that is joined to from property of the RelationJoin. For example Person_movies.actorId where Person_movies is the join table. Composite key can be specified using an array of columns e.g. ['persons_movies.a', 'persons_movies.b']. You can join nested json fields using the ref helper.
tostring
ReferenceBuilder
ArrayThe column that is joined to to property of the RelationJoin. For example Person_movies.movieId where Person_movies is the join table. Composite key can be specified using an array of columns e.g. ['persons_movies.a', 'persons_movies.b']. You can join nested json fields using the ref helper.
modelClassstring
ModelClassIf you have a model class for the join table, you should specify it here. This is optional so you don't need to create a model class if you don't want to.
extrastring
string[]
ObjectJoin table columns listed here are automatically joined to the related objects when they are fetched and automatically written to the join table instead of the related table on insert and update. The values can be aliased by providing an object {propertyName: 'columnName', otherPropertyName: 'otherColumnName'} instead of array See this recipe for more info.
modifyfunction(QueryBuilder)
string
objectOptional modifier for the join table query. If specified as a function, it will be called each time before fetching the relation. If specified as a string, modifier with specified name will be applied each time when fetching the relation. If specified as an object, it will be used as an additional query parameter - e. g. passing {name: 'Jenny'} would additionally narrow fetched rows to the ones with the name 'Jenny'.
filterfunction(QueryBuilder)
string
objectAlias for modify.
beforeInsertfunction(ModelQueryContext)Optional insert hook that is called for each inserted join table model instance. This function can be async.

type ModelOptions

PropertyTypeDescription
patchbooleanIf true the json is treated as a patch and the required field of the json schema is ignored in the validation. This allows us to create models with a subset of required properties for patch operations.
skipValidationbooleanIf true the json schema validation is skipped
oldobjectThe old values for methods like $beforeUpdate and $beforeValidate.

type CloneOptions

PropertyTypeDescription
shallowbooleanIf true, relations are ignored

type ToJsonOptions

PropertyTypeDescription
shallowbooleanIf true, relations are ignored. Default is false.
virtualsboolean
string[]If false, virtual attributes are omitted from the output. Default is true. You can also pass an array of property names and only those virtual properties get picked. You can even pass in property/function names that are not included in the static virtualAttributes array.

type GraphOptions

PropertyTypeDescription
minimizebooleanIf true the aliases of the joined tables and columns created by withGraphJoined are minimized. This is sometimes needed because of identifier length limitations of some database engines. objection throws an exception when a query exceeds the length limit. You need to use this only in those cases.
separatorstringSeparator between relations in nested withGraphJoined query. Defaults to :. Dot (.) cannot be used at the moment because of the way knex parses the identifiers.
aliasesObjectAliases for relations in a withGraphJoined query. Defaults to an empty object.
joinOperationstringWhich join type to use ['leftJoin', 'innerJoin', 'rightJoin', ...] or any other knex join method name. Defaults to leftJoin.
maxBatchSizeintegerFor how many parents should a relation be fetched using a single query at a time. If you set this to 1 then a separate query is used for each parent to fetch a relation. For example if you want to fetch pets for 5 persons, you get five queries (one for each person). Setting this to 1 will allow you to use stuff like limit and aggregate functions in modifyGraph and other graph modifiers. This can be used to replace the naiveEager objection 1.x had.

type UpsertGraphOptions

PropertyTypeDescription
relateboolean
string[]If true, relations are related instead of inserted. Relate functionality can be enabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
unrelateboolean
string[]If true, relations are unrelated instead of deleted. Unrelate functionality can be enabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
insertMissingboolean
string[]If true, models that have identifiers and are not found in the database, are inserted. By default this is false and an error is thrown. This functionality can be enabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
updateboolean
string[]If true, update operations are performed instead of patch when altering existing models, affecting the way the data is validated. With update operations, all required fields need to be present in the data provided. This functionality can be enabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
noInsertboolean
string[]If true, no inserts are performed. Inserts can be disabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
noUpdateboolean
string[]If true, no updates are performed. Updates can be disabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
noDeleteboolean
string[]If true, no deletes are performed. Deletes can be disabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
noRelateboolean
string[]If true, no relates are performed. Relate operations can be disabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
noUnrelateboolean
string[]If true, no unrelate operations are performed. Unrelate operations can be disabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
allowRefsbooleanThis needs to be true if you want to use #ref in your graphs. See this section for #ref usage examples.

type InsertGraphOptions

PropertyTypeDescription
relateboolean
string[]If true, models with an id are related instead of inserted. Relate functionality can be enabled for a subset of relations of the graph by providing a list of relation expressions. See the examples here.
allowRefsbooleanThis needs to be true if you want to use #ref in your graphs. See this section for #ref usage examples.

type FetchGraphOptions

PropertyTypeDescription
transactionknex
TransactionOptional transaction or knex instance for the query. This can be used to specify a transaction or even a different database.
 skipFetchedbooleanIf true, only fetch relations that don't yet exist in the object.

type TableMetadataFetchOptions

PropertyTypeDescription
tablestringA custom table name. If not given, Model.tableName is used.
knexknex
TransactionA knex instance or a transaction

type TableMetadataOptions

PropertyTypeDescription
tablestringA custom table name. If not given, Model.tableName is used.

type TableMetadata

PropertyTypeDescription
columnsstring[]Names of all the columns in a table.

type StaticHookArguments

PropertyTypeDescription
itemsModel[]Items for which the query was started. For example in case of an instance query person.$query() or person.$relatedQuery('pets') items would equal [person]. In case of Person.relatedQuery('pets').for([matt, jennifer]) items would equal [matt, jennifer]. In many cases like Person.query() or Person.query().findById(1) this array is empty. It's only populated when the query has been explicitly started for a set of model instances.
inputItemsModel[]Items that were passed as an input for the query. For example in case of Person.query().insert(person) or Person.query().patch(person) inputItems would equal [person].
asFindQuery() => QueryBuilderA function that returns a query builder that can be used to fetch the items that were/would get affected by the query being executed. Modifying this query builder doesn't affect the query being executed. For example calling await asFindQuery().select('id') in a beforeDelete hook would get you the identifiers of all the items that will get deleted by the query. This query is automatically executed inside any existing transaction. This query builder always returns an array even if the query being executed would return an object, a number or something else.
transactionknex
TransactionIf the query being executed has a transaction, this property will contain it. Otherwise this holds the knex instance installed for the query. Either way, this can and should be passed to any queries executed in the static hooks.
contextobjectThe context of the query. See context.
relationRelationIf the query is for a relation, this property holds the Relation object. For example when you call person.$relatedQuery('pets) or Person.relatedQuery('movies') the relation will be a relation object for pets and movies relation of Person respectively.
cancelQueryfunction(any)Cancels the query being executed. You can pass an arugment for the function and that value will be the result of the query.
resultany[]The result of the query. Only available in after* hooks.

type FieldExpression

Field expressions are strings that allow you to refer to JSONB fields inside columns.

Syntax: <column reference>[:<json field reference>]

e.g. persons.jsonColumnName:details.names[1] would refer to value 'Second' in column persons.jsonColumnName which has { details: { names: ['First', 'Second', 'Last'] } } object stored in it.

First part <column reference> is compatible with column references used in knex e.g. MyFancyTable.tributeToThBestColumnNameEver.

Second part describes a path to an attribute inside the referred column. It is optional and it always starts with colon which follows directly with first path element. e.g. Table.jsonObjectColumnName:jsonFieldName or Table.jsonArrayColumn:[321].

Syntax supports [<key or index>] and .<key or index> flavors of reference to json keys / array indexes:

e.g. both Table.myColumn:[1][3] and Table.myColumn:1.3 would access correctly both of the following objects [null, [null,null,null, "I was accessed"]] and { "1": { "3" : "I was accessed" } }

Caveats when using special characters in keys:

  1. objectColumn.key This is the most common syntax, good if you are not using dots or square brackets [] in your json object key name.
  2. Keys containing dots objectColumn:[keywith.dots] Column { "keywith.dots" : "I was referred" }
  3. Keys containing square brackets column['[]'] { "[]" : "This is getting ridiculous..." }
  4. Keys containing square brackets and quotes objectColumn:['Double."Quote".[]'] and objectColumn:["Sinlge.'Quote'.[]"] Column { "Double.\"Quote\".[]" : "I was referred", "Sinlge.'Quote'.[]" : "Mee too!" }
  5. Keys containing dots, square brackets, single quotes and double quotes in one json key is not currently supported

There are some special methods that accept FieldExpression strings directly, like whereJsonSupersetOf but you can use FieldExpressions anywhere with ref. Here's an example:

js
const { ref } = require('objection');

await Person.query()
  .select([
    'id',
    ref('persons.jsonColumn:details.name').castText().as('name'),
    ref('persons.jsonColumn:details.age').castInt().as('age'),
  ])
  .join(
    'someTable',
    ref('persons.jsonColumn:details.name').castText(),
    '=',
    ref('someTable.name')
  )
  .where('age', '>', ref('someTable.ageLimit'));

In the above example, we assume persons table has a column named jsonColumn of type jsonb (only works on postgres).

type RelationExpression

Relation expression is a simple DSL for expressing relation trees.

These strings are all valid relation expressions:

  • children
  • children.movies
  • [children, pets]
  • [children.movies, pets]
  • [children.[movies, pets], pets]
  • [children.[movies.actors.[children, pets], pets], pets]
  • [children as kids, pets(filterDogs) as dogs]

There are two tokens that have special meaning: * and ^. * means "all relations recursively" and ^ means "this relation recursively".

For example children.* means "relation children and all its relations, and all their relations and ...".

::: warning The * token must be used with caution or you will end up fetching your entire database. :::

Expression parent.^ is equivalent to parent.parent.parent.parent... up to the point a relation no longer has results for the parent relation. The recursion can be limited to certain depth by giving the depth after the ^ character. For example parent.^3 is equal to parent.parent.parent.

Relations can be aliased using the as keyword.

For example the expression children.[movies.actors.[pets, children], pets] represents a tree:

              children
              (Person)
                 |
         -----------------
         |               |
       movies           pets
      (Movie)         (Animal)
         |
       actors
      (Person)
         |
    -----------
    |         |
   pets    children
 (Animal)  (Person)

The model classes are shown in parenthesis. When given to withGraphFetched method, this expression would fetch all relations as shown in the tree above:

js
const people = await Person.query().withGraphFetched(
  'children.[movies.actors.[pets, children], pets]'
);

// All persons have the given relation tree fetched.
console.log(people[0].children[0].movies[0].actors[0].pets[0].name);

Relation expressions can have arguments. Arguments are used to refer to modifier functions (either global or local. Arguments are listed in parenthesis after the relation names like this:

js
Person.query().withGraphFetched(
  `children(arg1, arg2).[movies.actors(arg3), pets]`
);

You can spread relation expressions to multiple lines and add whitespace:

js
Person.query().withGraphFetched(`[
    children.[
      pets,
      movies.actors.[
        pets,
        children
      ]
    ]
  ]`);

Relation expressions can be aliased using as keyword:

js
Person.query().withGraphFetched(`[
    children as kids.[
      pets(filterDogs) as dogs,
      pets(filterCats) as cats,

      movies.actors.[
        pets,
        children as kids
      ]
    ]
  ]`);

RelationExpression object notation

In addition to the string expressions, a more verbose object notation can also be used.

The string expression in the comment is equivalent to the object expression below it:

js
// `children`
{
  children: true;
}
js
// `children.movies`
{
  children: {
    movies: true;
  }
}
js
// `[children, pets]`
{
  children: true;
  pets: true;
}
js
// `[children.[movies, pets], pets]`
{
  children: {
    movies: true,
    pets: true
  }
  pets: true
}
js
// `parent.^`
{
  parent: {
    $recursive: true;
  }
}
js
// `parent.^5`
{
  parent: {
    $recursive: 5;
  }
}
js
// `parent.*`
{
  parent: {
    $allRecursive: true;
  }
}
js
// `[children as kids, pets(filterDogs) as dogs]`
{
  kids: {
    $relation: 'children'
  },

  dogs: {
    $relation: 'pets',
    $modify: ['filterDogs']
  }
}

type TransactionObject

This is nothing more than a knex transaction object. It can be used as a knex query builder, it can be passed to objection queries and models can be bound to it

See the section about transactions for more info and examples.

Instance Methods

commit()

js
const promise = trx.commit();

Call this method to commit the transaction. This only needs to be called if you use transaction.start() method.

rollback()

js
const promise = trx.rollback(error);

Call this method to rollback the transaction. This only needs to be called if you use transaction.start() method. You need to pass the error to the method as the only argument.

class ValidationError

js
const { ValidationError } = require('objection');

throw new ValidationError({ type, message, data });

For each key, a list of errors is given. Each error contains the default message (as returned by the validator), an optional keyword string to identify the validation rule which didn't pass and a param object which optionally contains more details about the context of the validation error.

If type is anything else but "ModelValidation", data can be any object that describes the error.

Error of this class is thrown by default if validation of any input fails. By input we mean any data that can come from the outside world, like model instances (or POJOs), relation expressions object graphs etc.

You can replace this error by overriding Model.createValidationError() method.

See the error handling recipe for more info.

PropertyTypeDescription
statusCodenumberHTTP status code for interop with express error handlers and other libraries that search for status code from errors.
typestringOne of "ModelValidation", "RelationExpression", "UnallowedRelation" and "InvalidGraph". This can be any string for your own custom errors. The listed values are used internally by objection.
dataobjectThe content of this property is documented below for "ModelValidation" errors. For other types, this can be any data.

If type is "ModelValidation" then data object should follow this pattern:

js
{
  key1: [{
    message: '...',
    keyword: 'required',
    params: null
  }, {
    message: '...',
    keyword: '...',
    params: {
      ...
    }
  }, ...],

  key2: [{
    message: '...',
    keyword: 'minLength',
    params: {
      limit: 1,
      ...
    }
  }, ...],

  ...
}

class NotFoundError

js
const { NotFoundError } = require('objection');

throw new NotFoundError(data);

Error of this class is thrown by default by throwIfNotFound()

You can replace this error by overriding Model.createNotFoundError() method.

See the error handling recipe for more info.

class Relation

Relation is a parsed and normalized instance of a RelationMapping. Relations can be accessed using the getRelations method.

Relation holds a RelationProperty instance for each property that is used to create the relationship between two tables.

Relation is actually a base class for all relation types BelongsToOneRelation, HasManyRelation etc. You can use instanceof to determine the type of the relations (see the example on the right). Note that HasOneRelation is a subclass of HasManyRelation and HasOneThroughRelation is a subclass of ManyToManyRelation. Arrange your instanceof checks accordingly.

PropertyTypeDescription
namestringName of the relation. For example pets or children.
ownerModelClassfunctionThe model class that has defined the relation.
relatedModelClassfunctionThe model class of the related objects.
ownerPropRelationPropertyThe relation property in the ownerModelClass.
relatedPropRelationPropertyThe relation property in the relatedModelClass.
joinModelClassfunctionThe model class representing the join table. This class is automatically generated by Objection if none is provided in the join.through.modelClass setting of the relation mapping, see RelationThrough.
joinTablestringThe name of the join table (only for ManyToMany and HasOneThrough relations).
joinTableOwnerPropRelationPropertyThe join table property pointing to ownerProp (only for ManyToMany and HasOneThrough relations).
joinTableRelatedPropRelationPropertyThe join table property pointing to relatedProp (only for ManyToMany and HasOneThrough relations).

Note that Relation instances are actually instances of the relation classes used in relationMappings. For example:

js
class Person extends Model {
  static get relationMappings() {
    return {
      pets: {
        relation: Model.HasManyRelation,
        modelClass: Animal,
        join: {
          from: 'persons.id',
          to: 'animals.ownerId',
        },
      },
    };
  }
}

const relations = Person.getRelations();

console.log(relations.pets instanceof Model.HasManyRelation); // --> true
console.log(relations.pets.name); // --> pets
console.log(relations.pets.ownerProp.cols); // --> ['id']
console.log(relations.pets.relatedProp.cols); // --> ['ownerId']

class RelationProperty

Represents a property that is used to create relationship between two tables. A single RelationProperty instance can represent composite key. In addition to a table column, A RelationProperty can represent a nested field inside a column (for example a jsonb column).

Properties

PropertyTypeDescription
sizenumberThe number of columns. In case of composite key, this is greater than one.
modelClassfunctionThe model class that owns the property.
propsstring[]The column names converted to "external" format. For example if modelClass defines a snake_case to camelCase conversion, these names are in camelCase. Note that a RelationProperty may actually point to a sub-properties of the columns in case they are of json or some other non-scalar type. This array always contains only the converted column names. Use getProp(obj, idx) method to get the actual value from an object.
colsstring[]The column names in the database format. For example if modelClass defines a snake_case to camelCase conversion, these names are in snake_case. Note that a RelationProperty may actually point to a sub-properties of the columns in case they are of json or some other non-scalar type. This array always contains only the column names.

Methods

getProp()

js
const value = property.getProp(obj, index);

Gets this property's index:th value from an object. For example if the property represents a composite key [a, b.d.e, c] and obj is {a: 1, b: {d: {e: 2}}, c: 3} then getProp(obj, 1) would return 2.

setProp()

js
property.setProp(obj, index, value);

Sets this property's index:th value in an object. For example if the property represents a composite key [a, b.d.e, c] and obj is {a: 1, b: {d: {e: 2}}, c: 3} then setProp(obj, 1, 'foo') would mutate obj into {a: 1, b: {d: {e: 'foo'}}, c: 3}.

fullCol()

js
const col = property.fullCol(builder, index);

Returns the property's index:th column name with the correct table reference. Something like "Table.column". The first argument must be an objection QueryBuilder instance.

ref()

js
const ref = property.ref(builder, index);

Allows you to do things like this:

js
const builder = Person.query();
const ref = property.ref(builder, 0);
builder.where(ref, '>', 10);

Returns a ReferenceBuilder instance that points to the index:th column.

patch()

js
property.patch(patchObj, index, value);

Allows you to do things like this:

js
const builder = Person.query();
const patch = {};
property.patch(patch, 0, 'foo');
builder.patch(patch);

Appends an update operation for the index:th column into patchObj object.

class ReferenceBuilder

An instance of this is returned from the ref helper function.

Instance Methods

castText()

Cast reference to sql type text.

castInt()

Cast reference to sql type integer.

castBigInt()

Cast reference to sql type bigint.

castFloat()

Cast reference to sql type float.

castDecimal()

Cast reference to sql type decimal.

castReal()

Cast reference to sql type real.

castBool()

Cast reference to sql type boolean.

castTo()

Give custom type to which referenced value is cast to.

.castTo('mytype') --> CAST(?? as mytype)

castJson()

In addition to other casts wrap reference to_jsonb() function so that final value reference will be json type.

as()

Gives an alias for the reference .select(ref('age').as('yougness'))

from()

Specifies that table of the reference.

See this for some examples.

class ValueBuilder

An instance of this is returned from the val helper function. If an object is given as a value, it is cast to json by default.

Instance Methods

castText()

Cast to sql type text.

castInt()

Cast to sql type integer.

castBigInt()

Cast to sql type bigint.

castFloat()

Cast to sql type float.

castDecimal()

Cast to sql type decimal.

castReal()

Cast to sql type real.

castBool()

Cast to sql type boolean.

castTo()

Give custom type to which referenced value is cast to.

.castTo('mytype') --> CAST(?? as mytype)

castJson()

Converts the value to json (jsonb in case of postgresql). The default cast type for object values.

asArray()

Converts the value to an array.

val([1, 2, 3]).asArray() --> ARRAY[?, ?, ?]

Can be used in conjuction with castTo.

val([1, 2, 3]).asArray().castTo('real[]') -> CAST(ARRAY[?, ?, ?] AS real[])

as()

Gives an alias for the reference .select(ref('age').as('yougness'))

class RawBuilder

An instance of this is returned from the raw helper function.

Instance Methods

as()

Gives an alias for the raw expression .select(raw('concat(foo, bar)').as('fooBar')).

You should use this instead of inserting the alias to the SQL to give objection more information about the query. Some edge cases, like using raw in select inside a withGraphJoined modifier won't work unless you use this method.

class FunctionBuilder

An instance of this is returned from the fn helper function.

Instance Methods

as()

Gives an alias for the raw expression .select(fn('concat', 'foo', 'bar').as('fooBar')).

You should use this instead of inserting the alias to the SQL to give objection more information about the query. Some edge cases, like using fn in select inside a withGraphJoined modifier won't work unless you use this method.

class Validator

js
const { Validator } = require('objection');

Abstract class from which model validators must be inherited. See the example for explanation. Also check out the createValidator method.

Examples

js
const { Validator } = require('objection');

class MyCustomValidator extends Validator {
  validate(args) {
    // The model instance. May be empty at this point.
    const model = args.model;

    // The properties to validate. After validation these values will
    // be merged into `model` by objection.
    const json = args.json;

    // `ModelOptions` object. If your custom validator sets default
    // values, you need to check the `opt.patch` boolean. If it is true
    // we are validating a patch object and the defaults should not be set.
    const opt = args.options;

    // A context object shared between the validation methods. A new
    // object is created for each validation operation. You can store
    // any data here.
    const ctx = args.ctx;

    // Do your validation here and throw any exception if the
    // validation fails.
    doSomeValidationAndThrowIfFails(json);

    // You need to return the (possibly modified) json.
    return json;
  }

  beforeValidate(args) {
    // Takes the same arguments as `validate`. Usually there is no need
    // to override this.
    return super.beforeValidate(args);
  }

  afterValidate(args) {
    // Takes the same arguments as `validate`. Usually there is no need
    // to override this.
    return super.afterValidate(args);
  }
}

const { Model } = require('objection');

// Override the `createValidator` method of a `Model` to use the
// custom validator.
class BaseModel extends Model {
  static createValidator() {
    return new MyCustomValidator();
  }
}

class AjvValidator

js
const { AjvValidator } = require('objection');

The default Ajv based json schema validator. You can override the createValidator method of Model like in the example to modify the validator.

Examples

js
const { Model, AjvValidator } = require('objection');

class BaseModel extends Model {
  static createValidator() {
    return new AjvValidator({
      onCreateAjv: (ajv) => {
        // Here you can modify the `Ajv` instance.
      },
      options: {
        allErrors: true,
        validateSchema: false,
        ownProperties: true,
        v5: true,
      },
    });
  }
}