Extend validators with Medusa.js 1.8.x and up
Are you building a commerce store with Medusa.js and want to add custom validators to your products?
With Medusa.js version >=1.8.x
, it's now possible to extend and add new properties to validators that are triggered on some endpoints.
In this guide, I'll walk you through the steps required to extend core validators with Medusa.js. Let's get started!
Extending Core Validators
In that new version of Medusa.js, you can add file loaders that will be executed when the server is launched. These loaders allow you to fully customize Medusa.js to your needs.
Create an utility function
The first step to extending core validators is to create a function that allows you to override the validator in question. Here's an example of what this function might look like:
// src/utils/register-extended-validator.ts
import { ValidatorOptions } from 'class-validator'
import { ClassConstructor } from '@medusajs/medusa'
const extendedValidators: any = []
let isInitialized = false
export async function registerExtendedValidator<
T extends ClassConstructor<any>,
>(classValidator: T): Promise<void> {
extendedValidators.push(classValidator)
if (isInitialized) {
return
}
isInitialized = true
const module = await import('@medusajs/medusa/dist/utils/validator')
const originalValidator = module.validator
module.validator = <T extends ClassConstructor<any> = any, V = any>(
typedClass: T,
plain: V,
config?: ValidatorOptions,
): Promise<any> => {
for (const extendedValidator of extendedValidators) {
if (extendedValidator.name === typedClass.name) {
typedClass = extendedValidator
break
}
}
return originalValidator(typedClass, plain, config)
}
}
This code accepts a validator as a parameter.
This validator will be used to find a match in existing internal validators. Once the validator has been found it will be overridden ✅
Create an extended validator
In my case I decided to extend the product creation validator to add a new property store_id
.
// We alias the core validator so we can have the EXACT same name as the core validator.
import { AdminPostProductsReq as MedusaAdminPostProductsReq } from '@medusajs/medusa'
import { IsEnum, IsString } from 'class-validator'
export class AdminPostProductsReq extends MedusaAdminPostProductsReq {
@IsString()
store_id: string
}
Call the Function in a Loader
Now you need to call this function inside a loader with a custom validator.
A loader is a file that exports a function that Medusa.js will execute when the server is launched.
Here's an example of what the loader might look like:
// src/loaders/index.ts
export default async function () {
registerExtendedValidator(AdminPostProductsReq)
}
This loader calls the registerExtendedValidator
function and passes in the new AdminPostProductsReq
class to register an extended validator for the create product endpoint.
This means that my endpoint will now wait for store_id
to be part of the new DTO.
Conclusion
That's it! You've now learned how to extend core validators with Medusa.js 1.8.x.
By using this function inside a loader and registering an extended version of a specific validator, you can add custom validation logic to your Medusa.js commerce store.
I hope you found this guide helpful.
If you have any questions or comments, feel free to leave them below.
A special thanks to Adrien De Peretti for his help with this.