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 🙏

© 2025 – Pkg Stats / Ryan Hefner

check-rule-mate

v0.5.8

Published

Rule-based, extensible and async-friendly data validation engine for complex forms and business rules.

Readme

check-rule-mate

Rule-based, extensible and async-friendly data validation engine for complex forms and business rules.

Overview

check-rule-mate is a lightweight rule-driven validation engine for JavaScript. Instead of coupling validation logic directly to schemas or fields, check-rule-mate separates concerns into rules, schemas, validators, and error messages, allowing you to build highly reusable, composable, and context-aware validations.

It is designed for scenarios where traditional schema-based validators start to feel limiting, especially when you need:

  • Cross-field validation
  • Contextual rules
  • Async checks
  • Reusable validation logic across multiple forms
  • Full control over execution flow and error handling
  • Lifecycle Hooks

Github repository: check-rule-mate repository

Examples of how implement check-rule-mate: check-rule-mate examples

Test the core functionalities here: check-rule-mate demo (Note: Creating or modifying custom validators is not supported in the demo, as it requires JavaScript implementation.)

Why check-rule-mate?

Use check-rule-mate if you:

  • Need reusable validation logic across different forms and contexts
  • Have complex or conditional validation rules
  • Want full control over how validation runs
  • Need async validations (API calls, database checks, etc.)
  • Prefer rule-driven validation instead of tightly coupled schemas
  • Want clean separation between rules, data, and messages
  • You want to have auto documentation of your forms

Core Concepts

check-rule-mate is built around four main concepts:

  1. Rules: How data is validated
  2. Schema: What should be validated
  3. Validation Helpers: How rules are executed
  4. Error Messages: How errors are communicated

This separation makes the system flexible, scalable, and easy to maintain.

Features

  • Rule-based validation engine
  • Reusable validation rules
  • Modifiers for contextual rule extensions
  • Cross-field validation using dynamic parameters
  • Async validation support
  • Abort early or collect all errors
  • Strict or loose schema matching
  • i18n-ready error messages
  • Framework-agnostic (frontend or backend)
  • Auto documentation (automatic generated by a CLI command)
  • Template checker (automatic checked by a CLI command)

Table of Contents

Getting Started

Installation

If you are in NPM use this:

npm install check-rule-mate

Repository - Installation

If you downloaded the repository you can install using:

npm install
npm start

Repository - Running Tests

Execute the test suite with:

npm test

How It Works

Basic Usage

import MY_RULES from './rules/myValidatorRules.json' with { type: 'json' };
import CONTACT_US from './schemas/contactUs.json' with { type: 'json' };
import ERROR_MESSAGES from './i18n/en_US/errors.json' with { type: 'json' };

import { createValidator } from 'check-rule-mate';
import { myValidator } from './validators/myValidator.js';

const fields = {
  name: 'John',
  lastName: 'Doe',
  email: '[email protected]',
  emailConfirm: '[email protected]',
  phone: '',
  subject: 'I need a coffee',
  message: 'Give me coffee'
};

async function runFormValidate() {
  const validator = createValidator(fields, {
    validationHelpers: myValidator,
    rules: MY_RULES,
    schema: CONTACT_US,
    errorMessages: ERROR_MESSAGES,
    options: {
      cache: true,
      abortEarly: false,
      propertiesMustMatch: true,
    }
  });

  const result = await validator.validate();

  // This should return { ok: true }
  console.log(result);
}

runFormValidate();

Validation Result

A validation result follows this structure:

When is valid:

{ ok: true }

When is invalid and has errors:

{
  error: true,
  errors: {
    [field: string]: {
      name: string,
      type: string,
      message: string,
      code: string,
    }[];
  };
}

Lifecycle Hooks

The check-rule-mate lifecycle hooks allow you to observe, extend and react to the validation process without coupling logic to rules or helpers.

Hooks are especially useful for:

  • Logging and debugging
  • Analytics and metrics
  • Custom side-effects
  • Integrating validation with UI or external systems
  • Advanced error handling and reporting
  • They provide fine-grained control over the validation lifecycle.
hooks?: {
  onValidateStart?: (payload) => void;
  onValidateFieldStart?: (payload) => void;
  onValidateFieldError?: (payload) => void;
  onValidateFieldSuccess?: (payload) => void;
  onValidateEnd?: (payload) => void;
}

Hook Payloads

onValidateStart

Triggered once before validation begins.

onValidateStart: ({ data }) => void

Payload:

  • data: Full form data object being validated
onValidateFieldStart

Triggered before validating each field.

onValidateFieldStart: ({ field, value, schemaField }) => void

Payload:

  • field: Field name
  • value: Field value
  • schemaField: Schema configuration for the field (or null if missing)
onValidateFieldError

Triggered when a field fails validation.

onValidateFieldError: ({ field, value, schemaField, error }) => void

Payload:

  • field: Field name
  • value: Field value
  • schemaField: Schema configuration for the field (or null if missing)
  • error: Validation error object
onValidateFieldSuccess

Triggered when a field is successfully validated.

onValidateFieldSuccess: ({ field, value, schemaField }) => void

Payload:

  • field: Field name
  • value: Field value
  • schemaField: Schema configuration for the field (or null if missing)
onValidateEnd

Triggered once after validation finishes.

onValidateEnd: ({ data, errors }) => void

Payload:

  • data: Full form data object being validated
  • errors: Validation errors (if any) If no errors occurred, errors may be undefined.

Hooks - Example Usage

const validator = createValidator(fields, {
  validationHelpers: myValidator,
  rules: MY_RULES,
  schema: CONTACT_US,
  errorMessages: ERROR_MESSAGES,
  hooks: {
    onValidateStart: ({ data }) => {
      console.log('Validation started', data);
    },

    onValidateFieldStart: ({ field, value }) => {
      console.log(`Validating ${field}`, value);
    },

    onValidateFieldError: ({ field, error }) => {
      console.error(`Error on ${field}`, error);
    },

    onValidateFieldSuccess: ({ field }) => {
      console.log(`${field} validated successfully`);
    },

    onValidateEnd: ({ data, errors }) => {
      if (errors) {
        console.log('Validation finished with errors', errors);
      } else {
        console.log('Validation finished successfully');
      }
    }
  }
});

await validator.validate();

Auto Documentation

check-rule-mate contains a script to generate automatic documentation based in your rules, schemas and error messages.

To use that it is simple, you only need to run this command:

npx check-rule-mate-auto-docs --rules {rules path} --schemas {schemas path} --errors {errors path} --out {file.html}

This will generate a HTML file containing the rules, schemas and errors.

[Experimental] Documentation Playground

⚠️ The playground executes bundled client-side JavaScript. Do not use untrusted validation code.

The Docs Playground allows you to generate an interactive HTML page where you can test your schemas, rules, and validators directly in the browser.

This feature is experimental and intended mainly for development and exploration purposes. It bundles your validation logic into a client-side format, enabling real-time validation without any backend setup.

⚠️ Since this feature is experimental, APIs and behavior may change.


Requirements

The playground generator depends on optional dependencies that are not installed by default.

Before using it, make sure you have the required optional dependencies installed:

npm install esbuild

Usage

Run the playground generator using the CLI:

npx check-rule-mate-auto-docs-playground-experimental \
  --rules {rules-path} \
  --schemas {schemas-path} \
  --errors {errors-path} \
  --options {options-path} \
  --out {output-file.html}

This command will generate a self-contained HTML file with:

  • Documentation for your rules and schemas
  • A playground to test validation behavior in real time

Options File

The playground requires an options file to map validator names to their source files.

Example:

{
  "validators": {
    "myValidator": "./examples/vanilla/src/check-rule-mate-rules/validators/validators.js",
    "nameValidator": "./examples/vanilla/src/check-rule-mate-rules/validators/validators.js",
    "myValidator2": "./examples/vanilla/src/check-rule-mate-rules/validators/validator2.js"
  }
}

How it works:

  • Keys represent the exported object/function/class name of your validator
  • Values are paths to the files where those validators are defined
  • These validators are bundled and made available inside the playground

This explicit mapping ensures predictable builds and avoids magic imports.

Auto Checker for Templates

You can auto check if your template it is working properly with all necessary properties or have something missing.

It is works with: Schemas, Rules and Errors

npx check-rule-mate-verify-templates --rules {rules path} --schemas {schemas path} --errors {errors path}

If everything it is working properly this should be your message:

✔ Schemas loaded: 4
✔ Rules loaded: 6
✔ Errors loaded: 6

✔ No issues found

Else if some error was found could be something like that:

✔ Schemas loaded: 4
✔ Rules loaded: 6
✔ Errors loaded: 6

❌ Validation failed

❌ Schema "contactUs.json" → field "phone" references rule "cellphone" which does not exist

Defining Validation

Defining a Schema (What to validate)

Schemas map data fields to rules.

{
  "name": {
    "rule": "name",
    "required": true
  },
  "email": {
    "rule": "email",
    "required": true,
    "cache": false,
  },
  "emailConfirm": {
    "rule": "email--confirm",
    "required": true,
    "cache": false,
  },
  "phone": {
    "rule": "phone",
    "required": false
  }
}

Schema Properties

  • rule: Rule name (supports modifiers via rule--modifier)
  • required: Whether the field must exist and not be empty
  • cache: if this field will have cache or not

Defining Rules (How to validate)

Rules define validation logic, independent of any specific form.

{
  "name": {
    "validate": ["hasText"],
    "error": { "hasText": "common.hasText" }
  },
  "email": {
    "regex": "/^[a-z0-9.]+@[a-z0-9]+\\.[a-z]+(\\.[a-z]+)?$/i",
    "validate": ["regex"],
    "error": { "regex": "email.regex" },
    "modifier": {
      "confirm": {
        "validate": ["regex", "equals"],
        "params": { "equals": ["$email"] },
        "error": { "equals": "email.equals" }
      }
    }
  },
  "date": {
    "regex": "/^\\d{4}[\/\\-](0?[1-9]|1[012])[\/\\-](0?[1-9]|[12][0-9]|3[01])$/",
    "validate": ["regex", "validDate"],
    "error": {
      "regex": "common.dateFormat",
      "validDate": "date.validDate"
    },
    "modifier": {
      "age": {
        "validate": ["regex", "validateAge"],
        "params": {
          "validateAge": [18, 130]
        },
        "error": {
          "regex": "common.dateFormat",
          "validateAge": "date.modifier.age.validateAge"
        }
      }
    }
  }
}

Rule Properties

  • validate: Ordered list of validation functions
  • regex: Optional regex used by the regex helper
  • error: Error keys mapped to validation functions
  • modifier: Contextual rule extensions
  • params: Parameters passed to validation helpers

Modifiers (Contextual Rules)

Modifiers allow extending a rule without duplicating logic.

Example:

"email--confirm"

Internally:

  • Base rule: email
  • Modifier: confirm

Modifiers can override:

  • validate
  • params
  • regex
  • error

This makes rules highly reusable and expressive.

Dynamic Parameters ($field)

Rules can reference other fields dynamically:

"params": {
  "equals": ["$email"]
}

At runtime:

  • $email resolves to data.email
  • Enables cross-field validation

Validation Helpers (Execution Layer)

Validation helpers are the runtime implementation of rules.

const myValidator = function (value, rule, modifier = null, data = null) {
  function regex() {
    const regexTemplate = rule.modifier?.[modifier]?.regex || rule.regex;
    const regex = new RegExp(regexTemplate);
    return regex.test(value);
  }

  function hasText() {
    return value.trim().length > 0;
  }

  function equals(key) {
    return value === data[key];
  }

  async function isDataFetched() {
    try {
      let result = await new Promise((resolve, reject) => {
        setTimeout(() => {
          const success = !!value;
          if (success) {
            resolve('Data fetched successfully!');
          } else {
            reject('Error fetching data');
          }
        }, 2000);
      });
      return !!result;
    } catch (error) {
      return false;
    }
  }

  return { regex, hasText, equals, isDataFetched };
};

Helper Signature

(value, rule, modifier?, data?) => Record<string, Function>

Helpers:

  • Can be sync or async
  • Are stateless
  • Do not know about schemas or error messages

Error Messages (i18n-ready)

Errors are resolved via keys, not hardcoded strings.

{
  "common": {
    "hasText": "Please fill the field"
  },
  "email": {
    "regex": "Please enter a valid email",
    "equals": "Emails do not match"
  }
}

This makes localization and message customization straightforward.

Validation Options

options: {
  cache?: boolean,               // If cache is enabled or not
  abortEarly?: boolean,          // Stop on first error
  propertiesMustMatch?: boolean, // Schema vs data strictness
}

Example Usage

Explore examples in the examples folder folder. Before execute any test change the type in package.json for module instead commonjs

Examples folder: Github repo examples folder.

Vanilla

Here you are free to test anything you want about form validation, also We have a lot of tests scenarios in tests which could be a great start.

Command to run Vanilla example:

npm run example:vanilla

Vanilla example: Github repo vanilla file.

tests

Command to run tests:

npm run test

Unit tests examples: Github repo unit tests file.

Express:

See how the check-rule-mate works in back-end using a middleware.

Command to run Express example:

npm run example:express

Express example: Github repo express file.

Frontend:

Here you can found the DEMO page and it's a type of "playground" to test how RULES works and validations works. (Here you can't create customized javascript so custom validatorHelpers are disabled by default)

Frontend example: check-rule-mate demo.

When NOT to use check-rule-mate

  • Simple one-off forms
  • Basic required-only validation
  • When schema-based validation is enough

License

  • ISC