diff --git a/content/docs/extend/custom_rules.md b/content/docs/extend/custom_rules.md index d99df84..714c9ef 100644 --- a/content/docs/extend/custom_rules.md +++ b/content/docs/extend/custom_rules.md @@ -261,6 +261,8 @@ export const uniqueRule = vine.createRule(unique, { }) ``` +With the [synchronous validation APIs](../guides/getting_started.md#synchronous-validation), schemas containing async rules are rejected on the first sync call. Declaring a rule synchronous does not make it compatible if it returns a Promise or thenable. Sync validation rejects such a return value at runtime. + ## Testing rules You may use the `validator` test factory to write unit tests for your custom validation rules. diff --git a/content/docs/guides/getting_started.md b/content/docs/guides/getting_started.md index bb86ed2..2428357 100644 --- a/content/docs/guides/getting_started.md +++ b/content/docs/guides/getting_started.md @@ -117,6 +117,60 @@ const validator = vine.create({ }) ``` +## Synchronous validation + +Use `validateSync` when your code needs a result without returning or awaiting a Promise. It returns the validated output directly, typed as `Infer`, and throws validation errors immediately. This API is for synchronous code paths, not a performance optimization. + +```ts +import vine from '@vinejs/vine' + +const validator = vine.create({ + email: vine.string().email(), + age: vine.number(), +}) + +const data = { email: 'virk@example.com', age: '32' } +const output = validator.validateSync(data) +// { email: 'virk@example.com', age: 32 } +``` + +To receive validation errors as a return value, use `tryValidateSync`. It returns `[ValidationError, null]` on failure or `[null, Infer]` on success, without a Promise. + +```ts +const [error, output] = validator.tryValidateSync(data) + +if (error) { + console.log(error.messages) +} else { + console.log(output.email) +} +``` + +`tryValidateSync` catches only `ValidationError`. Other errors, including incompatible async rules, still throw. + +Both methods accept the same options as their async counterparts, including [metadata](./schema_101.md#validation-metadata), [`messagesProvider`](./custom_error_messages.md#registering-messages-provider), and [`errorReporter`](./error_reporter.md#registering-the-error-reporter). Metadata declared with `vine.withMetaData` remains required. + +The `vine` instance also provides shortcuts that accept the schema, data, and validation options in one object. + +```ts +const schema = vine.object({ + email: vine.string().email(), +}) + +const output = vine.validateSync({ schema, data }) +const [error, result] = vine.tryValidateSync({ schema, data }) +``` + +A validator compiles its synchronous validation function on the first sync call and caches it for later calls. Reuse a validator when validating repeatedly instead of using the shortcuts. + +### Compatible schemas + +The entire schema must be synchronous, including rules inside nested objects, arrays, unions, and conditional branches, even branches that the current input does not use. For example, [`activeUrl()`](../types/string.md#activeurl) performs an async DNS lookup and cannot be used with synchronous validation. + +The first sync call rejects a schema containing any async rule. You can still create that validator and use its async methods. A custom rule declared synchronous that returns a Promise or thenable is rejected at runtime. + +The existing `validate`, `tryValidate`, and Standard Schema `~standard.validate` methods remain asynchronous and unchanged. + ## Handling errors In case of an error, VineJS will throw a [ValidationError](https://github.com/vinejs/vine/blob/main/src/errors/validation_error.ts) exception. You may access the detailed error messages using the `error.messages` property. diff --git a/content/docs/types/string.md b/content/docs/types/string.md index b7ebe4e..ed611fb 100644 --- a/content/docs/types/string.md +++ b/content/docs/types/string.md @@ -126,6 +126,8 @@ vine.object({ Ensure the URL value of a field has valid `A` or `AAAA` DNS records. The DNS lookup is performed using the [dnsPromises.resolve](https://nodejs.org/api/dns.html#dnspromisesresolvehostname-rrtype) method. +This rule is asynchronous and cannot be used with the [`validateSync` or `tryValidateSync` APIs](../guides/getting_started.md#synchronous-validation). Use `validate` or `tryValidate` for schemas containing this rule. + ```ts vine.object({ health_checks_url: vine