@vvlad1973/data-validator
v2.0.0
Published
TypeScript library for loading and validating JSON/YAML schemas using AJV with optional logging support
Downloads
70
Maintainers
Readme
@vvlad1973/data-validator
TypeScript library for loading and validating JSON/YAML schemas using AJV with optional pino-logger-tree integration.
Features
- Loads all
.json,.jsonc,.yaml,.ymlschemas from a directory - Supports
$reflinks between schemas - Validates data by schema key
- Supports comments (
jsonc) and YAML format - Optional multi-level logging (trace, debug, info, warn, error)
- Optional integration with
@vvlad1973/pino-logger-treefor structured logging - Automatic method tracing via decorators (when pino-logger-tree is installed)
- Three logging modes: no logging, direct logger, auto-binding
- Pure ESM package
- Comprehensive JSDoc documentation
Installation
npm install @vvlad1973/data-validatorOptional: Install pino-logger-tree for advanced logging
npm install @vvlad1973/pino-logger-treeQuick Start
Basic Usage
import DataValidator from '@vvlad1973/data-validator';
const validator = new DataValidator({
schemasDir: './schemas'
});
await validator.isReady();
await validator.validate('user.schema.json', {
name: 'John Doe',
email: '[email protected]'
});Legacy Constructor (Backward Compatible)
import DataValidator from '@vvlad1973/data-validator';
const validator = new DataValidator('./schemas');
await validator.isReady();With pino-logger-tree (Direct Logger)
import DataValidator from '@vvlad1973/data-validator';
import { LoggerTree } from '@vvlad1973/pino-logger-tree';
// Create logger tree
const tree = new LoggerTree({ level: 'debug' });
const logger = tree.createLogger('app.validator');
// Create validator with logger
const validator = new DataValidator({
schemasDir: './schemas',
logger
});
// Validator will log all operations with structured logging
await validator.validate('user.schema.json', userData);With pino-logger-tree (Auto-binding)
import DataValidator from '@vvlad1973/data-validator';
import { LoggerTree } from '@vvlad1973/pino-logger-tree';
// Create logger tree
const tree = new LoggerTree({ level: 'debug' });
// Create validator with auto-binding
const validator = new DataValidator({
schemasDir: './schemas',
loggerTree: tree,
loggerPath: 'app.validator'
});
// Logger automatically created and bound
await validator.validate('user.schema.json', userData);
// Cleanup when done
validator.destroy();With Custom Logger
import DataValidator, { ILogger } from '@vvlad1973/data-validator';
const customLogger: ILogger = {
trace: (msg, ...args) => console.log('[TRACE]', msg, ...args),
debug: (msg, ...args) => console.log('[DEBUG]', msg, ...args),
info: (msg, ...args) => console.log('[INFO]', msg, ...args),
warn: (msg, ...args) => console.warn('[WARN]', msg, ...args),
error: (msg, ...args) => console.error('[ERROR]', msg, ...args),
};
const validator = new DataValidator({
schemasDir: './schemas',
logger: customLogger
});API Reference
Constructor
new DataValidator(options?: string | DataValidatorOptions)Parameters:
options- Schema directory path (string) or configuration object
DataValidatorOptions:
interface DataValidatorOptions {
schemasDir?: string; // Directory containing schema files
logger?: ILogger; // Optional logger instance (direct mode)
loggerTree?: LoggerTree; // Optional LoggerTree for auto-binding
loggerPath?: string; // Path in LoggerTree hierarchy
}Logging Modes
The validator supports three logging modes:
- No logging - Don't provide any logger-related options
- Direct logger - Provide
loggerinstance - Auto-binding - Provide both
loggerTreeandloggerPathfor automatic logger creation
Methods
isReady(): Promise<boolean>
Checks if schemas are loaded and validator is ready.
const ready = await validator.isReady();
if (ready) {
// Validator is ready to use
}loadSchemasFromDirectory(schemaDir: string): Promise<boolean>
Loads schemas from a directory. Supports .json, .jsonc, .yaml, .yml formats.
await validator.loadSchemasFromDirectory('./custom-schemas');addSchema(schema: object, key: string): void
Adds a schema programmatically.
validator.addSchema({
type: 'object',
properties: {
name: { type: 'string' }
},
required: ['name']
}, 'user');validate(schemaKey: string, data: unknown): Promise<void>
Validates data against a schema. Throws error if validation fails.
try {
await validator.validate('user.schema.json', userData);
console.log('Valid!');
} catch (error) {
console.error('Invalid:', error.message);
}destroy(): void
Cleans up resources and removes logger from tree if auto-bound. Call this when the validator is no longer needed, especially when using auto-binding mode.
const validator = new DataValidator({
schemasDir: './schemas',
loggerTree: tree,
loggerPath: 'app.validator'
});
// Use validator...
await validator.validate('schema.json', data);
// Cleanup
validator.destroy();Types
import { DataValidator, DataValidatorOptions, ILogger } from '@vvlad1973/data-validator';ILogger Interface:
interface ILogger {
// Pino-style: structured logging with context object
trace(obj: object, msg?: string, ...args: unknown[]): void;
debug(obj: object, msg?: string, ...args: unknown[]): void;
info(obj: object, msg?: string, ...args: unknown[]): void;
warn(obj: object, msg?: string, ...args: unknown[]): void;
error(obj: object, msg?: string, ...args: unknown[]): void;
// Simple style: console-like logging
trace(msg: string, ...args: unknown[]): void;
debug(msg: string, ...args: unknown[]): void;
info(msg: string, ...args: unknown[]): void;
warn(msg: string, ...args: unknown[]): void;
error(msg: string, ...args: unknown[]): void;
}The interface supports both Pino-style structured logging and simple console-style logging.
Schema Structure
Schemas should be placed in a directory. The package includes example schemas to demonstrate functionality:
schemas/
├── user.schema.json # User validation schema
├── product.schema.yaml # Product schema (YAML format)
├── order.schema.json # Order schema with $ref examples
└── config.schema.jsonc # Config schema (JSON with comments)All matching files (.json, .jsonc, .yaml, .yml) are automatically loaded on initialization. Each schema is registered with its filename (including extension) as the key.
Example Schemas
The package includes example schemas that demonstrate:
- user.schema.json - Basic validation with formats (email, uuid), patterns, and enums
- product.schema.yaml - YAML format support with arrays and nested objects
- order.schema.json - Schema references using
$reffor reusable definitions - config.schema.jsonc - JSONC format with comments for documentation
Logging Levels
When a logger is provided, the validator logs operations at different levels:
- trace - Method tracing (via decorators when pino-logger-tree is installed), very detailed info (file parsing, skipped files)
- debug - Operation details (loading schemas, validation start/end)
- info - Major operations (schema loading completed) - uses template strings without context object
- warn - Non-critical issues (validation failed with details)
- error - Critical errors (schema not found, parsing errors)
With pino-logger-tree
When pino-logger-tree is installed, all public methods are automatically traced at TRACE level via decorators:
import { LoggerTree } from '@vvlad1973/pino-logger-tree';
const tree = new LoggerTree({ level: 'trace' });
const validator = new DataValidator({
schemasDir: './schemas',
loggerTree: tree,
loggerPath: 'app.validator'
});
// Method calls are automatically logged with parameters
await validator.validate('user.schema.json', userData);Example pino log output (JSON format):
{"level":20,"time":1234567890,"name":"app.validator","msg":"Initializing DataValidator","schemasDir":"./schemas"}
{"level":10,"time":1234567890,"name":"app.validator","msg":"loadSchemasFromDirectory() called","schemaDir":"./schemas"}
{"level":20,"time":1234567890,"name":"app.validator","msg":"Schema loaded successfully","file":"user.schema.json","key":"user.schema.json"}
{"level":30,"time":1234567890,"name":"app.validator","msg":"Schema loading completed: loaded 3 of 3 files"}
{"level":10,"time":1234567890,"name":"app.validator","msg":"validate() called","schemaKey":"user.schema.json"}
{"level":20,"time":1234567890,"name":"app.validator","msg":"Validation succeeded","schemaKey":"user.schema.json"}Without pino-logger-tree
When pino-logger-tree is not installed, decorators become no-ops and only explicit logger calls are made:
[DEBUG] Initializing DataValidator { schemasDir: './schemas' }
[DEBUG] Schema loaded successfully { file: 'user.schema.json', key: 'user.schema.json' }
[INFO] Schema loading completed: loaded 3 of 3 files
[DEBUG] Starting validation { schemaKey: 'user.schema.json' }
[DEBUG] Validation succeeded { schemaKey: 'user.schema.json' }Development
Testing
This project uses Vitest with comprehensive test coverage (96%+).
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
# Run tests with UI
npm run test:uiTest Coverage:
- Overall: 96.42%
- Statements: 96.42%
- Branches: 91.48%
- Functions: 100%
- Lines: 96.87%
Linting
# Check code quality
npm run lint
# Auto-fix issues
npm run lint:fixBuilding
# Build the project
npm run buildExamples
Complete Example
import DataValidator from '@vvlad1973/data-validator';
import { LoggerTree } from '@vvlad1973/pino-logger-tree';
// Setup logger tree
const loggerTree = new LoggerTree();
const rootLogger = loggerTree.root();
// Configure logger level
rootLogger.updateParam({ level: 'debug' });
// Create validator with auto-binding
const validator = new DataValidator({
schemasDir: './schemas',
loggerTree: loggerTree,
loggerPath: 'app.validator'
});
// Wait for schemas to load
await validator.isReady();
// Add custom schema
validator.addSchema({
type: 'object',
properties: {
id: { type: 'string', format: 'uuid' },
email: { type: 'string', format: 'email' },
age: { type: 'number', minimum: 0 }
},
required: ['id', 'email']
}, 'custom-user');
// Validate data
try {
await validator.validate('custom-user', {
id: '123e4567-e89b-12d3-a456-426614174000',
email: '[email protected]',
age: 25
});
console.log('Data is valid!');
} catch (error) {
console.error('Validation error:', error.message);
}Error Handling
async function validateUserData(userData: unknown) {
const validator = new DataValidator({ schemasDir: './schemas' });
await validator.isReady();
try {
await validator.validate('user.schema.json', userData);
return { valid: true };
} catch (error) {
if (error instanceof Error) {
return {
valid: false,
errors: error.message.split('\n')
};
}
throw error;
}
}TypeScript Support
This package is written in TypeScript and provides full type definitions.
import DataValidator, {
DataValidatorOptions,
ILogger
} from '@vvlad1973/data-validator';
// Type-safe options
const options: DataValidatorOptions = {
schemasDir: './schemas',
logger: myLogger
};
const validator = new DataValidator(options);Build System
The package uses a pure ESM build system:
- ESM output in
dist/src/ - Post-build scripts to clean test files from distribution
Compatibility
- Node.js: 20.x or higher
- TypeScript: 5.x or higher
- Module System: ES Modules only
- Logger: Compatible with TreeLogger from @vvlad1973/pino-logger-tree and console-like loggers
- Optional Integration: @vvlad1973/pino-logger-tree ^1.1.0 (optional peer dependency)
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
npm test - Run linter:
npm run lint - Submit a pull request
Changelog
See CHANGELOG.md for version history.
License
MIT License with Commercial Use
