@std/valid
Validation predicates for IDs, financial data, and locale-specific formats. All validators return true or false and are pure functions with no side effects.
let valid = import @std/valid
v1.0 Change: This module was slimmed down for v1.0. Type checks, string/number constraints, format validators (email, url, phone), date/time validators, and collection helpers have been removed. See Migration from Previous API below.
ID Validators
Validate any ID type generated by @std/id.
| Function | Args | Description |
|---|---|---|
uuid(s) |
string | Valid UUID v4/v7 format? |
ulid(s) |
string | Valid ULID format (26 chars, Crockford Base32)? |
nanoid(s, len?) |
string, integer? | Valid NanoID format? (default length 21) |
cuid(s) |
string | Valid CUID2 format (25 chars, starts with 'c')? |
valid.uuid("550e8400-e29b-41d4-a716-446655440000") // true
valid.ulid("01ARZ3NDEKTSV4RRFFQ69G5FAV") // true
valid.nanoid("V1StGXR8_Z5jdHi6B-myT") // true (default 21 chars)
valid.nanoid("abc", 3) // true (custom length)
valid.cuid("cjld2cjxh0000qzrmn831i7rn") // true
Validation Patterns
| ID Type | Pattern |
|---|---|
| UUID | [0-9a-fA-F]{8}-[0-9a-fA-F]{4}-... (36 chars with dashes) |
| ULID | [0-9A-HJKMNP-TV-Z]{26} (Crockford Base32, no I/L/O/U) |
| NanoID | [0-9A-Za-z_-]+ with length check (default 21) |
| CUID2 | c[0-9a-z]{24} (25 chars, starts with 'c') |
Non-string arguments return false (not an error):
valid.uuid(123) // false
valid.ulid(null) // false
Financial Validators
| Function | Args | Description |
|---|---|---|
creditCard(s) |
string | Valid credit card number? (Luhn check, 13–19 digits) |
luhn(s) |
string | Passes Luhn algorithm? (any length) |
valid.creditCard("4111111111111111") // true (Visa test number)
valid.creditCard("4111-1111-1111-1111") // true (dashes stripped)
valid.creditCard("4111 1111 1111 1111") // true (spaces stripped)
valid.creditCard("4111111111111112") // false (bad check digit)
valid.luhn("79927398713") // true (generic Luhn)
valid.luhn("0") // true
creditCard enforces 13–19 digit length (standard card lengths). luhn accepts any length — use it for non-card Luhn-checked identifiers.
Locale-Aware Validators
| Function | Args | Description |
|---|---|---|
postalCode(s, locale) |
string, string | Valid postal code for locale? |
valid.postalCode("90210", "US") // true
valid.postalCode("90210-1234", "US") // true (ZIP+4)
valid.postalCode("SW1A 1AA", "GB") // true
valid.postalCode("sw1a1aa", "GB") // true (case-insensitive)
valid.postalCode("M5V 2T6", "CA") // true
valid.postalCode("k1a0b1", "CA") // true (case-insensitive)
Supported Locales
| Locale | Format |
|---|---|
"US" |
5-digit ZIP or ZIP+4 (12345 or 12345-6789) |
"GB" |
UK postcode (SW1A 1AA, with or without space) |
"CA" |
Canadian postal code (M5V 2T6, with or without space) |
Unsupported locales return an error:
valid.postalCode("12345", "XX") // Error: unsupported locale
Common Patterns
Validate Generated IDs
Every ID type generated by @std/id can be validated by @std/valid:
let id = import @std/id
let valid = import @std/valid
valid.uuid(id.uuid()) // true
valid.uuid(id.uuidv7()) // true
valid.ulid(id.new()) // true
valid.nanoid(id.nanoid()) // true
valid.cuid(id.cuid()) // true
Payment Form Validation
let valid = import @std/valid
let cardOk = valid.creditCard(input.cardNumber)
let zipOk = valid.postalCode(input.zip, "US")
if (!cardOk) { "Invalid card number" }
if (!zipOk) { "Invalid ZIP code" }
API Input Validation
let valid = import @std/valid
let handler = fn(req) {
let id = req.params.id
if (!valid.uuid(id)) {
api.badRequest("Invalid ID format")
}
// ... proceed with valid UUID
}
Destructuring Import
let { uuid, creditCard, postalCode } = import @std/valid
uuid("550e8400-e29b-41d4-a716-446655440000") // true
creditCard("4111111111111111") // true
postalCode("90210", "US") // true
Migration from Previous API
The following functions were removed in v1.0. Use native Parsley features or @schema DSL instead:
| Removed Function | Alternative |
|---|---|
string(x), number(x), integer(x), boolean(x), array(x), dict(x) |
inspect(x).type == "string" |
empty(s) |
s.trim() == "" |
minLen(s, n), maxLen(s, n), length(s, min, max) |
@schema constraint: string(n..) |
min(n, v), max(n, v), between(n, lo, hi) |
@schema constraint: int(lo..hi) |
positive(n), negative(n) |
Simple comparison: n > 0, n < 0 |
email(s), url(s), phone(s) |
@schema types: email, url, phone |
matches(s, pattern) |
Native regex: s ~ /pattern/ |
alpha(s), alphanumeric(s), numeric(s) |
Native regex: s ~ /^[a-zA-Z]+$/ |
contains(arr, val), oneOf(v, arr) |
Native in operator: val in arr |
date(s), time(s), parseDate(s, fmt) |
@schema type: date, datetime |
Key Differences from Other Languages
- Pure predicates — every function returns a boolean. No exceptions, no error objects.
- No mutation — validators never modify the input value.
- Focused scope — only validators that aren't trivially expressed with native syntax or
@schema. Type checking, string constraints, and format validation belong in schemas.
See Also
- @std/id — ID generation (the counterpart to these validators)
- @std/hash — cryptographic hash functions
- Data Model — schema-based validation with error messages
- Strings — string methods including
.length()and regex matching