Migrate to v0.31.0

JavaScript pattern

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));