@bernierllc/validators-schema-shape
v1.2.0
Published
Primitive validator for schema shape validation - required fields, types, enums, constraints
Readme
@bernierllc/validators-schema-shape
Primitive validator for schema shape validation - validates data against schema definitions including required fields, type checking, enum values, constraints, and patterns.
Installation
npm install @bernierllc/validators-schema-shapeUsage
Basic Validation
import { validateSchema, type Schema } from '@bernierllc/validators-schema-shape';
// Define a schema
const schema: Schema = {
properties: {
name: { type: 'string', required: true, min: 2, max: 50 },
email: { type: 'string', required: true, pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ },
age: { type: 'number', min: 18, max: 120 },
role: { type: 'string', enum: ['admin', 'user', 'guest'] },
tags: { type: 'array', min: 1, max: 10, items: { type: 'string' } },
},
required: ['name', 'email'],
};
// Validate data
const data = {
name: 'John Doe',
email: '[email protected]',
age: 30,
role: 'user',
tags: ['developer', 'typescript'],
};
const problems = await validateSchema(data, schema);
if (problems.length === 0) {
console.log('Data is valid!');
} else {
problems.forEach(problem => {
console.error(`${problem.severity}: ${problem.message}`);
});
}Quick Validation
import { isValidSchema } from '@bernierllc/validators-schema-shape';
const schema = {
properties: {
username: { type: 'string', required: true },
password: { type: 'string', required: true, min: 8 },
},
};
const isValid = await isValidSchema({ username: 'john', password: 'secret123' }, schema);
console.log(isValid ? 'Valid' : 'Invalid');Detailed Validation
import { validateSchemaDetailed } from '@bernierllc/validators-schema-shape';
const result = await validateSchemaDetailed(data, schema);
console.log('Success:', result.success);
console.log('Total problems:', result.problems.length);
console.log('Errors:', result.errors.length);
console.log('Warnings:', result.warnings.length);Schema Definition
Field Types
Supported field types:
'string'- String values'number'- Numeric values'boolean'- Boolean values'object'- Object values'array'- Array values'null'- Null values'any'- Any type (no validation)- Multiple types:
['string', 'number']- Value can be any of the specified types
Field Properties
interface SchemaField {
type: SchemaFieldType | SchemaFieldType[];
required?: boolean; // Field is required
enum?: unknown[]; // Allowed enum values
min?: number; // Min value/length
max?: number; // Max value/length
pattern?: string | RegExp; // Pattern to match (strings only)
properties?: Record<string, SchemaField>; // Nested object schema
items?: SchemaField; // Array item schema
message?: string; // Custom error message
}Validation Options
interface SchemaShapeOptions {
checkRequired?: boolean; // Check required fields (default: true)
checkTypes?: boolean; // Check type constraints (default: true)
checkEnums?: boolean; // Check enum values (default: true)
checkConstraints?: boolean; // Check min/max constraints (default: true)
checkPatterns?: boolean; // Check string patterns (default: true)
checkArrayLength?: boolean; // Check array lengths (default: true)
allowAdditionalProperties?: boolean; // Allow extra properties (default: true)
checkNested?: boolean; // Check nested objects (default: true)
}Examples
Required Fields
const schema = {
properties: {
username: { type: 'string', required: true },
email: { type: 'string', required: true },
},
required: ['username'], // Schema-level required
};
// Missing required field
const problems = await validateSchema({ email: '[email protected]' }, schema);
// Error: Missing required field: "username"Type Checking
const schema = {
properties: {
age: { type: 'number' },
active: { type: 'boolean' },
tags: { type: 'array' },
},
};
const problems = await validateSchema({
age: '25', // Error: expected number, got string
active: 'true', // Error: expected boolean, got string
tags: 'a,b,c', // Error: expected array, got string
}, schema);Multiple Types
const schema = {
properties: {
value: { type: ['string', 'number', 'null'] },
},
};
await validateSchema({ value: 'text' }, schema); // Valid
await validateSchema({ value: 123 }, schema); // Valid
await validateSchema({ value: null }, schema); // Valid
await validateSchema({ value: true }, schema); // Error: expected string | number | null, got booleanEnum Values
const schema = {
properties: {
status: { type: 'string', enum: ['active', 'inactive', 'pending'] },
priority: { type: 'number', enum: [1, 2, 3] },
},
};
const problems = await validateSchema({
status: 'deleted', // Error: must be one of ['active', 'inactive', 'pending']
priority: 5, // Error: must be one of [1, 2, 3]
}, schema);Constraints (Min/Max)
const schema = {
properties: {
age: { type: 'number', min: 0, max: 150 },
username: { type: 'string', min: 3, max: 20 },
tags: { type: 'array', min: 1, max: 10 },
},
};
const problems = await validateSchema({
age: -5, // Error: less than minimum 0
username: 'ab', // Error: length less than minimum 3
tags: [], // Error: array length less than minimum 1
}, schema);String Patterns
const schema = {
properties: {
email: {
type: 'string',
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
},
phone: {
type: 'string',
pattern: '^\\d{3}-\\d{3}-\\d{4}$'
},
zipCode: {
type: 'string',
pattern: /^\d{5}(-\d{4})?$/,
},
},
};
const problems = await validateSchema({
email: 'invalid-email', // Error: does not match pattern
phone: '1234567890', // Error: does not match pattern
zipCode: 'ABCDE', // Error: does not match pattern
}, schema);Array Item Types
const schema = {
properties: {
scores: {
type: 'array',
items: { type: 'number', min: 0, max: 100 },
},
tags: {
type: 'array',
items: { type: 'string', min: 1 },
},
},
};
const problems = await validateSchema({
scores: [85, 90, '95'], // Error: array item at index 2 has invalid type
tags: ['valid', ''], // Error: array item at index 1 has invalid length
}, schema);Nested Objects
const schema = {
properties: {
user: {
type: 'object',
properties: {
name: { type: 'string', required: true },
email: { type: 'string', pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ },
address: {
type: 'object',
properties: {
street: { type: 'string', required: true },
city: { type: 'string', required: true },
zipCode: { type: 'string', pattern: /^\d{5}$/ },
},
},
},
},
},
};
const problems = await validateSchema({
user: {
email: 'invalid',
address: {
street: '123 Main St',
// Missing city
},
},
}, schema);
// Errors: missing name, invalid email, missing cityAdditional Properties
// Allow additional properties (default)
const schema1 = {
properties: {
name: { type: 'string' },
},
};
await validateSchema({ name: 'John', age: 30 }, schema1); // Valid
// Disallow additional properties
const schema2 = {
properties: {
name: { type: 'string' },
},
additionalProperties: false,
};
const problems = await validateSchema(
{ name: 'John', age: 30 },
schema2,
{ allowAdditionalProperties: false }
);
// Error: Additional property "age" is not allowedCustom Error Messages
const schema = {
properties: {
email: {
type: 'string',
required: true,
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: 'Please provide a valid email address in the format [email protected]',
},
age: {
type: 'number',
min: 18,
message: 'You must be at least 18 years old to register',
},
},
};
const problems = await validateSchema({ email: 'invalid', age: 16 }, schema);
// Custom messages appear in suggestionsAPI Reference
validateSchema(data, schema, options?, utils?)
Validates data against a schema definition.
Parameters:
data: unknown- Data to validateschema: Schema- Schema definitionoptions?: SchemaShapeOptions- Validation options (optional)utils?: SharedUtils- Shared utilities (optional)
Returns: Promise<Problem[]> - Array of validation problems
isValidSchema(data, schema, options?)
Checks if data is valid according to schema (only checks errors, ignores warnings).
Parameters:
data: unknown- Data to validateschema: Schema- Schema definitionoptions?: SchemaShapeOptions- Validation options (optional)
Returns: Promise<boolean> - True if valid, false otherwise
validateSchemaDetailed(data, schema, options?)
Validates data with detailed result including success flag and separated errors/warnings.
Parameters:
data: unknown- Data to validateschema: Schema- Schema definitionoptions?: SchemaShapeOptions- Validation options (optional)
Returns: Promise<{ success: boolean; problems: Problem[]; errors: Problem[]; warnings: Problem[] }>
Individual Rules
All rules can be imported individually:
import {
requiredFieldsRule,
typeCheckingRule,
enumValidationRule,
constraintsRule,
patternValidationRule,
additionalPropertiesRule,
} from '@bernierllc/validators-schema-shape';Primitive Validator
The composed primitive validator:
import { schemaShapeValidator } from '@bernierllc/validators-schema-shape';
console.log(schemaShapeValidator.name); // 'schema-shape'
console.log(schemaShapeValidator.domain); // 'schema'
console.log(schemaShapeValidator.rules); // Array of all rulesIntegration Status
- Logger: not-applicable - Pure validation function with no logging requirements
- Docs-Suite: ready - Full TypeDoc documentation with markdown README
- NeverHub: not-applicable - Primitive validator with no service dependencies
Performance
This validator is optimized for performance:
- Minimal dependencies (@bernierllc/validators-core only)
- Pure functions with no side effects
- Early returns for invalid data
- Efficient type checking and pattern matching
- Suitable for real-time validation in forms and APIs
Development
# Install dependencies
npm install
# Build the package
npm run build
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run linter
npm run lint
# Type check
npm run typecheckLicense
Copyright (c) 2025 Bernier LLC. All rights reserved.
See Also
- @bernierllc/validators-core - Core validation infrastructure
- @bernierllc/validators-runner - Validation runner for executing validators
- @bernierllc/validators-reporters - Reporting utilities for validation results
