step-validator
v2.1.3
Published
A flexible validation library with customizable rules for strings and numbers
Maintainers
Readme
step-validator
A flexible, list-driven validation toolkit for strings, numbers, ports, queries, and URLs. ESM-only, fully typed, and highly composable.
- Bold, simple API: validateX(...) returns a result object; isValidX(...) returns a boolean
- List-style rules with AND/OR composition and customizable validation order
- Whitelist and blacklist semantics with optional self-check functions
- Granular error messages that you can customize or fully control
- URL component validation (protocol/hostname/port/path/query/hash)
Installation
npm install step-validator
# or
pnpm add step-validator
# or
yarn add step-validatorThis package is ESM-only. Use import syntax.
Quick start
import { validateString, isValidNumber, validatePort } from "step-validator";
// String whitelist with AND composition
const result = validateString("example123", {
error_label: "Name",
whitelist: {
combination: "AND",
values: ["example123", "hello"],
starts_with: ["ex"],
ends_with: ["123"],
contains: ["amp"]
}
});
// result: { is_valid: true }
// Boolean-only check
const ok = isValidNumber(123456, {
whitelist: {
ranges: [[120000, 130000]]
}
});
// ok: true
// Port validation (string or number), range auto-checked (1..65535)
const portCheck = validatePort("8080", {
whitelist: { values: [8080, 443] },
error_label: "Port"
});
// { is_valid: true }Exports
- validateString(value, options): ValidationResult
- isValidString(value, options): boolean
- validateNumber(value, options): ValidationResult
- isValidNumber(value, options): boolean
- validatePort(value, options): ValidationResult
- isValidPort(value, options): boolean
- validateQuery(query, options): ValidationResult
- isValidQuery(query, options): boolean
- validateUrl(url, options): ValidationResult
- isValidUrl(url, options): boolean
TypeScript definitions are included.
ValidationResult
interface ValidationResult {
is_valid: boolean;
error_message?: string;
}List-based rules
Most validators accept list-based options to describe allowed/blocked values.
Shared building blocks:
- ListOptions
- combination: "AND" | "OR" (default is context-aware; whitelist -> AND, blacklist -> OR)
- validation_sequence: Array of checks to run and their order. Can include self-check functions
(value: T) => boolean.
- String checks:
values,starts_with,ends_with,contains - Number checks:
values,starts_with,ends_with,contains,ranges: [min, max][]
Validation order matters. The first decisive failure/success short-circuits.
Self-check functions must return a boolean. They let you plug in any custom logic.
String
import { validateString, isValidString } from "step-validator";Options:
- allowed?: boolean
- required?: boolean
- whitelist?: ListOptions
- blacklist?: ListOptions
- validation_sequence?: ("whitelist" | "blacklist")[] // order of list application
- error_label?: string
- error_messages?: { type_error?: string; allowed_error?: string; required_error?: string; whitelist?: string | ((type, expected) => string); blacklist?: string | ((type, expected) => string); }
Example:
const res = validateString("alpha-1", {
required: true,
error_label: "Username",
whitelist: {
combination: "AND",
starts_with: ["alpha"],
contains: ["-"]
},
blacklist: {
combination: "OR",
contains: [" "]
},
validation_sequence: ["whitelist", "blacklist"],
error_messages: {
whitelist: (type, values) => `Username must ${type} ${values.join(" or ")}`
}
});
// -> { is_valid: true }Behavior notes:
- If
required === trueand value is empty, validation fails. - If
allowed === falseand value is non-empty, validation fails. - Empty value short-circuits to valid when not required.
Number
import { validateNumber, isValidNumber } from "step-validator";Options:
- whitelist?: ListOptions
- blacklist?: ListOptions
- validation_sequence?: ("whitelist" | "blacklist")[]
- error_label?: string
- error_messages?: { type_error?: string; whitelist?: string | ((type, expected) => string); blacklist?: string | ((type, expected) => string); }
Number-only check ranges is supported: [[min, max], ...].
Port
import { validatePort, isValidPort } from "step-validator";- Accepts string or number input
- Enforces 1 <= port <= 65535
- For string input,
allowed/requiredbehave like String validator before numeric checks
Options extend Number options with:
- allowed?: boolean
- required?: boolean
- error_messages?: NumberErrorMessages & { allowed_error?: string; required_error?: string; }
Query string
import { validateQuery, isValidQuery } from "step-validator";Validates query strings like ?a=1&b=2 or a=1&b=2.
Options:
- allowed?: boolean
- required?: boolean
- keys_config?: { whitelist?: string[]; // allowed keys allow_duplicates?: boolean; // reject repeated keys when false require_all?: boolean; // require all keys in whitelist when true }
- values_config?: { [key: string]: | ({ type?: "string" } & StringValidationOptions) | ({ type: "number" } & NumberValidationOptions) | ({ type: "port" } & PortValidationOptions); }
- error_messages?: { allowed_error?: string; required_error?: string; invalid_key_error?: string | ((key: string) => string); duplicate_key_error?: string | ((key: string) => string); require_all_error?: string; }
Example:
const q = "?ip=192.168.0.10&port=8080";
const isIPv4 = (v: string) => /^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$/.test(v);
const res = validateQuery(q, {
required: true,
keys_config: {
whitelist: ["ip", "port"],
allow_duplicates: false,
require_all: true
},
values_config: {
ip: {
whitelist: { validation_sequence: [isIPv4] },
error_label: "ip"
},
port: { type: "port", error_label: "port" }
}
});
// -> { is_valid: true }URL
import { validateUrl, isValidUrl } from "step-validator";Validate individual URL components using the same string/port/query validators under the hood.
Options:
- protocol_config?: StringValidationOptions
- hostname_config?: StringValidationOptions
- port_config?: PortValidationOptions
- path_config?: StringValidationOptions // path validated without leading '/'
- query_config?: QueryValidationOptions // search validated without leading '?'
- hash_config?: StringValidationOptions // hash validated without leading '#'
- validation_sequence?: ("protocol" | "hostname" | "port" | "path" | "query" | "hash")[]
Example:
const isIPv4 = (v: string) => /^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$/.test(v);
const cfg = {
protocol_config: {
required: true,
whitelist: { values: ["http:", "https:"] },
error_label: "Protocol"
},
hostname_config: {
required: true,
whitelist: { validation_sequence: [isIPv4] },
error_label: "Hostname",
error_messages: {
whitelist: (t) => (t === isIPv4 ? "Hostname must be an IPv4 address" : "Invalid hostname")
}
},
port_config: { required: true, error_label: "Port" },
query_config: {
keys_config: { whitelist: ["id"], allow_duplicates: false },
values_config: { id: { whitelist: { values: ["1", "2"] } } }
}
} as const;
const ok = isValidUrl("http://192.168.1.10:8080?id=1", cfg);
// ok: trueError handling and edge cases
- All option objects must be plain objects; otherwise an error is thrown
- Empty options mean “no constraints” and return success
- Empty strings are allowed for string validators when not required
- For
validate*functions, you receive aValidationResultwith message;isValid*returns only a boolean - Self-check functions must return a boolean; if not, an error is thrown
TypeScript
All public APIs are fully typed. You can import option types when needed:
import type { StringValidationOptions, URLValidationOptions } from "step-validator";License
MIT © Buqi Liao
