Skip to content

Zod Refine

You can use Zod Refine to implement more flexible validation rules

Create Zod Refine

For example, create a Zod Refine nameExists in the module demo-student to check if the student name already exists

1. Cli command

bash
$ vona :create:bean zodRefine nameExists --module=demo-student

2. Menu command

TIP

Context Menu - [Module Path]: Vona Bean/Zod Refine

Zod Refine Definition

typescript
export interface TypeZodRefineNameExistsData { name: string }

export interface IZodRefineOptionsNameExists extends IDecoratorZodRefineOptions {}

@ZodRefine<IZodRefineOptionsNameExists>()
class ZodRefineNameExists {
  async execute(value: TypeZodRefineNameExistsData, refinementCtx: TypeRefinementCtx, _options: IZodRefineOptionsNameExists) {
    const student = await this.scope.model.student.getByName(value.name);
    if (student) {
      refinementCtx.addIssue({
        code: 'custom',
        message: 'Student Exists',
        path: ['name'],
      });
    }
  }
}
  • TypeZodRefineNameExistsData: Input parameter type
  • IZodRefineOptionsNameExists: Defines Zod Refine parameters
  • execute: Validates the input parameter. If the student already exists, refinementCtx.addIssue is called to generate a custom error message

Using Zod Refine

diff
import { v } from 'vona-module-a-openapi';

@Controller()
class ControllerStudent {
  @Web.post()
+ async create(@Arg.body(v.refine('demo-student:nameExists')) student: DtoStudentCreate) {}
}
  • v.refine: This function is used to use Zod Refine. Simply pass the Zod Refine name
    • The nameExists Zod Refine belongs to the demo-student module, so the full name is demo-student:nameExists

Zod Refine Parameters

You can define parameters for Zod Refine, allowing for more flexible configuration of Zod Refine logic

For example, define the errorMessage parameter for the nameExists Zod Refine to provide custom error message

1. Defining parameter types

diff
export interface IZodRefineOptionsNameExists extends IDecoratorZodRefineOptions {
+ errorMessage: string;
}

2. Providing default values ​​for parameters

diff
@ZodRefine<IZodRefineOptionsNameExists>({
+ errorMessage: 'Student Exists',
})

3. Using Parameters

diff
export interface TypeZodRefineNameExistsData { name: string }

export interface IZodRefineOptionsNameExists extends IDecoratorZodRefineOptions {
  errorMessage: string;
}

@ZodRefine<IZodRefineOptionsNameExists>({
  errorMessage: 'Student Exists',
})
class ZodRefineNameExists {
  async execute(value: TypeZodRefineNameExistsData, refinementCtx: TypeRefinementCtx, options: IZodRefineOptionsNameExists) {
    const student = await this.scope.model.student.getByName(value.name);
    if (student) {
      refinementCtx.addIssue({
        code: 'custom',
-       message: 'Student Exists',
+       message: options.errorMessage,
        path: ['name'],
      });
    }
  }
}

4. Specify parameters when using

You can specify Zod Refine parameters when using

diff
class ControllerStudent {
  @Web.post()
+ async create(@Arg.body(v.refine('demo-student:nameExists', { errorMessage: 'Student Exists!!!' })) student: DtoStudentCreate) {}
}

5. App config

Zod Refine parameters can be configured in App config

src/backend/config/config/config.ts

typescript
// onions
config.onions = {
  zodRefine: {
    'demo-student:nameExists': {
      errorMessage: 'Student Exists!!!',
    },
  },
};

6. Parameter precedence

Specify parameters when using > App config > Default values

Released under the MIT License.