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

polyval

v1.0.2

Published

Advanced, multilingual and customizable validation library

Downloads

5

Readme

PolyVal

PolyVal is a multilingual and highly customizable validation library. It uses Zod as a backend while providing developers with a simplified API.

Features

  • Simplified API: Use without needing complex type definitions or knowledge of validation rules
  • Multilingual Support: Default support for en (English) and tr (Turkish)
  • Fully Customizable Error Messages: Customize error messages by field, rule type, or globally
  • Custom Validation Rules: Easily define your own validation rules
  • TypeScript Support: Full TypeScript support with type safety

Installation

npm install polyval

Basic Usage

import { validate } from 'polyval';

// Simple schema definition
const userSchema = {
  username: {
    type: 'string',
    required: true,
    min: 3,
    max: 20
  },
  email: {
    type: 'string',
    required: true,
    email: true
  },
  age: {
    type: 'number',
    min: 18
  }
};

// Data to validate
const userData = {
  username: 'jo',
  email: 'invalid-email',
  age: 16
};

// Validation (using Turkish language)
const errors = validate(userSchema, userData, { lang: 'tr' });
console.log(errors);
// [
//   "Username: En az 3 karakter uzunluğunda olmalıdır",
//   "Email: Geçersiz e-posta adresi",
//   "Age: En az 18 olmalıdır"
// ]

Schema Definition

PolyVal schemas are defined using simple JavaScript objects. Each field uses a configuration object:

const schema = {
  fieldName: {
    type: 'string' | 'number' | 'boolean' | 'date',  // Field type (required)
    required: boolean,                               // Is field required? (default: false)
    // Other validation rules...
  }
};

Supported Validation Rules

For String Fields

{
  type: 'string',
  required: boolean,           // Is required?
  min: number,                 // Minimum length
  max: number,                 // Maximum length
  length: number,              // Exact length
  email: boolean,              // Email format
  url: boolean,                // URL format
  uuid: boolean,               // UUID format
  cuid: boolean,               // CUID format
  datetime: boolean,           // ISO 8601 datetime format
  ip: 'v4' | 'v6',             // IP address format
  regex: string,               // Regex pattern (as string)
  startsWith: string,          // Must start with this value
  endsWith: string,            // Must end with this value
  numeric: boolean             // Only numeric characters
}

For Number Fields

{
  type: 'number',
  required: boolean,           // Is required?
  min: number,                 // Minimum value
  max: number                  // Maximum value
}

For Date Fields

{
  type: 'date',
  required: boolean,           // Is required?
  min: number,                 // Minimum date (timestamp)
  max: number                  // Maximum date (timestamp)
}

For Boolean Fields

{
  type: 'boolean',
  required: boolean,           // Is required?
  equals: boolean              // Expected to be a specific value (true/false)?
}

Field Comparison Rules

To validate a field in relation to another field:

{
  password: {
    type: 'string',
    required: true,
    min: 8
  },
  confirmPassword: {
    type: 'string',
    required: true,
    equals: 'password'         // Must match the 'password' field
  },
  oldPassword: {
    type: 'string',
    required: true,
    notEquals: 'password'      // Must not match the 'password' field
  }
}

Custom Validation Rules

To define your own validation logic:

{
  username: {
    type: 'string',
    required: true,
    customValidators: [
      {
        validator: (value, data) => {
          // Custom validation logic
          if (value.toLowerCase() === 'admin') {
            return 'This username is not available'; // Return error message
          }
          return undefined; // Return undefined for successful validation
        },
        messageKey: 'noAdminUsername'  // Key to use for custom messages
      }
    ]
  }
}

Customizing Error Messages

PolyVal allows you to fully customize error messages:

const errors = validate(schema, data, {
  lang: 'en',
  customMessages: {
    // 1. General error messages
    required: 'This field cannot be empty',
    invalid_type: 'Invalid value type',
    
    // 2. Type-based error messages
    string: {
      min: (min) => `Please enter at least ${min} characters`,
      email: 'Please enter a valid email address'
    },
    number: {
      min: (min) => `Value must be at least ${min}`
    },
    
    // 3. Custom comparison rule messages
    equals: (field) => `This field must match the ${field} field`,
    
    // 4. Field-based custom messages (highest priority)
    fields: {
      username: {
        min: (min) => `Username must be at least ${min} characters`,
        required: 'Username is required',
        // Message for custom validation rule
        noAdminUsername: 'Admin username is reserved'
      }
    },
    
    // 5. Global custom validator messages
    custom: {
      noAdminUsername: 'Admin username cannot be used'
    }
  }
});

Message Priority Order

Error messages are determined according to the following priority order (from highest to lowest):

  1. Field-based custom validator messages (customMessages.fields['fieldName']['customMessageKey'])
  2. Other field-based custom messages (customMessages.fields['fieldName']['min'])
  3. Global custom validator messages (customMessages.custom['messageKey'])
  4. General rule-based custom messages (customMessages.string.email, customMessages.number.min)
  5. General error type messages (customMessages.required, customMessages.invalid_type)
  6. Default messages in the selected language

Comprehensive Examples

User Registration Validation Example

import { validate } from 'polyval';

// User registration schema
const userRegistrationSchema = {
  username: {
    type: 'string',
    required: true,
    min: 3,
    max: 20,
    regex: '^[a-zA-Z0-9]+$', // Only alphanumeric characters
    customValidators: [{
      validator: (value) => value.toLowerCase() !== 'admin' ? undefined : 'Admin username is not available',
      messageKey: 'noAdminUsername'
    }]
  },
  email: {
    type: 'string',
    required: true,
    email: true
  },
  age: {
    type: 'number',
    min: 18,
    required: false
  },
  password: {
    type: 'string',
    required: true,
    min: 8,
    regex: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]+$' // Strong password
  },
  confirmPassword: {
    type: 'string',
    required: true,
    equals: 'password', // Must match the 'password' field
    customValidators: [{
      validator: (value, data) => value !== data.password + '123' ? undefined : 'You used a predictable password',
      messageKey: 'predictablePassword'
    }]
  },
  acceptTerms: {
    type: 'boolean',
    required: true,
    equals: true // User must accept terms
  }
};

// Invalid data
const userData = {
  username: "al",
  email: "invalid-email",
  password: "123",
  confirmPassword: "456",
  acceptTerms: false
};

// Validate with Turkish error messages
const errorsTR = validate(userRegistrationSchema, userData, { lang: 'tr' });
console.log(errorsTR);

// Validate with English and customized messages
const errorsEN = validate(userRegistrationSchema, userData, {
  lang: 'en',
  customMessages: {
    string: {
      min: (min) => `Please ensure this field has at least ${min} characters.`,
      email: "That doesn't look like a valid email address."
    },
    fields: {
      username: {
        noAdminUsername: "Sorry, 'admin' is a reserved username."
      },
      confirmPassword: {
        equals: "Passwords must match exactly."
      }
    }
  }
});

console.log(errorsEN);

Development

Setup

git clone https://github.com/yourusername/polyval.git
cd polyval
npm install

Test

npm test

Build

npm run build

Example Usage

There is an example project in the example directory that demonstrates how to use the library. To explore and run this example:

  1. Install and build the main PolyVal project:
npm install
npm run build
  1. Navigate to the example project and run it:
cd example
npm install
npm run dev

This example demonstrates user registration validation, multilingual error messages, and how to use customized messages.

License

MIT