@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

See Also