Skip to content

Releases: vinejs/vine

Update dependencies

07 Apr 09:41

Choose a tag to compare

4.3.1 (2026-04-07)

What's Changed

  • chore: bump tsdown version to fix node:module static import by @kerwanp in #142

Full Changelog: v4.3.0...v4.3.1

JSON Schema Support

06 Feb 12:42

Choose a tag to compare

4.3.0 (2026-02-06)

VineJS now supports converting validation schemas to JSON Schema Draft 7 format, enabling interoperability with standard JSON Schema validators and tools.

Converting to JSON Schema

Use the .toJSONSchema() method to convert any VineJS validator to JSON Schema:

import vine from '@vinejs/vine'

const validator = vine.create({
  name: vine.string(),
  email: vine.string().email(),
  age: vine.number().min(18),
})

const jsonSchema = validator.toJSONSchema()
console.log(jsonSchema)

Output:

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "email": { "type": "string", "format": "email" },
    "age": { "type": "number", "minimum": 18 }
  },
  "required": ["name", "email", "age"],
  "additionalProperties": false
}

Using with Standard Validators

The generated JSON Schema works seamlessly with validators like AJV:

import { Ajv } from 'ajv'
import addFormats from 'ajv-formats'
import vine from '@vinejs/vine'

const ajv = new Ajv()
addFormats.default(ajv)

const validator = vine.create({
  username: vine.string().minLength(3),
  email: vine.string().email(),
  role: vine.enum(['admin', 'user', 'guest']),
})

const validate = ajv.compile(validator.toJSONSchema())

// Validate data
const isValid = validate({
  username: 'johndoe',
  email: 'john@example.com',
  role: 'admin',
})

if (!isValid) {
  console.log(validate.errors)
}

StandardSchema Compliance

VineJS validators now implement the StandardJSONSchemaV1 specification, enabling seamless integration with the broader JavaScript validation ecosystem.

const validator = vine.create({
  name: vine.string(),
})

// Access via standard interface
const schema = validator['~standard'].jsonSchema.input({
  target: 'draft-2020-12'
})

Bug Fixes

  • Handle use-case when convertEmptyStringsToNull flag is applied on a string with multiple empty spaces (5a99348), closes #138
  • handling of optional properties (571bc3e)

Features

What's Changed

New Contributors

Full Changelog: v4.2.0...v4.3.0

Partial objects, shorthand for creating object validators, new vat rule, and global transforms

11 Dec 06:50

Choose a tag to compare

4.2.0 (2025-12-11)

Shorthand method to create object validators

Introduced vine.create() method to create validators directly from top-level objects (7960e28). As a result of this, you do not have to use vine.compile(vine.object({})), just vine.create({}) will give the same result.

  import vine from '@vinejs/vine'

  // Create a validator from a plain object schema
-  const validator = vine.compile(
-    vine.object({
-      username: vine.string().minLength(3),
-      password: vine.string().minLength(8),
-      terms: vine.boolean().isTrue()
-    })
-  )
+  const validator = vine.create({
+    username: vine.string().minLength(3),
+    password: vine.string().minLength(8),
+    terms: vine.boolean().isTrue()
+  })

  // Use the validator
  const data = await validator.validate({
    username: 'johndoe',
    password: 'secret123',
    terms: true
  })

Object Schema Enhancement

Added partial() method (initially named toOptional) to make all properties of an object schema optional (#127, 08a3472)

  import vine from '@vinejs/vine'

  // Define a base schema
  const createUserValidator = vine.create({
    name: vine.string(),
    email: vine.string().email(),
    age: vine.number()
  })

  // Make all properties optional
  const updateUserValidator = vine.create(
    createUserValidator.schema.partial()
  )

  // Now all fields are optional - useful for updates/patches
  const result = await updateUserValidator.validate({
    { email: 'user@example.com' }
  })

Global Transforms

Added support for global transforms to transform date objects globally across all validators (f368feb). This will allow AdonisJS projects to always return a Luxon DateTime object when validating dates.

  import { DateTime } from 'luxon'
  import { VineDate } from '@vinejs/vine'

  declare module '@vinejs/vine/types' {
    interface VineGlobalTransforms {
      date: DateTime
    }
  }

  VineDate.transform((value) => {
    return new DateTime.fromJSDate(value)
  })

  vine.create({
    birthDate: vine.date(), // instanceof DateTime
    createdAt: vine.date() // instanceof DateTime
  })

Bug Fixes

  • allow vine.nativeFile to work with vine.unionOfTypes b34f1b0
  • object toOptional types (#130) d28c949, closes #130

Features

  • add toOptional to object (#127) 08a3472, closes #127
  • add vine.create method to create validators from top-level objects 7960e28
  • introduce global transforms to transform the date objects globally f368feb
  • make validator schema public to allow cloning it 752acff
  • rename toOptional to partial b6e3461
  • rules: add strongPassword rule (#132) b443638, closes #132
  • rules: add vat rule (#131) 999b667, closes #131
  • update types and write types benchmarks 2fea19c

Reverts

What's Changed

New Contributors

Full Changelog: v4.1.0...v4.2.0

Accept confirmation field alias via "as" property

27 Oct 09:39

Choose a tag to compare

4.1.0 (2025-10-27)

Features

  • accept confirmation field alias via "as" property (cacc3ca)

Full Changelog: v4.0.1...v4.1.0

Fix date rule to work when the field has been marked as optional

21 Oct 03:22

Choose a tag to compare

4.0.1 (2025-10-21)

Bug Fixes

What's Changed

Full Changelog: v4.0.0...v4.0.1

Bug fixes, support for standard schema, file validation, optional and nullable unions

17 Oct 04:09

Choose a tag to compare

Breaking changes

Removed BaseModifiers class

This release refactors parts of VineJS internals and removes the BaseModifiers class.
In most cases, this change will not affect your application. However, if you were extending or directly using BaseModifiers for a custom use case, you may need to adjust your implementation.
If you run into any issues, please open an issue on GitHub.


Report confirmed rule errors on the confirmation field

The confirmed rule is commonly used for fields like password to ensure a matching field (for example, password_confirmation) has the same value.
Previously, when the values didn’t match, the validation error was reported on the original field (e.g. password).

This created a poor user experience — you would see an error message like

“The values of password and password_confirmation must be the same”
next to the password field, even though the issue was with the confirmation field.

This behavior has now been corrected.
Errors from the confirmed rule are now reported on the confirmation field (e.g. password_confirmation).
Since this changes the location of validation errors, it is considered a breaking change.


Introducing dataTypeValidator

We identified a bug in how Vine handled validations when bail(false) was used.
When bail mode is disabled, all validations on a field should run — even if earlier ones fail.

For example:

const schema = vine.object({
  email: vine.string().email().minLength(5).bail(false)
})

const data = { email: 'virk' }

In this case, both email() and minLength() validations should report errors.
However, Vine stopped after the first failure because of an internal field.isValid check.
We removed this check to ensure all validations run as expected.

This change, however, introduced redundant type checks — for instance, if a field wasn’t a string, each subsequent rule (email(), minLength(), etc.) had to recheck the type manually.

To solve this, we introduced dataTypeValidator.

The dataTypeValidator is a special validator defined at the schema level (e.g. string, number, etc.).
When it fails, the compiler automatically skips all subsequent validations for that field, preventing redundant checks and improving performance.

If you’ve defined custom Schema classes:

  • Define a dataTypeValidator for each of them.
  • The validator must return true or false and report errors using the errorReporter when the check fails.

Notable improvements

Added support for the Standard Schema specification

Vine validators now implement the Standard Schema specification.
This means Vine schemas can now integrate directly with tools and frameworks that support the standard — such as Hono.

Example:

import vine from '@vinejs/vine'
import { sValidator } from '@hono/standard-validator'

const validator = vine.compile(
  vine.object({
    name: vine.string(),
    age: vine.number(),
  })
)

app.post('/', sValidator('json', validator), (c) => {
  const data = c.req.valid('json')
  return data
})

unionOfTypes now supports literal, optional, and nullable

The unionOfTypes schema type now supports the optional() and nullable() modifiers.
You can also use the literal() schema type within a union, allowing for more expressive and flexible validation rules.

Note

The union() schema type also supports optional() and nullable() modifiers.

Example:

const schema = vine.object({
  ipRange: vine
    .unionOfTypes([
      vine.string(),
      vine.array(vine.string()),
      vine.literal('*'),
    ])
    .optional()
})

Here, the ipRange field can be:

  • A string
  • An array of strings
  • The literal value '*'
  • Or completely omitted

Pick and omit properties from existing schemas

You can now compose new schemas from existing ones by picking or omitting specific properties.
This makes it easy to reuse and adapt schemas across different contexts without duplicating field definitions.

Use object.pick() to select specific properties, or object.omit() to exclude them.

Example:

const createUserSchema = vine.object({
  fullName: vine.string(),
  email: vine.string().email(),
  password: vine.string().minLength(8),
})

// Reuse part of the schema for login
const loginSchema = vine.object({
  ...createUserSchema.pick(['email', 'password']),
})

This keeps your schemas consistent, maintainable, and DRY.

Commits

Bug Fixes

  • fail positive and negative validations when value is a neutral number (9136e4f), closes #97 #117
  • Update logic of converting string values to DayJS instances (2e74503), closes #102 #123
  • issues around bail mode ([45a1cbc](45a1cbc03f9
  • a708926e75932389dc85901691de7)), closes #87
  • move date internal properties to the fieldContext and not the meta (a687229)

Code Refactoring

Features

  • add nonNegative and nonPositive number rules (bbd01bf)
  • rename vine.file to vine.nativeFile (df98e47)
  • add File schema that returns a platform native File instance (6842fdb)
  • add optional and nullable modifiers to unionOfTypes (95a5f7e), closes #75
  • add support for picking and omitting properties (6086716), closes #80
  • add support for standard schema spec (768beed), closes #93
  • allow vine.union to be optional or nullable (96aba9b), closes #75
  • introduce vine.optional and vine.null schema types (6d3c12e), closes #75
  • report confirmed error on the confirmation field and rename confirmationField to as (51ed080)

BREAKING CHANGES

  • The error for the confirmed rule is no longer reported on the same field. Instead it is reported on the _confirmation field
  • The BaseModifiers class does not exist anymore, hence cannot be exported
  • The value zero will fail validation for both positive and negative validation rules, since zero is a neutral number. If you want the old behavior, replace positive rule with nonNegative and negative rule with nonPositive.

Fix date comparison rules and positive, negative rules

16 Oct 09:08

Choose a tag to compare

BREAKING CHANGES

  • The value zero will fail validation for both positive and negative validation rules, since zero is a neutral number. If you want the old behavior, replace positive rule with nonNegative and negative rule with nonPositive.

Bug Fixes

  • fail positive and negative validations when value is a neutral number (9136e4f), closes #97 #117
  • Update logic of converting string values to DayJS instances (2e74503), closes #102 #123

Features

  • add nonNegative and nonPositive number rules (bbd01bf)
  • rename vine.file to vine.nativeFile (df98e47)

Support for standard schema, file validation, optional and nullable unions

14 Oct 09:09

Choose a tag to compare

Breaking changes

Removed BaseModifiers class

This release refactors parts of VineJS internals and removes the BaseModifiers class.
In most cases, this change will not affect your application. However, if you were extending or directly using BaseModifiers for a custom use case, you may need to adjust your implementation.
If you run into any issues, please open an issue on GitHub.


Report confirmed rule errors on the confirmation field

The confirmed rule is commonly used for fields like password to ensure a matching field (for example, password_confirmation) has the same value.
Previously, when the values didn’t match, the validation error was reported on the original field (e.g. password).

This created a poor user experience — you would see an error message like

“The values of password and password_confirmation must be the same”
next to the password field, even though the issue was with the confirmation field.

This behavior has now been corrected.
Errors from the confirmed rule are now reported on the confirmation field (e.g. password_confirmation).
Since this changes the location of validation errors, it is considered a breaking change.


Introducing dataTypeValidator

We identified a bug in how Vine handled validations when bail(false) was used.
When bail mode is disabled, all validations on a field should run — even if earlier ones fail.

For example:

const schema = vine.object({
  email: vine.string().email().minLength(5).bail(false)
})

const data = { email: 'virk' }

In this case, both email() and minLength() validations should report errors.
However, Vine stopped after the first failure because of an internal field.isValid check.
We removed this check to ensure all validations run as expected.

This change, however, introduced redundant type checks — for instance, if a field wasn’t a string, each subsequent rule (email(), minLength(), etc.) had to recheck the type manually.

To solve this, we introduced dataTypeValidator.

The dataTypeValidator is a special validator defined at the schema level (e.g. string, number, etc.).
When it fails, the compiler automatically skips all subsequent validations for that field, preventing redundant checks and improving performance.

If you’ve defined custom Schema classes:

  • Define a dataTypeValidator for each of them.
  • The validator must return true or false and report errors using the errorReporter when the check fails.

Notable improvements

Added support for the Standard Schema specification

Vine validators now implement the Standard Schema specification.
This means Vine schemas can now integrate directly with tools and frameworks that support the standard — such as Hono.

Example:

import vine from '@vinejs/vine'
import { sValidator } from '@hono/standard-validator'

const validator = vine.compile(
  vine.object({
    name: vine.string(),
    age: vine.number(),
  })
)

app.post('/', sValidator('json', validator), (c) => {
  const data = c.req.valid('json')
  return data
})

unionOfTypes now supports literal, optional, and nullable

The unionOfTypes schema type now supports the optional() and nullable() modifiers.
You can also use the literal() schema type within a union, allowing for more expressive and flexible validation rules.

Note

The union() schema type also supports optional() and nullable() modifiers.

Example:

const schema = vine.object({
  ipRange: vine
    .unionOfTypes([
      vine.string(),
      vine.array(vine.string()),
      vine.literal('*'),
    ])
    .optional()
})

Here, the ipRange field can be:

  • A string
  • An array of strings
  • The literal value '*'
  • Or completely omitted

Pick and omit properties from existing schemas

You can now compose new schemas from existing ones by picking or omitting specific properties.
This makes it easy to reuse and adapt schemas across different contexts without duplicating field definitions.

Use object.pick() to select specific properties, or object.omit() to exclude them.

Example:

const createUserSchema = vine.object({
  fullName: vine.string(),
  email: vine.string().email(),
  password: vine.string().minLength(8),
})

// Reuse part of the schema for login
const loginSchema = vine.object({
  ...createUserSchema.pick(['email', 'password']),
})

This keeps your schemas consistent, maintainable, and DRY.

Commits

Bug Fixes

  • issues around bail mode (45a1cbc), closes #87
  • move date internal properties to the fieldContext and not the meta (a687229)

Code Refactoring

Features

  • add File schema that returns a platform native File instance (6842fdb)
  • add optional and nullable modifiers to unionOfTypes (95a5f7e), closes #75
  • add support for picking and omitting properties (6086716), closes #80
  • add support for standard schema spec (768beed), closes #93
  • allow vine.union to be optional or nullable (96aba9b), closes #75
  • introduce vine.optional and vine.null schema types (6d3c12e), closes #75
  • report confirmed error on the confirmation field and rename confirmationField to as (51ed080)

BREAKING CHANGES

  • The error for the confirmed rule is no longer reported on the same field. Instead it is reported on the _confirmation field
  • The BaseModifiers class does not exist anymore, hence cannot be exported

Fix CamelCase utilities not work with keys containing numbers

13 Mar 05:26

Choose a tag to compare

3.0.1 (2025-03-13)

Bug Fixes

  • CamelCase utility to work with existing camelCase values with numbers (9012036), closes #94

Full Changelog: v3.0.0...v3.0.1

Breaking changes and bug fixes

01 Dec 04:18

Choose a tag to compare

This release contains a few breaking changes along with a handful of new improvements and bug fixes.

Breaking changes

Infer type

The infer type of schema now marks optional fields as optional within the TypeScript types. This ensures the property can be missing altogether from the data object/inferred types vs being marked as undefined explicitly. For example:

// Schema
vine.object({
    username: vine.string(),
    age: vine.number().optional(),
})

// Old output
{
    age: number | undefined;
    username: string;
}

// New output
{
    age?: number | undefined;
    username: string;
}

SUBTYPE symbol

Custom types extending the VineJS BaseLiteralType now must define the symbols.SUBTYPE property on the schema. This property can be used by schema transformers to get a more accurate type for the schema node. Here's how the StringSchema defines the SUBTYPE property.

For example:

import { symbols, BaseLiteralType } from '@vinejs/vine'

class MySchemaType extends BaseLiteralType<Input, Output, CamelCaseOutput> {
   [symbols.SUBTYPE] = 'multipartFile'
}

Bug Fixes

  • add tests to ensure field names with special chars are allowed (67f6c52), closes #50 #63 #82
  • do not use Error.captureStackTrace when not available (715e761), closes #49
  • infer types (#79) (54f5237)

Features

  • add subtype property to schema output (818fbf0), closes #64
  • add support for conditional validation in arrays, object, records and tuples (890228e), closes #71
  • add support for parsing iso8601 dates (fe61951), closes #65
  • add support for ULID validation (#58) (02d3a28)

Pull Requests

New Contributors

Full Changelog: v2.1.0...v3.0.0