JSPM

@vvlad1973/data-validator

2.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 28
  • Score
    100M100P100Q56485F
  • License MIT with Commercial Use

TypeScript library for loading and validating JSON/YAML schemas using AJV with optional logging support

Package Exports

  • @vvlad1973/data-validator

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, .yml schemas from a directory
  • Supports $ref links 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-tree for 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-validator

Optional: Install pino-logger-tree for advanced logging

npm install @vvlad1973/pino-logger-tree

Quick 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: 'john@example.com'
});

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:

  1. No logging - Don't provide any logger-related options
  2. Direct logger - Provide logger instance
  3. Auto-binding - Provide both loggerTree and loggerPath for 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 $ref for 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:ui

Test 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:fix

Building

# Build the project
npm run build

Examples

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: 'user@example.com',
    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

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests: npm test
  5. Run linter: npm run lint
  6. Submit a pull request

Changelog

See CHANGELOG.md for version history.

License

MIT License with Commercial Use