Pipelines

For detailed validations and transformations, a pipeline can be passed as the last optional argument to almost any schema function. Especially for schema functions like string, number, bigint, date and array this feature is useful to validate further details apart from the raw data type.

How it works

In simple words, a pipeline is an array of functions that synchronously passes through the input of a schema. Each function can examine and modify the input. The pipeline is therefore perfect for detailed validations and transformations.

Important: The pipeline cannot be used to change the data type of a value. For this, the transform method must be used explicitly.

Example

For example, the pipeline feature can be used to trim a string and make sure that it is an email that ends with a specific domain.

import { email, endsWith, string, toTrimmed } from 'valibot'; // 0.6 kB

const EmailSchema = string([toTrimmed(), email(), endsWith('@example.com')]);

Validations

Validation functions examine the input and, if the input does not meet a certain condition, return an issue. If the input is valid, it is returned as the output and, if present, picked up by the next function in the pipeline.

By default I run a pipeline completely, even if an error is thrown in between, to collect all issues. If you want me to abort the pipeline early after the first error is thrown, you have to set the abortPipeEarly option of parse, parseAsync, safeParse or safeParseAsync to true. Learn more here.

Example

For example, a validation function that controls the length of a string might look like the following.

import { getOutput, getPipeIssues, string } from 'valibot'; // 0.54 kB

const StringSchema = string([
  (input) => {
    if (input.length > 10) {
      return getPipeIssues('custom', 'Invalid length', input);
    }
    return getOutput(input);
  },
]);

Utility functions

Since the code of a pipeline, as seen in the previous example, can quickly become confusing. I provide you with small utility functions that make your code more understandable and readable.

Utility functions: bytes, cuid2, custom, customAsync email, emoji, endsWith, equal, excludes, finite, includes, integer, ip, ipv4, ipv6, isoDate, isoDateTime, isoTime, isoTimeSecond, isoTimestamp, isoWeek, length, maxBytes, maxLength, maxSize, maxValue, mimeType, minBytes, minLength, minSize, minValue, multipleOf, regex, safeInteger, size, startsWith, ulid, url, uuid, value

Some of these utility functions can be used in the pipeline of different schema functions. For example, minValue can be used in the pipeline of string, number, bigint and date.

import { bigint, date, minValue, number, string } from 'valibot'; // 0.58 kB

const StringSchema = string([minValue('2023-07-29')]);
const NumberSchema = number([minValue(1234)]);
const BigintSchema = bigint([minValue(1234n)]);
const DateSchema = date([minValue(new Date())]);

Custom validation

For custom validations custom or customAsync can be used. If the function passed as the first argument returns a falsy value, an error is thrown. Otherwise the input is considered valid.

import { customAsync, stringAsync } from 'valibot'; // 0.5 kB
import { isAvailableUsername } from '~/api';

const UsernameSchema = stringAsync([
  customAsync(isAvailableUsername, 'This username is already taken.'),
]);

Transformations

Transformation functions allow to change the value of an input, but not the data type. This can be useful for example to remove spaces at the beginning or end of a string or to force a minimum or maximum value.

If you also want to change the data type, you must explicitly use the transform method.

Example

A transformation function that enforces a minimum value of a number could look like the following.

import { number } from 'valibot'; // 0.44 kB

const NumberSchema = number([(input) => ({ output: input > 10 ? input : 10 })]);

Utility functions

To make the code of a pipeline more readable, you can use the utility functions I provide for transformations.

Utility functions: toCustom, toCustomAsync, toLowerCase, toMaxValue, toMinValue, toTrimmed, toTrimmedEnd, toTrimmedStart, toUpperCase

import { number, toMinValue } from 'valibot'; // 0.47 kB

const NumberSchema = number([toMinValue(10)]);