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

piorjs

v0.0.3

Published

A simple multi mode validator

Readme

📦 Pior

The Lightweight, Zero-Dependency, Chain-First Validation Library for TypeScript

Validate your data with absolute clarity. Pior is a modern validation engine that operates with zero runtime dependencies, no decorator magic, and no heavy proxy layers. Designed to be ESM-native, tree-shake friendly, and instantly understandable.


NPM Version License Last Commit


🚀 Features

Pior delivers robust validation capabilities without the runtime complexity of traditional schema libraries.

⚙️ Core Architecture

  • Zero Runtime Dependency – Pure TypeScript compiled to native, lightweight ESM.
  • 🌲 Tree-Shake Friendly – Explicit validator imports and modular code footprint.
  • 🧠 No Hidden Behavior – No Reflect Metadata, no experimental decorators, and no Proxy black box routing.
  • 🚀 Universal Compatibility – Operates seamlessly on Node.js, Deno, and Bun.

🛠 Supported Validation Modes

Pior supports exactly four distinct validation modes using a single, unified validation engine:

  • 🔗 Chain Mode – Perfect for single variables, Bot commands, and quick router queries.
  • 📋 Schema Mode – Define type-safe objects with nested constraints for request payloads.
  • Inline Mode – Quick configuration validation without declaring detached reusable schemas.
  • 🧩 Rule Mode – Isolate and export modular validator pipelines for reusable constraints.

Table of contents


Getting Started

Install

Install Pior into your target project runtime:

  • Node.js (NPM)
    npm install pior
  • Bun
    bun add pior
  • Deno
    import { pior } from "npm:pior@latest";

Back to Table of contents

Quick Example

import { pior } from 'pior';

// Validate an object payload with Schema Mode
const UserSchema = pior.object({
  username: pior.string().required().min(3),
  email: pior.email().required(),
  age: pior.number().between(18, 60)
});

const result = UserSchema.validate({
  username: "vibe",
  email: "[email protected]",
  age: 28
});

console.log(result.success); // true

Back to Table of contents


Validation Modes

Pior's core validation engine runs identically across all four usage profiles.

Chain Mode

Best suited for single variables, query parameters, CLI inputs, or route parameters. It resolves to a string (first validation failure message) or null if valid.

const error = pior
  .check("email")
  .input("not-an-email")
  .required()
  .email()
  .validate();

console.log(error); // "Invalid email address"

Back to Table of contents

Schema Mode

Best suited for structure validation (such as validation of HTTP requests). Resolves structural error payloads mapped by object path coordinates.

const RegistrationSchema = pior.object({
  email: pior.email().required(),
  password: pior.string().required().min(8)
});

const result = RegistrationSchema.validate({
  email: "[email protected]",
  password: "123"
});

console.log(result);
/*
Output:
{
  success: false,
  errors: {
    "password": ["Length must be at least 8"]
  }
}
*/

Back to Table of contents

Inline Mode

Executes object payloads instantly on-the-fly without maintaining reusable schema instances. Under the hood, this routes straight to Schema Mode.

const result = pior.validate(req.body, {
  token: pior.uuid().required(),
  role: pior.string().required()
});

Back to Table of contents

Rule Mode

Isolate pipeline rules as discrete, exportable modular definitions. These can then be nested freely inside standard object schemas.

// Define isolated reusable validator pipeline rule
export const EmailRule = pior.email().required();

// 1. Validate on its own
const result = EmailRule.validate("not-valid"); // { success: false, message: "Invalid email address" }

// 2. Nest freely in schemas
const ContactSchema = pior.object({
  primaryEmail: EmailRule,
  secondaryEmail: EmailRule.optional()
});

Back to Table of contents


API Reference

Every validator method supports custom override error messages as its final argument.

Primitive Validators

| Method | Arguments | Description | | --- | --- | --- | | string(msg?) | msg?: string | Asserts the target input is string data. | | number(msg?) | msg?: string | Asserts the target is a valid non-NaN number. | | integer(msg?) | msg?: string | Asserts the target is a whole integer. | | float(msg?) | msg?: string | Asserts the target is a floating point/decimal number. | | bigint(msg?) | msg?: string | Asserts the target is native BigInt data. | | boolean(msg?) | msg?: string | Asserts the target is standard boolean data. |

Back to Table of contents

Collection Validators

| Method | Arguments | Description | | --- | --- | --- | | object(schema?, msg?) | schema?: Record<string, Pior>, msg?: string | Checks type is object, and parses nested fields against schema. | | array(item?, msg?) | item?: Pior, msg?: string | Asserts target is an array, executing item validation sequentially. | | buffer(msg?) | msg?: string | Asserts target is a native Buffer object. | | map(msg?) | msg?: string | Asserts target is a Map object. | | set(msg?) | msg?: string | Asserts target is a Set object. |

Back to Table of contents

Web Domain Validators

| Method | Arguments | Description | | --- | --- | --- | | email(msg?) | msg?: string | Asserts the string matches compliant RFC email profiles. | | url(msg?) | msg?: string | Asserts the string parses as a valid URL. | | uuid(msg?) | msg?: string | Asserts the string conforms to structural UUID formats. | | hostname(msg?) | msg?: string | Asserts string represents a structurally valid hostname. | | domain(msg?) | msg?: string | Asserts string conforms to Domain formatting specs. | | ip(msg?) | msg?: string | Asserts target is a valid IP address (v4 or v6). | | ipv4(msg?) | msg?: string | Asserts target is a valid IPv4 address. | | ipv6(msg?) | msg?: string | Asserts target is a valid IPv6 address. | | slug(msg?) | msg?: string | Asserts string matches valid slug URL patterns. |

Back to Table of contents

String Constraints

| Method | Arguments | Description | | --- | --- | --- | | min(limit, msg?) | limit: number, msg?: string | Asserts dynamic lower boundary check (string length, number value, collection size). | | max(limit, msg?) | limit: number, msg?: string | Asserts dynamic upper boundary check (string length, number value, collection size). | | length(len, msg?) | len: number, msg?: string | Asserts target string is exactly len characters. | | minLength(limit, msg?) | limit: number, msg?: string | Asserts string minimum length constraints. | | maxLength(limit, msg?) | limit: number, msg?: string | Asserts string maximum length constraints. | | startsWith(prefix, msg?) | prefix: string, msg?: string | Asserts target begins with matching prefix string. | | endsWith(suffix, msg?) | suffix: string, msg?: string | Asserts target ends with matching suffix string. | | contains(sub, msg?) | sub: string, msg?: string | Asserts target string contains matching substring. | | regex(pattern, msg?) | pattern: RegExp, msg?: string | Evaluates string data against target Regular Expression. | | alpha(msg?) | msg?: string | Asserts string contains strictly alphabetic characters. | | alphaNumeric(msg?) | msg?: string | Asserts string contains strictly alphabetic and numeric values. | | lowercase(msg?) | msg?: string | Asserts target string contains solely lowercased letters. | | uppercase(msg?) | msg?: string | Asserts target string contains solely uppercased letters. |

Back to Table of contents

Number Constraints

| Method | Arguments | Description | | --- | --- | --- | | positive(msg?) | msg?: string | Asserts target value is positive (> 0). | | negative(msg?) | msg?: string | Asserts target value is negative (< 0). | | between(min, max, msg?) | min: number, max: number, msg?: string | Asserts value is inclusively within min/max parameters. | | multipleOf(factor, msg?) | factor: number, msg?: string | Asserts target value is perfectly divisible by factor. |

Back to Table of contents

Date Constraints

| Method | Arguments | Description | | --- | --- | --- | | date(msg?) | msg?: string | Asserts value parses cleanly into a valid JS Date. | | before(limit, msg?) | limit: Date \| string, msg?: string | Asserts target represents date temporally prior to limit boundary. | | after(limit, msg?) | limit: Date \| string, msg?: string | Asserts target represents date temporally after limit boundary. |

Back to Table of contents

General Modifiers

| Method | Arguments | Description | | --- | --- | --- | | required(msg?) | msg?: string | Asserts value is defined, not null, and not empty. | | optional() | - | Explicitly marks pipeline as optional (allows undefined values). | | nullable() | - | Explicitly marks pipeline as nullable (allows null values). | | custom(fn, msg?) | fn: (val: any) => boolean \| string, msg?: string | Runs custom verification callback logic. |

Back to Table of contents


Flow Control & Extras

Bail Mode

By default, Pior will attempt to parse through the entire validation pipeline and nested elements, collecting all structural issues. Using .bail(), you can instruct the validation engine to halt immediately upon reaching the first failure.

// Define a schema that exits early
const StrictUser = pior.bail().object({
  username: pior.string().required().min(5),
  email: pior.email().required(),
  age: pior.number().required()
});

// If username fails min(5), remaining fields (email, age) are completely ignored.
const result = StrictUser.validate({ username: "usr" });

Back to Table of contents

Custom Validator

Inject specialized verification rules dynamically using .custom(). Your custom function should return true on success, false to invoke standard error messages, or a string representing a dynamic failure message.

const DynamicSchema = pior.object({
  couponCode: pior.string().custom((val) => {
    if (!val.startsWith("SALE_")) {
      return "Coupon must start with SALE_ prefix";
    }
    return true;
  })
});

Back to Table of contents