From 32f871593fa256e59ccbee0c58e026e3a4e15a41 Mon Sep 17 00:00:00 2001 From: flozdra Date: Fri, 15 Nov 2024 15:55:17 +0100 Subject: [PATCH] feat: add validation rules --- content/docs/db.json | 6 ++ content/docs/guides/validation.md | 136 ++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 content/docs/guides/validation.md diff --git a/content/docs/db.json b/content/docs/db.json index 36ddf39..6d807a4 100644 --- a/content/docs/db.json +++ b/content/docs/db.json @@ -35,6 +35,12 @@ "contentPath": "./guides/seeders.md", "category": "Guides" }, + { + "permalink": "validation", + "title": "Validation rules", + "contentPath": "./guides/validation.md", + "category": "Guides" + }, { "permalink": "select-query-builder", "title": "Select query builder", diff --git a/content/docs/guides/validation.md b/content/docs/guides/validation.md new file mode 100644 index 0000000..00a4386 --- /dev/null +++ b/content/docs/guides/validation.md @@ -0,0 +1,136 @@ +--- +summary: Validation rules added to VineJS through AdonisJS container +--- + +# Validation rules + +Lucid adds validation rules to VineJS to use in your schemas. Under the hood, it registers a provider in your AdonisJS application that extends VineJS rules. +You can read more in the [AdonisJS docs](https://docs.adonisjs.com/guides/concepts/service-providers#service-providers) and [VineJS docs](https://vinejs.dev/docs/extend/custom_rules). + +You can use these rules directly from your VineJS schema. For example, the `unique` rule: + +```ts +import vine from '@vinejs/vine' + +const schema = vine.object({ + email: vine + .string() + // highlight-start + .unique({ + table: 'users', + column: 'email', + }), + // highlight-end +}) +``` + +## Unique + +Ensure the value is unique (does not exists) inside a given database table and column. + +:::note +The rule is a macro for `VineString` and `VineNumber`, so you can use it after `vine.string()` or `vine.number()`. +::: + +You may either pass a callback to query the database directly, or an object: + +- The callback must return `true` if the value is unique (does not exist), or `false` if the value already exists. +- You may also pass an options object to specify the table and column. + +```ts +// Usage with callback +const schema = vine.object({ + email: vine + .string() + // highlight-start + .unique((db, value) => { + const row = await db.from('users').where('email', value).first() + return row === null + }), + // highlight-end +}) + +// Usage with options +const schema = vine.object({ + email: vine + .string() + // highlight-start + .unique({ table: 'users', column: 'email' }), + // highlight-end +}) +``` + +Following is the list of available parameters for the unique rule: + +```ts +type UniqueRuleCallback = (db: Database, value: string, field: FieldContext) => Promise + +type UniqueRuleOptions = { + table: string + column?: string + filter?: (db: DatabaseQueryBuilderContract, value: unknown, field: FieldContext) => Promise +} +``` + +You may also use your Lucid model directly inside the callback: + +```ts +const schema = vine.object({ + email: vine + .string() + // highlight-start + .unique((_, value) => { + const row = await User.findBy('email', value) + return row === null + }), + // highlight-end +}) +``` + +## Exists + +Ensure the value exists inside a given database table and column. This is the inverse of the unique rule. + +:::note +The rule is also a macro for `VineString` and `VineNumber`, so you can use it after `vine.string()` or `vine.number()`. +::: + +You may either pass a callback to query the database directly, or an object: + +- The callback must return `true` if the value exists, `false` otherwise. +- You may also pass an option object to specify the table and column. + +```ts +// Usage with callback +const schema = vine.object({ + slug: vine + .string() + // highlight-start + .exists((db, value) => { + const row = await db.from('categories').where('slug', value).first() + return row !== null + }), + // highlight-end +}) + +// Usage with options +const schema = vine.object({ + slug: vine + .string() + // highlight-start + .exists({ table: 'categories', column: 'slug' }), + // highlight-end +}) +``` + +Following is the list of available parameters for the exists rule: + +```ts +type ExistsRuleCallback = (db: Database, value: string, field: FieldContext) => Promise + +type ExistsRuleOptions = { + table: string + column?: string + filter?: (db: DatabaseQueryBuilderContract, value: unknown, field: FieldContext) => Promise +} +```