npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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-shape

Usage

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 boolean

Enum 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 city

Additional 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 allowed

Custom 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 suggestions

API Reference

validateSchema(data, schema, options?, utils?)

Validates data against a schema definition.

Parameters:

  • data: unknown - Data to validate
  • schema: Schema - Schema definition
  • options?: 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 validate
  • schema: Schema - Schema definition
  • options?: 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 validate
  • schema: Schema - Schema definition
  • options?: 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 rules

Integration 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 typecheck

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

See Also