You can use Grit to automatically update your code to the new API. See the migration guide for more details on the changes.
Apply with the Grit CLI
grit apply github.com/fabian-hiller/valibot#migrate_to_v0_31_0
Should transform simple pipe
Before:
BEFORE
const Schema1 = v.string([v.email('Email required')]); const Schema2 = v.string([v.email(), v.endsWith('@example.com')]); const Schema3 = v.string([v.email(), v.endsWith('@example.com'), v.maxLength(30)]);
After:
AFTER
const Schema1 = v.pipe(v.string(), v.email('Email required')); const Schema2 = v.pipe(v.string(), v.email(), v.endsWith('@example.com')); const Schema3 = v.pipe(v.string(), v.email(), v.endsWith('@example.com'), v.maxLength(30));
Should transform nested pipe
Before:
BEFORE
const Schema1 = v.map(v.number(), v.string([v.url(), v.endsWith('@example.com')]), [v.maxSize(10)]); const Schema2 = v.object({ list: v.array(v.string([v.minLength(3)]), [v.minLength(3), v.includes('foo')]), length: v.number([v.integer()]) }, [v.custom((input) => input.list.length === input.length)]);
After:
AFTER
const Schema1 = v.pipe(v.map(v.number(), v.pipe(v.string(), v.url(), v.endsWith('@example.com'))), v.maxSize(10)); const Schema2 = v.pipe(v.object({ list: v.pipe(v.array(v.pipe(v.string(), v.minLength(3))), v.minLength(3), v.includes('foo')), length: v.pipe(v.number(), v.integer()) }), v.check((input) => input.list.length === input.length));
Should not transform non pipe
Before:
BEFORE
const Schema = v.object({ normal: v.string([v.email(() => 'Email required')]), union: v.union([v.string([v.decimal()]), v.number()], [v.minValue(10)]), intersection: v.intersect([v.object({ a: v.string() }), v.object({ b: v.number() })]), variant: v.variant('type', [v.object({ type: v.literal('a') }), v.object({ type: v.literal('b') })]), picklist: v.picklist(['a', 'b']), tuple: v.tuple([v.string(), v.number()]), });
After:
AFTER
const Schema = v.object({ normal: v.pipe(v.string(), v.email(() => 'Email required')), union: v.pipe(v.union([v.pipe(v.string(), v.decimal()), v.number()]), v.minValue(10)), intersection: v.intersect([v.object({ a: v.string() }), v.object({ b: v.number() })]), variant: v.variant('type', [v.object({ type: v.literal('a') }), v.object({ type: v.literal('b') })]), picklist: v.picklist(['a', 'b']), tuple: v.tuple([v.string(), v.number()]), });
Should transform coerce method
Before:
BEFORE
const Schema = v.coerce(v.date(), (input) => new Date(input));
After:
AFTER
const Schema = v.pipe(v.unknown(), v.transform((input) => new Date(input)));
Should transform flatten argument
Before:
BEFORE
const flatErrors1 = v.flatten(error); // This should be unchanged const flatErrors2 = v.flatten([issue]); const flatErrors3 = v.flatten(result.issues);
After:
AFTER
const flatErrors1 = v.flatten(error.issues); // This should be unchanged const flatErrors2 = v.flatten([issue]); const flatErrors3 = v.flatten(result.issues);
Should transform any Valibot wildcard
Before:
BEFORE
import * as foo from 'valibot'; import * as notFoo from 'zod'; const Schema1 = foo.string([foo.email()]); const Schema2 = notFoo.string([notFoo.email()]);
After:
AFTER
import * as foo from 'valibot'; import * as notFoo from 'zod'; const Schema1 = foo.pipe(foo.string(), foo.email()); const Schema2 = notFoo.string([notFoo.email()]);
Should transform direct Valibot imports
Before:
BEFORE
import { email, string } from 'valibot'; const Schema = string([email()]);
After:
AFTER
import { email, string, pipe } from 'valibot'; const Schema = pipe(string(), email());
Should transform brand and transform method
Before:
BEFORE
const Schema1 = v.brand(v.string([v.url()]), 'foo'); const Schema2 = v.transform(v.string(), (input) => input.length); const Schema3 = v.transform(v.brand(v.string(), 'Name'), (input) => input.length); const Schema4 = v.brand(v.brand(v.string(), 'Name1'), 'Name2');
After:
AFTER
const Schema1 = v.pipe(v.string(), v.url(), v.brand('foo')); const Schema2 = v.pipe(v.string(), v.transform((input) => input.length)); const Schema3 = v.pipe(v.string(), v.brand('Name'), v.transform((input) => input.length)); const Schema4 = v.pipe(v.string(), v.brand('Name1'), v.brand('Name2'));
Should transform unnecessary pipes
Before:
BEFORE
const Schema1 = v.pipe(v.pipe(v.pipe(v.string()), v.email()), v.maxLength(10)); const Schema2 = v.transform(v.coerce(v.date(), (input) => new Date(input)), (input) => input.toJSON()); const Schema3 = v.pipe(v.array(v.pipe(v.string(), v.decimal())), v.transform((input) => input.length));
After:
AFTER
const Schema1 = v.pipe(v.string(), v.email(), v.maxLength(10)); const Schema2 = v.pipe(v.unknown(), v.transform((input) => new Date(input)), v.transform((input) => input.toJSON())); const Schema3 = v.pipe(v.array(v.pipe(v.string(), v.decimal())), v.transform((input) => input.length));
Should not rename unrelated methods
Before:
BEFORE
import { special } from 'valibot'; import * as vb from 'valibot'; import { Input } from '~/ui'; const foo = <Input /> const bar = special(); const baz = vb.toCustom();
After:
AFTER
import { custom } from 'valibot'; import * as vb from 'valibot'; import { Input } from '~/ui'; const foo = <Input /> const bar = custom(); const baz = vb.transform();
Should transform objects and tuples
Before:
BEFORE
const ObjectSchema = v.object({ key: v.string() }, v.null_()); const TupleSchema = v.tuple([v.string()], v.null_()); const LooseObjectSchema = v.object({ key: v.string() }, v.unknown()); const LooseTupleSchema = v.tuple([v.string()], v.unknown()); const StrictObjectSchema = v.object({ key: v.string() }, v.never()); const StrictTupleSchema = v.tuple([v.string()], v.never());
After:
AFTER
const ObjectSchema = v.objectWithRest({ key: v.string() }, v.null_()); const TupleSchema = v.tupleWithRest([v.string()], v.null_()); const LooseObjectSchema = v.looseObject({ key: v.string() }); const LooseTupleSchema = v.looseTuple([v.string()]); const StrictObjectSchema = v.strictObject({ key: v.string() }); const StrictTupleSchema = v.strictTuple([v.string()]);
Should transform object merging
Before:
BEFORE
const ObjectSchema1 = v.object({ foo: v.string() }); const ObjectSchema2 = v.object({ bar: v.number() }); const MergedObject = v.merge([ObjectSchema1, ObjectSchema2]);
After:
AFTER
const ObjectSchema1 = v.object({ foo: v.string() }); const ObjectSchema2 = v.object({ bar: v.number() }); const MergedObject = v.object({ ...ObjectSchema1.entries, ...ObjectSchema2.entries });
Should transform object with additional arguments
Before:
BEFORE
const Schema = v.merge([ObjectSchema1, ObjectSchema1], v.string(), 'Error message', [v.custom(() => true)]);
After:
AFTER
const Schema = v.pipe(v.objectWithRest({ ...ObjectSchema1.entries, ...ObjectSchema1.entries }, v.string(), 'Error message'), v.check(() => true));