Object schema validation library for JavaScript with comprehensive validation capabilities
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Dynamic validation system supporting field references, context access, and template expressions for advanced validation scenarios.
Creates references to other fields or context values for dynamic validation.
/**
* Creates reference to another field for dynamic validation
* @param key - Reference key (field path or context path)
* @param options - Optional reference configuration
* @returns Reference object for dynamic value access
*/
function ref(key: string, options?: ReferenceOptions): Reference;
interface ReferenceOptions {
// Separator for key path parsing (default: '.')
separator?: string;
// Context options
contextPrefix?: string; // Prefix for context references (default: '$')
// Path options
ancestor?: number; // Number of parent levels to traverse
prefix?: {
global?: string; // Global context prefix (default: '/')
local?: string; // Local context prefix (default: '#')
root?: string; // Root value prefix (default: '#')
};
// Rendering options
render?: boolean; // Enable template rendering (default: true)
// Adjustment function
adjust?: (value: any) => any; // Value adjustment function
// Mapping function
map?: Array<[any, any]> | Map<any, any>; // Value mapping
// In-references
in?: boolean; // Enable in-reference mode
}
interface Reference {
readonly isContext: boolean; // True if reference points to context
readonly isGlobal: boolean; // True if reference is global
readonly key: string; // Reference key
readonly path: string[]; // Parsed key path
readonly ancestor: number; // Ancestor level count
readonly prefix: string; // Reference prefix type
readonly root: string; // Root identifier
readonly display: string; // Display representation
readonly type: string; // Reference type ('value' | 'context' | 'global')
}Usage Examples:
const Joi = require('joi');
// Basic field reference
const schema = Joi.object({
password: Joi.string().min(8),
confirmPassword: Joi.string().valid(Joi.ref('password'))
});
// Context reference
const contextSchema = Joi.object({
minValue: Joi.number().min(Joi.ref('$minAllowed'))
});
const { error, value } = contextSchema.validate(
{ minValue: 5 },
{ context: { minAllowed: 10 } }
);
// Nested field reference
const nestedSchema = Joi.object({
user: Joi.object({
name: Joi.string(),
email: Joi.string().email()
}),
contact: Joi.object({
primaryEmail: Joi.string().valid(Joi.ref('..user.email'))
})
});
// Reference with ancestor traversal
const hierarchySchema = Joi.object({
level1: Joi.object({
value: Joi.string(),
level2: Joi.object({
compare: Joi.string().valid(Joi.ref('value', { ancestor: 1 }))
})
})
});
// Reference with custom separator
const customRefSchema = Joi.object({
'field/name': Joi.string(),
compare: Joi.string().valid(Joi.ref('field/name', { separator: '/' }))
});Creates array references for rule matching and validation.
/**
* Creates array reference for rule matching
* @param ref - Reference key or Reference object
* @param options - Optional reference configuration
* @returns Reference configured for array matching
*/
function in(ref: string | Reference, options?: ReferenceOptions): Reference;Usage Examples:
// Array membership validation
const membershipSchema = Joi.object({
allowedValues: Joi.array().items(Joi.string()),
selectedValue: Joi.string().valid(Joi.in('allowedValues'))
});
const { error, value } = membershipSchema.validate({
allowedValues: ['red', 'green', 'blue'],
selectedValue: 'red' // Valid - 'red' is in allowedValues array
});
// Dynamic validation based on array context
const dynamicSchema = Joi.object({
category: Joi.string().valid(Joi.in('$availableCategories'))
});
const contextValidation = dynamicSchema.validate(
{ category: 'electronics' },
{
context: {
availableCategories: ['electronics', 'clothing', 'books']
}
}
);Creates template expressions for dynamic content generation and validation.
/**
* Creates template expressions with dynamic placeholders
* @param template - Template string with placeholder syntax
* @param options - Optional template configuration
* @returns Template object for dynamic rendering
*/
function expression(template: string, options?: TemplateOptions): Template;
// Alias for expression function
const x: typeof expression;
interface TemplateOptions {
// Custom functions for template rendering
functions?: Record<string, Function>;
// Variable references
reference?: boolean; // Enable reference resolution (default: true)
}
interface Template {
readonly isTemplate: boolean; // Always true for template objects
readonly source: string; // Original template string
/**
* Renders template with provided context
* @param context - Rendering context with variables
* @param prefs - Optional preferences
* @param local - Local context variables
* @param options - Rendering options
* @returns Rendered string
*/
render(
context: any,
prefs?: any,
local?: any,
options?: any
): string;
}Usage Examples:
// Basic template expression
const messageTemplate = Joi.expression('Hello {#name}, you are {#age} years old');
// Custom error messages with templates
const customSchema = Joi.string()
.min(3)
.message(Joi.expression('Field {#label} must be at least {#limit} characters, got {#value}'));
// Dynamic validation with templates
const dynamicValidation = Joi.object({
name: Joi.string().required(),
greeting: Joi.string().valid(Joi.expression('Hello {#name}'))
});
// Template with functions
const advancedTemplate = Joi.expression('User {#name|uppercase} has {#posts|length} posts', {
functions: {
uppercase: (value) => value.toUpperCase(),
length: (array) => array ? array.length : 0
}
});
// Using x alias
const shortTemplate = Joi.x('Welcome {#user.name}!');Utility functions for working with references and templates.
/**
* Checks if value is a reference object
* @param ref - Value to check
* @returns True if value is Reference object
*/
function isRef(ref: any): ref is Reference;
/**
* Checks if value is a template expression
* @param expression - Value to check
* @returns True if value is Template object
*/
function isExpression(expression: any): expression is Template;Usage Examples:
const ref = Joi.ref('field');
const template = Joi.expression('Hello {#name}');
const string = 'regular string';
console.log(Joi.isRef(ref)); // true
console.log(Joi.isRef(template)); // false
console.log(Joi.isRef(string)); // false
console.log(Joi.isExpression(template)); // true
console.log(Joi.isExpression(ref)); // false
console.log(Joi.isExpression(string)); // falseconst conditionalSchema = Joi.object({
type: Joi.string().valid('user', 'admin'),
permissions: Joi.array()
.when('type', {
is: 'admin',
then: Joi.array().min(1),
otherwise: Joi.array().max(0)
})
});const relationshipSchema = Joi.object({
startDate: Joi.date(),
endDate: Joi.date().greater(Joi.ref('startDate')),
duration: Joi.number().when('startDate', {
is: Joi.exist(),
then: Joi.number().min(1),
otherwise: Joi.forbidden()
})
});const dynamicArraySchema = Joi.object({
maxItems: Joi.number().integer().min(1),
items: Joi.array().max(Joi.ref('maxItems')),
selectedItems: Joi.array()
.items(Joi.string().valid(Joi.in('items')))
.unique()
});const customErrorSchema = Joi.object({
username: Joi.string()
.min(3)
.max(20)
.messages({
'string.min': Joi.expression('Username {#label} must be at least {#limit} characters'),
'string.max': Joi.expression('Username {#label} cannot exceed {#limit} characters')
}),
email: Joi.string()
.email()
.message(Joi.expression('Please provide a valid email address for {#label}'))
});const globalContextSchema = Joi.object({
userLevel: Joi.string().valid(Joi.ref('/user.level')),
maxUpload: Joi.number().max(Joi.ref('/limits.upload'))
});
// Validation with global context
const result = globalContextSchema.validate(data, {
context: {
'/': {
user: { level: 'premium' },
limits: { upload: 1000000 }
}
}
});const localContextSchema = Joi.object({
priority: Joi.string().valid(Joi.ref('#priorities')),
category: Joi.string().valid(Joi.ref('#categories'))
});
// Local context validation
const localResult = localContextSchema.validate(data, {
context: {
priorities: ['low', 'medium', 'high'],
categories: ['bug', 'feature', 'enhancement']
}
});// String manipulation functions
const stringTemplate = Joi.expression('{#name|lowercase|trim}');
// Array functions
const arrayTemplate = Joi.expression('Found {#items|length} items');
// Date functions
const dateTemplate = Joi.expression('Created on {#createdAt|date("YYYY-MM-DD")}');
// Custom functions
const customTemplate = Joi.expression('{#value|multiply(2)|format}', {
functions: {
multiply: (value, factor) => value * factor,
format: (value) => `$${value.toFixed(2)}`
}
});