@eqxjs/joi-schema-builder
v1.0.1
Published
A template for creating libraries in the @eqxjs ecosystem.
Keywords
Readme
Joi Schema Builder
Table of Contents
Description
A declarative and type-safe builder library for creating Joi validation schemas from configuration objects. This library simplifies the process of building complex Joi schemas by providing a clean, structured approach with full TypeScript support.
Instead of imperatively chaining Joi methods, you can define your validation schemas as plain configuration objects, making them easier to maintain, test, and reuse across your application.
Features
- Declarative Schema Definition: Define validation schemas using simple configuration objects
- Type-Safe: Full TypeScript support with comprehensive type definitions
- Comprehensive Validation Support: Supports all major Joi data types:
- String (with email, URI, UUID, IP, domain, hex, base64, credit card validations)
- Number (with range, precision, integer, positive/negative validations)
- Boolean (with custom truthy/falsy values)
- Date (with range and ISO format validations)
- Array (with items, uniqueness, ordering, and sorting)
- Object (with nested schemas, patterns, and dependencies)
- Nested Objects: Support for complex nested object structures
- Common Field Properties: Shared validation properties like required, optional, default, min, max, custom messages
- NestJS Integration: Works seamlessly with NestJS dependency injection
- Lightweight: Minimal overhead on top of Joi
Installation
To install the library, use the following command:
npm install @eqxjs/joi-schema-builder joior with yarn:
yarn add @eqxjs/joi-schema-builder joiNote: joi is a peer dependency and must be installed alongside this library.
Usage
Basic Example
Here's a simple example of creating a validation schema:
import {
SchemaBuilder,
FieldType,
ISchemaDefinition,
} from '@eqxjs/joi-schema-builder';
const schemaBuilder = new SchemaBuilder();
const userSchemaDefinition: ISchemaDefinition<FieldType> = {
fields: {
username: {
type: FieldType.STRING,
required: true,
min: 3,
max: 30,
alphanum: true,
message: 'Username must be alphanumeric and between 3-30 characters',
},
email: {
type: FieldType.STRING,
required: true,
email: true,
message: 'Valid email address is required',
},
age: {
type: FieldType.NUMBER,
required: true,
integer: true,
min: 18,
max: 120,
message: 'Age must be between 18 and 120',
},
isActive: {
type: FieldType.BOOLEAN,
default: true,
optional: true,
},
},
description: 'User registration schema',
allowUnknown: false,
};
const userSchema = schemaBuilder.build(userSchemaDefinition);
// Use the schema to validate data
const result = userSchema.validate({
username: 'john_doe',
email: '[email protected]',
age: 25,
});NestJS Integration
Register the SchemaBuilder as a provider in your NestJS module:
import { Module } from '@nestjs/common';
import { SchemaBuilder } from '@eqxjs/joi-schema-builder';
import { UserService } from './user.service';
import { UserController } from './user.controller';
@Module({
controllers: [UserController],
providers: [SchemaBuilder, UserService],
exports: [SchemaBuilder],
})
export class UserModule {}Use it in a service:
import { Injectable } from '@nestjs/common';
import {
SchemaBuilder,
FieldType,
ISchemaDefinition,
} from '@eqxjs/joi-schema-builder';
@Injectable()
export class UserService {
private userSchema;
constructor(private readonly schemaBuilder: SchemaBuilder) {
const schemaDefinition: ISchemaDefinition<FieldType> = {
fields: {
username: {
type: FieldType.STRING,
required: true,
min: 3,
max: 30,
},
email: {
type: FieldType.STRING,
required: true,
email: true,
},
},
};
this.userSchema = this.schemaBuilder.build(schemaDefinition);
}
async createUser(userData: any) {
const { error, value } = this.userSchema.validate(userData);
if (error) {
throw new BadRequestException(error.details);
}
// Process validated data
return value;
}
}Advanced Examples
String Validations
const emailField = {
type: FieldType.STRING,
email: true,
emailOptions: {
allowUnicode: true,
minDomainSegments: 2,
tlds: { allow: ['com', 'net', 'org'] },
},
required: true,
};
const urlField = {
type: FieldType.STRING,
uri: true,
uriOptions: {
scheme: ['http', 'https'],
allowRelative: false,
},
};
const uuidField = {
type: FieldType.STRING,
uuid: true,
guidOptions: {
version: ['uuidv4'],
},
};Number Validations
const priceField = {
type: FieldType.NUMBER,
positive: true,
precision: 2,
min: 0,
max: 999999.99,
required: true,
};
const portField = {
type: FieldType.NUMBER,
port: true,
integer: true,
};
const percentageField = {
type: FieldType.NUMBER,
min: 0,
max: 100,
multiple: 5, // Must be multiple of 5
};Array Validations
const tagsField = {
type: FieldType.ARRAY,
items: [
{
type: FieldType.STRING,
min: 1,
max: 50,
},
],
min: 1,
max: 10,
unique: true,
required: true,
};
const coordinatesField = {
type: FieldType.ARRAY,
ordered: [
{ type: FieldType.NUMBER, min: -90, max: 90 }, // latitude
{ type: FieldType.NUMBER, min: -180, max: 180 }, // longitude
],
length: 2,
};Nested Object Validations
const addressSchemaDefinition: ISchemaDefinition<FieldType> = {
fields: {
street: {
type: FieldType.STRING,
required: true,
},
city: {
type: FieldType.STRING,
required: true,
},
zipCode: {
type: FieldType.STRING,
pattern: '^[0-9]{5}$',
required: true,
},
coordinates: {
type: FieldType.OBJECT,
properties: {
latitude: {
type: FieldType.NUMBER,
min: -90,
max: 90,
required: true,
},
longitude: {
type: FieldType.NUMBER,
min: -180,
max: 180,
required: true,
},
},
required: false,
},
},
};
const schema = schemaBuilder.build(addressSchemaDefinition);Date Validations
const birthdateField = {
type: FieldType.DATE,
max: new Date(), // Cannot be in the future
iso: true,
required: true,
};
const appointmentField = {
type: FieldType.DATE,
greater: new Date(), // Must be in the future
less: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), // Within 1 year
required: true,
};Boolean with Custom Truthy/Falsy
const acceptTermsField = {
type: FieldType.BOOLEAN,
truthy: ['yes', 'true', '1', 1],
falsy: ['no', 'false', '0', 0],
required: true,
};Comprehensive Method Examples
String Field Methods
// Email validation with options
const emailField = {
type: FieldType.STRING,
email: true,
emailOptions: {
allowUnicode: true,
allowUnderscore: true,
minDomainSegments: 2,
maxDomainSegments: 3,
tlds: { allow: ['com', 'net', 'org', 'edu'] },
multiple: false,
},
required: true,
};
// Domain validation
const domainField = {
type: FieldType.STRING,
domain: true,
domainOptions: {
allowFullyQualified: true,
allowUnicode: false,
minDomainSegments: 2,
tlds: { deny: ['test', 'localhost'] },
},
};
// URI/URL validation with scheme
const uriField = {
type: FieldType.STRING,
uri: true,
uriOptions: {
scheme: ['http', 'https', 'ftp'],
allowRelative: false,
allowQuerySquareBrackets: true,
domain: {
minDomainSegments: 2,
tlds: { allow: true },
},
},
};
// IP address validation
const ipField = {
type: FieldType.STRING,
ip: true,
ipOptions: {
version: ['ipv4', 'ipv6'],
cidr: 'optional',
},
};
// UUID/GUID validation
const uuidField = {
type: FieldType.STRING,
uuid: true,
guidOptions: {
version: ['uuidv4', 'uuidv5'],
separator: '-',
},
};
// Hexadecimal validation
const hexField = {
type: FieldType.STRING,
hex: true,
hexOptions: {
byteAligned: true,
prefix: 'optional', // Allows '0x' prefix
},
};
// Base64 validation
const base64Field = {
type: FieldType.STRING,
base64: true,
base64Options: {
paddingRequired: true,
urlSafe: false,
},
};
// Data URI validation
const dataUriField = {
type: FieldType.STRING,
dataUri: true,
dataUriOptions: {
paddingRequired: false,
},
};
// Credit card validation
const creditCardField = {
type: FieldType.STRING,
creditCard: true,
required: true,
};
// Hostname validation
const hostnameField = {
type: FieldType.STRING,
hostname: true,
};
// ISO date string validation
const isoDateField = {
type: FieldType.STRING,
isoDate: true,
};
// ISO duration validation
const isoDurationField = {
type: FieldType.STRING,
isoDuration: true,
};
// Pattern/Regex validation
const patternField = {
type: FieldType.STRING,
pattern: '^[A-Z]{2}[0-9]{4}$',
message: 'Must be 2 uppercase letters followed by 4 digits',
};
// Alphanumeric validation
const alphanumField = {
type: FieldType.STRING,
alphanum: true,
min: 5,
max: 20,
};
// Token validation (alphanumeric + underscore)
const tokenField = {
type: FieldType.STRING,
token: true,
};
// Case transformations
const upperCaseField = {
type: FieldType.STRING,
case: 'upper',
trim: true,
};
const lowerCaseField = {
type: FieldType.STRING,
lowercase: true,
trim: true,
};
// String normalization
const normalizedField = {
type: FieldType.STRING,
normalize: 'NFC',
trim: true,
};
// String replacement
const replacementField = {
type: FieldType.STRING,
replace: [
{ pattern: /\s+/g, replacement: ' ' },
{ pattern: /_/g, replacement: '-' },
],
};
// Truncate to max length
const truncateField = {
type: FieldType.STRING,
max: 100,
truncate: true,
};Number Field Methods
// Integer validation
const integerField = {
type: FieldType.NUMBER,
integer: true,
min: 1,
max: 1000,
};
// Positive number validation
const positiveField = {
type: FieldType.NUMBER,
positive: true,
precision: 2,
};
// Negative number validation
const negativeField = {
type: FieldType.NUMBER,
negative: true,
};
// Sign requirement
const signField = {
type: FieldType.NUMBER,
sign: 'positive',
};
// Greater than validation
const greaterField = {
type: FieldType.NUMBER,
greater: 0,
max: 100,
};
// Less than validation
const lessField = {
type: FieldType.NUMBER,
less: 1000,
min: 0,
};
// Multiple validation
const multipleField = {
type: FieldType.NUMBER,
multiple: 5,
message: 'Must be a multiple of 5',
};
// Precision validation
const precisionField = {
type: FieldType.NUMBER,
precision: 2,
positive: true,
};
// Port validation
const portField = {
type: FieldType.NUMBER,
port: true,
};
// Unsafe number (outside JS safe range)
const unsafeField = {
type: FieldType.NUMBER,
unsafe: true,
};Boolean Field Methods
// Custom truthy/falsy values
const customBoolField = {
type: FieldType.BOOLEAN,
truthy: ['yes', 'y', 'true', '1', 1, true],
falsy: ['no', 'n', 'false', '0', 0, false],
sensitive: true, // Case sensitive
};
// With default value
const defaultBoolField = {
type: FieldType.BOOLEAN,
default: false,
optional: true,
};
// With custom validation
const customValidationField = {
type: FieldType.BOOLEAN,
custom: (value, helpers) => {
if (value === false) {
return helpers.error('any.invalid');
}
return value;
},
};Date Field Methods
// ISO format validation
const isoDateField = {
type: FieldType.DATE,
iso: true,
required: true,
};
// Date range validation
const dateRangeField = {
type: FieldType.DATE,
min: new Date('2020-01-01'),
max: new Date('2025-12-31'),
};
// Greater than validation
const futureField = {
type: FieldType.DATE,
greater: new Date(),
message: 'Date must be in the future',
};
// Less than validation
const pastField = {
type: FieldType.DATE,
less: new Date(),
message: 'Date must be in the past',
};
// Timestamp validation
const timestampField = {
type: FieldType.DATE,
timestamp: 'unix', // 'unix' or 'javascript'
};
// Age verification (18+ years)
const birthDateField = {
type: FieldType.DATE,
max: new Date(Date.now() - 18 * 365 * 24 * 60 * 60 * 1000),
iso: true,
required: true,
};Array Field Methods
// Array with item validation
const stringArrayField = {
type: FieldType.ARRAY,
items: [
{
type: FieldType.STRING,
min: 1,
max: 50,
},
],
min: 1,
max: 10,
unique: true,
};
// Ordered array (specific sequence)
const coordinatesField = {
type: FieldType.ARRAY,
ordered: [
{ type: FieldType.NUMBER, min: -90, max: 90 }, // latitude
{ type: FieldType.NUMBER, min: -180, max: 180 }, // longitude
],
length: 2,
};
// Array with uniqueness validation
const uniqueArrayField = {
type: FieldType.ARRAY,
items: [{ type: FieldType.NUMBER }],
unique: {
comparator: (a, b) => a === b,
options: {
ignoreUndefined: true,
},
},
};
// Sorted array
const sortedArrayField = {
type: FieldType.ARRAY,
items: [{ type: FieldType.NUMBER }],
sort: {
order: 'ascending',
},
};
// Sparse array (allows undefined)
const sparseArrayField = {
type: FieldType.ARRAY,
items: [{ type: FieldType.STRING }],
sparse: true,
min: 3,
max: 10,
};
// Single value to array conversion
const singleOrArrayField = {
type: FieldType.ARRAY,
items: [{ type: FieldType.STRING }],
single: true,
};
// Array with "has" validation
const hasItemField = {
type: FieldType.ARRAY,
items: [{ type: FieldType.NUMBER }],
has: { type: FieldType.NUMBER, positive: true },
};
// Complex nested array
const nestedArrayField = {
type: FieldType.ARRAY,
items: [
{
type: FieldType.OBJECT,
keys: {
id: { type: FieldType.NUMBER, required: true },
name: { type: FieldType.STRING, required: true },
tags: {
type: FieldType.ARRAY,
items: [{ type: FieldType.STRING }],
unique: true,
},
},
},
],
min: 1,
};Object Field Methods
// Object with nested keys
const userObjectField = {
type: FieldType.OBJECT,
keys: {
username: {
type: FieldType.STRING,
min: 3,
max: 30,
required: true,
},
email: {
type: FieldType.STRING,
email: true,
required: true,
},
age: {
type: FieldType.NUMBER,
integer: true,
min: 18,
},
},
};
// Object with unknown keys allowed
const flexibleObjectField = {
type: FieldType.OBJECT,
keys: {
id: { type: FieldType.NUMBER, required: true },
},
unknown: true,
};
// Object with pattern validation
const patternObjectField = {
type: FieldType.OBJECT,
pattern: [
{
regex: /^[a-z]+$/,
schema: { type: FieldType.STRING },
},
],
};
// Object with dependencies (AND)
const andDependencyField = {
type: FieldType.OBJECT,
keys: {
creditCard: { type: FieldType.STRING },
cvv: { type: FieldType.STRING },
expiryDate: { type: FieldType.STRING },
},
and: ['creditCard', 'cvv', 'expiryDate'],
};
// Object with OR dependency
const orDependencyField = {
type: FieldType.OBJECT,
keys: {
email: { type: FieldType.STRING, email: true },
phone: { type: FieldType.STRING },
},
or: ['email', 'phone'],
};
// Object with XOR dependency
const xorDependencyField = {
type: FieldType.OBJECT,
keys: {
password: { type: FieldType.STRING },
oauth: { type: FieldType.STRING },
},
xor: ['password', 'oauth'],
};
// Object with NAND dependency
const nandDependencyField = {
type: FieldType.OBJECT,
keys: {
freeShipping: { type: FieldType.BOOLEAN },
shippingCost: { type: FieldType.NUMBER },
},
nand: ['freeShipping', 'shippingCost'],
};
// Object with WITH dependency
const withDependencyField = {
type: FieldType.OBJECT,
keys: {
username: { type: FieldType.STRING },
password: { type: FieldType.STRING },
},
with: [
{
key: 'username',
peers: 'password',
},
],
};
// Object with WITHOUT dependency
const withoutDependencyField = {
type: FieldType.OBJECT,
keys: {
isAnonymous: { type: FieldType.BOOLEAN },
userId: { type: FieldType.NUMBER },
},
without: [
{
key: 'isAnonymous',
peers: 'userId',
},
],
};
// Object with key renaming
const renameObjectField = {
type: FieldType.OBJECT,
keys: {
user_name: { type: FieldType.STRING },
},
rename: [
{
from: 'userName',
to: 'user_name',
options: {
alias: false,
multiple: false,
override: false,
},
},
],
};
// Object with length validation
const exactKeysField = {
type: FieldType.OBJECT,
keys: {
x: { type: FieldType.NUMBER },
y: { type: FieldType.NUMBER },
},
length: 2,
};
// Object instance validation
const instanceField = {
type: FieldType.OBJECT,
instance: {
constructor: Date,
name: 'Date',
},
};Conditional Validation (When)
// String conditional based on another field
const conditionalStringField = {
type: FieldType.STRING,
when: {
refKey: {
ref: {
key: 'accountType',
},
},
options: {
switch: [
{
is: 'business',
then: { type: FieldType.STRING, min: 10, max: 100 },
},
{
is: 'personal',
then: { type: FieldType.STRING, min: 3, max: 50 },
},
],
otherwise: { type: FieldType.STRING, optional: true },
},
},
};
// Number conditional validation
const conditionalNumberField = {
type: FieldType.NUMBER,
when: {
refKey: {
ref: {
key: 'priceType',
},
},
options: {
switch: [
{
is: 'fixed',
then: { type: FieldType.NUMBER, valid: [10, 20, 50, 100] },
},
{
is: 'custom',
then: { type: FieldType.NUMBER, min: 1, max: 1000 },
},
],
},
},
};Reference Field
// Reference to another field
const passwordConfirmField = {
type: FieldType.REF,
ref: {
key: 'password',
options: {
adjust: (value) => value, // Optional adjustment function
},
},
};Complex Nested Schema Example
const complexSchemaDefinition: ISchemaDefinition<FieldType> = {
fields: {
user: {
type: FieldType.OBJECT,
keys: {
id: {
type: FieldType.NUMBER,
integer: true,
positive: true,
required: true,
},
profile: {
type: FieldType.OBJECT,
keys: {
firstName: {
type: FieldType.STRING,
min: 2,
max: 50,
trim: true,
required: true,
},
lastName: {
type: FieldType.STRING,
min: 2,
max: 50,
trim: true,
required: true,
},
email: {
type: FieldType.STRING,
email: true,
emailOptions: {
tlds: { allow: ['com', 'org', 'net'] },
},
required: true,
},
birthDate: {
type: FieldType.DATE,
max: new Date(Date.now() - 18 * 365 * 24 * 60 * 60 * 1000),
iso: true,
},
},
required: true,
},
roles: {
type: FieldType.ARRAY,
items: [
{
type: FieldType.STRING,
valid: ['admin', 'user', 'moderator'],
},
],
unique: true,
min: 1,
required: true,
},
settings: {
type: FieldType.OBJECT,
keys: {
notifications: {
type: FieldType.BOOLEAN,
default: true,
},
theme: {
type: FieldType.STRING,
valid: ['light', 'dark', 'auto'],
default: 'auto',
},
},
unknown: false,
},
metadata: {
type: FieldType.OBJECT,
unknown: true,
optional: true,
},
},
required: true,
},
},
description: 'Complex user schema with nested objects and arrays',
allowUnknown: false,
};
const complexSchema = schemaBuilder.build(complexSchemaDefinition);API Reference
SchemaBuilder
The main class for building Joi schemas.
Methods
build(schemaDef: ISchemaDefinition<FieldType>): Joi.ObjectSchemaBuilds a Joi ObjectSchema from a schema definition.
Field Types
Available field types in the FieldType enum:
| Property | Value | Description |
| --------- | ----------- | --------------------------- |
| STRING | 'string' | String validation |
| NUMBER | 'number' | Number validation |
| BOOLEAN | 'boolean' | Boolean validation |
| DATE | 'date' | Date validation |
| ARRAY | 'array' | Array validation |
| OBJECT | 'object' | Object validation |
| ANY | 'any' | Any type (permissive) |
| REF | 'ref' | Reference field validateion |
Common Field Properties
All field types support these common properties:
required- Field is requiredoptional- Field is optionaldefault- Default value if undefinedmin/max/length- Size constraintsallow- Explicitly allowed valuesvalid- Whitelist of valid valuesinvalid- Blacklist of invalid valuesmessage- Custom error messagedescription- Field descriptionexample- Example valuelabel- Custom label for error messagesmeta- Metadata attachment
Field Type Interfaces
Common Field Definition (ICommonFieldDefinition)
Base interface inherited by all field types:
| Property | Type | Required | Description |
| ------------- | -------------------------------------------------- | -------- | ---------------------------------------------------------------------------- |
| properties | { [propName: string]: TExtendedFieldDefinition } | No | Nested properties for object-type fields |
| allow | any[] | No | Values that are explicitly allowed even if they would fail other validations |
| concat | any | No | Additional schema to merge with this schema |
| disallow | any[] | No | Values that are explicitly disallowed |
| equal | any[] | No | Values that must be equal to one of the specified values |
| exist | boolean | No | Whether the field must exist (cannot be undefined) |
| forbidden | boolean | No | Whether the field is forbidden (cannot be present) |
| invalid | any[] | No | Values that are explicitly invalid |
| message | string | No | Custom error message for validation failures |
| not | any[] | No | Values that are explicitly not allowed |
| optional | boolean | No | Whether the field is optional |
| required | boolean | No | Whether the field is required |
| strict | boolean | No | Whether strict validation is enabled (no type coercion) |
| valid | any[] | No | Values that are explicitly valid (whitelist) |
| min | number | No | Minimum value/length constraint |
| max | number | No | Maximum value/length constraint |
| length | number | No | Exact length constraint |
| meta | any | No | Metadata to attach to the schema |
| description | string | No | Description of the field |
String Field Definition (IStringFieldDefinition)
Extends ICommonFieldDefinition:
| Property | Type | Required | Description |
| --------------- | -------------------- | -------- | ---------------------------------------------------------------------- |
| type | 'string' | Yes | Field type identifier |
| pattern | RegExp \| string | No | Regular expression pattern for validation |
| regex | RegExp \| string | No | Alias for pattern |
| alphanum | boolean | No | Requires alphanumeric characters only |
| token | boolean | No | Requires alphanumeric and underscore characters only |
| email | boolean | No | Validates as email address |
| emailOptions | object | No | Email validation options (allowUnicode, minDomainSegments, tlds, etc.) |
| domain | boolean | No | Validates as domain name |
| domainOptions | object | No | Domain validation options |
| uri | boolean | No | Validates as URI/URL |
| uriOptions | object | No | URI validation options (scheme, allowRelative, etc.) |
| ip | boolean | No | Validates as IP address |
| ipOptions | object | No | IP validation options (version, cidr) |
| guid / uuid | boolean | No | Validates as GUID/UUID |
| guidOptions | object | No | GUID validation options (version) |
| hex | boolean | No | Validates as hexadecimal string |
| base64 | boolean | No | Validates as base64 encoded string |
| dataUri | boolean | No | Validates as data URI |
| creditCard | boolean | No | Validates as credit card number |
| isoDate | boolean | No | Validates as ISO date string |
| isoDuration | boolean | No | Validates as ISO duration string |
| hostname | boolean | No | Validates as hostname |
| lowercase | boolean | No | Requires lowercase characters |
| uppercase | boolean | No | Requires uppercase characters |
| trim | boolean | No | Trims whitespace from string |
| truncate | boolean | No | Truncates string to max length |
| case | 'upper' \| 'lower' | No | Convert string to specific case |
| replace | object | No | Replace patterns in string |
| when | object | No | Conditional validation |
Number Field Definition (INumberFieldDefinition)
Extends ICommonFieldDefinition:
| Property | Type | Required | Description |
| -------------- | -------------------------- | -------- | ------------------------------------------------ |
| type | 'number' | Yes | Field type identifier |
| greater | number \| any | No | Must be greater than limit (supports references) |
| less | number \| any | No | Must be less than limit (supports references) |
| integer | boolean | No | Must be an integer (no floating point) |
| positive | boolean | No | Must be positive |
| negative | boolean | No | Must be negative |
| sign | 'positive' \| 'negative' | No | Specific sign requirement |
| multiple | number \| any | No | Must be a multiple of base |
| precision | number | No | Maximum number of decimal places |
| port | boolean | No | Must be a valid TCP port (0-65535) |
| unsafe | boolean | No | Allow unsafe numbers outside JS safety range |
| when | object | No | Conditional validation |
| alternatives | any[] | No | Alternative schemas |
Boolean Field Definition (IBooleanFieldDefinition)
Extends ICommonFieldDefinition:
| Property | Type | Required | Description |
| ----------- | ----------------- | -------- | ------------------------------------------------------ |
| type | 'boolean' | Yes | Field type identifier |
| truthy | any[] | No | Values that should be considered truthy |
| falsy | any[] | No | Values that should be considered falsy |
| sensitive | boolean | No | Whether to be case sensitive for string boolean values |
| convert | boolean | No | Enable type conversion |
| custom | function | No | Custom validation function |
| external | function | No | External validation function |
| when | object | No | Conditional validation |
| default | any \| function | No | Default value or function |
Date Field Definition (IDateFieldDefinition)
Extends ICommonFieldDefinition (excluding min/max):
| Property | Type | Required | Description |
| ----------- | --------------------------------------- | -------- | ----------------------------- |
| type | 'date' | Yes | Field type identifier |
| greater | Date \| number \| string \| Reference | No | Must be greater than limit |
| less | Date \| number \| string \| Reference | No | Must be less than limit |
| min | Date \| number \| string \| Reference | No | Minimum date value |
| max | Date \| number \| string \| Reference | No | Maximum date value |
| iso | boolean | No | Requires ISO 8601 date format |
| timestamp | any | No | Validates timestamp format |
| when | object | No | Conditional validation |
Array Field Definition (IArrayFieldDefinition)
Extends ICommonFieldDefinition:
| Property | Type | Required | Description |
| -------------- | ---------------------------- | -------- | ------------------------------------------------- |
| type | 'array' | Yes | Field type identifier |
| items | TExtendedFieldDefinition[] | No | Schema(s) for validating array items |
| ordered | any[] | No | Schema(s) for validating items in sequence order |
| has | any | No | At least one item must match this schema |
| single | boolean | No | Allow single values to be treated as arrays |
| sparse | boolean | No | Allow undefined values in arrays |
| unique | object | No | Uniqueness validation with comparator and options |
| sort | object | No | Sorting validation (order, by) |
| when | object | No | Conditional validation |
| alternatives | any[] | No | Alternative schemas |
Object Field Definition (IObjectFieldDefinition)
Extends ICommonFieldDefinition:
| Property | Type | Required | Description |
| ------------- | -------------------------------------------------- | -------- | --------------------------------------------- |
| type | 'object' | Yes | Field type identifier |
| keys | { [propName: string]: TExtendedFieldDefinition } | No | Nested properties for object-type fields |
| unknown | boolean | No | Allow unknown keys |
| length | number | No | Number of keys in object |
| pattern | Array<object> | No | Key pattern validation |
| and | string[] | No | Require all specified keys together |
| nand | string[] | No | Disallow all specified keys together |
| or | string[] | No | Require at least one of specified keys |
| oxor | string[] | No | Require only one of specified keys |
| xor | string[] | No | Require exactly one of specified keys |
| with | Array<object> | No | Requires key to exist with specified peers |
| without | Array<object> | No | Requires key to exist without specified peers |
| rename | Array<object> | No | Rename keys with options |
| instance | object | No | Validates object is instance of constructor |
| ref | boolean | No | Validates as Joi reference |
| regex | boolean | No | Validates as regex |
| preferences | object | No | Object-specific preferences |
| when | object | No | Conditional validation |
Any Field Definition (IAnyFieldDefinition)
Extends ICommonFieldDefinition:
| Property | Type | Required | Description |
| -------- | ------- | -------- | --------------------- |
| type | 'any' | Yes | Field type identifier |
Most permissive field type with minimal validation.
Reference Field Definition (IRefFieldDefinition)
Extends ICommonFieldDefinition:
| Property | Type | Required | Description |
| -------- | -------- | -------- | -------------------------------------------- |
| type | 'ref' | Yes | Field type identifier |
| ref | object | Yes | Reference configuration with key and options |
TypeScript Support
The library is written in TypeScript and provides comprehensive type definitions. All interfaces and types are exported for use in your application:
import {
SchemaBuilder,
FieldType,
ISchemaDefinition,
IStringFieldDefinition,
INumberFieldDefinition,
IArrayFieldDefinition,
IObjectFieldDefinition,
// ... other interfaces
} from '@eqxjs/joi-schema-builder';Requirements
- Node.js >= 22
- TypeScript >= 5.0 (if using TypeScript)
- joi >= 18.0.0
License
ISC
Contact
For any questions or issues, please open an issue on the GitHub repository.
