API Stability Notice

Macroforge is under active development. The API is not yet stable and may change between versions. Some documentation sections may be outdated.

Validators

Validators run during deserialization. Failures are reported through the errors array of the result union rather than thrown, so a single call reports every problem at once.

Three ways to apply them

/** @derive(Deserialize) */
class User {
  /** @serde(validate: ["email", "maxLength(255)"]) */
  email: string;

  /** @serde(validate: [{ validate: "minLength(2)", message: "Name too short" }]) */
  name: string;

  /** @serde(minLength(8), maxLength(64)) */
  password: string;
}
  1. Array of stringsvalidate: ["email", "maxLength(255)"]
  2. Array of objects — adds a custom message per validator
  3. Shorthand — bare validator calls directly in @serde(...)

validate must be an array. An object literal such as validate: { email: true } is rejected with “validate must be an array”.

Misspelled names are caught with a suggestion: the parser does a Levenshtein match against the known list and tells you what you probably meant.

String validators

ValidatorChecks
emailValid email address
urlValid URL
uuidValid UUID
pattern("re")Matches the regular expression
minLength(n)Length ≥ n
maxLength(n)Length ≤ n
length(n)Length exactly n
length(min, max)Length within range
nonEmptyNot the empty string
trimmedNo leading/trailing whitespace
lowercaseAll lowercase
uppercaseAll uppercase
capitalizedFirst character uppercase
uncapitalizedFirst character lowercase
startsWith(s)Has the prefix
endsWith(s)Has the suffix
includes(s)Contains the substring

Number validators

ValidatorChecks
greaterThan(n)> n
greaterThanOrEqualTo(n)≥ n
lessThan(n)< n
lessThanOrEqualTo(n)≤ n
between(min, max)Within range
intInteger
nonNegativeIntInteger and ≥ 0
uint8Integer in 0–255
multipleOf(n)Divisible by n
positive> 0
nonNegative≥ 0
negative< 0
nonPositive≤ 0
finiteNot Infinity
nonNaNNot NaN

BigInt validators

ValidatorChecks
positiveBigInt> 0n
nonNegativeBigInt≥ 0n
negativeBigInt< 0n
nonPositiveBigInt≤ 0n
greaterThanBigInt(n)> n
greaterThanOrEqualToBigInt(n)≥ n
lessThanBigInt(n)< n
lessThanOrEqualToBigInt(n)≤ n
betweenBigInt(min, max)Within range

Date validators

Note the names — they are comparison-shaped, not after/before:

ValidatorChecks
validDateParses to a valid Date
greaterThanDate(d)After d
greaterThanOrEqualToDate(d)At or after d
lessThanDate(d)Before d
lessThanOrEqualToDate(d)At or before d
betweenDate(start, end)Within range

Array validators

ValidatorChecks
minItems(n)At least n elements
maxItems(n)At most n elements
itemsCount(n)Exactly n elements

Custom validators

custom(fnName) calls a function you supply, which should return true when the value is valid.

/** @serde(validate: ["custom(isStrongPassword)"]) */
password: string;

Validating without deserializing

Generated types also expose the validators directly, which is useful for form validation:

User.validateField("email", "not-an-email");
User.validateFields({ email: "a@b.com", name: "" });