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.
🚀 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 noProxyblack 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";
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); // trueValidation 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"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"]
}
}
*/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()
});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()
});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. |
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. |
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. |
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. |
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. |
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. |
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. |
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" });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;
})
});