fix: allow additional_data to be undefined or null (#9687)

This commit is contained in:
Harminder Virk
2024-10-21 13:44:21 +05:30
committed by GitHub
parent fa15db4538
commit 63fff01f2f
5 changed files with 95 additions and 17 deletions
@@ -16,6 +16,44 @@ describe("validateAndTransformBody", () => {
}) })
it("should pass additionalDataValidator to validator factory", async () => { it("should pass additionalDataValidator to validator factory", async () => {
let mockRequest = {
query: {},
body: {
additional_data: {},
},
} as MedusaRequest
const mockResponse = {} as MedusaResponse
const nextFunction = jest.fn()
mockRequest.additionalDataValidator = zod
.object({
brand_id: zod.number(),
})
.nullish()
const validatorFactory = (
schema?: Zod.ZodOptional<Zod.ZodNullable<Zod.ZodObject<any, any>>>
) => {
return schema
? createLinkBody().extend({
additional_data: schema,
})
: createLinkBody()
}
let middleware = validateAndTransformBody(validatorFactory)
await middleware(mockRequest, mockResponse, nextFunction)
expect(nextFunction.mock.calls[0]).toEqual([
new MedusaError(
"invalid_data",
`Invalid request: Field 'additional_data, brand_id' is required`
),
])
})
it("should allow additional_data to be undefined", async () => {
let mockRequest = { let mockRequest = {
query: {}, query: {},
body: {}, body: {},
@@ -24,22 +62,58 @@ describe("validateAndTransformBody", () => {
const mockResponse = {} as MedusaResponse const mockResponse = {} as MedusaResponse
const nextFunction = jest.fn() const nextFunction = jest.fn()
mockRequest.additionalDataValidator = zod.object({ mockRequest.additionalDataValidator = zod
.object({
brand_id: zod.number(), brand_id: zod.number(),
}) })
.nullish()
const validatorFactory = (schema?: Zod.ZodObject<any, any>) => { const validatorFactory = (
return schema ? createLinkBody().merge(schema) : createLinkBody() schema?: Zod.ZodOptional<Zod.ZodNullable<Zod.ZodObject<any, any>>>
) => {
return schema
? createLinkBody().extend({
additional_data: schema,
})
: createLinkBody()
} }
let middleware = validateAndTransformBody(validatorFactory) let middleware = validateAndTransformBody(validatorFactory)
await middleware(mockRequest, mockResponse, nextFunction) await middleware(mockRequest, mockResponse, nextFunction)
expect(nextFunction).toHaveBeenCalledWith( expect(nextFunction.mock.calls[0]).toEqual([])
new MedusaError( })
"invalid_data",
`Invalid request: Field 'brand_id' is required` it("should allow additional_data nested properties to be undefined", async () => {
) let mockRequest = {
) query: {},
body: {
additional_data: {},
},
} as MedusaRequest
const mockResponse = {} as MedusaResponse
const nextFunction = jest.fn()
mockRequest.additionalDataValidator = zod
.object({
brand_id: zod.number().optional(),
})
.nullish()
const validatorFactory = (
schema?: Zod.ZodOptional<Zod.ZodNullable<Zod.ZodObject<any, any>>>
) => {
return schema
? createLinkBody().extend({
additional_data: schema,
})
: createLinkBody()
}
let middleware = validateAndTransformBody(validatorFactory)
await middleware(mockRequest, mockResponse, nextFunction)
expect(nextFunction.mock.calls[0]).toEqual([])
}) })
}) })
+2 -2
View File
@@ -1,5 +1,5 @@
import type { NextFunction, Request, Response } from "express" import type { NextFunction, Request, Response } from "express"
import { ZodObject } from "zod" import { ZodNullable, ZodObject, ZodOptional } from "zod"
import { import {
FindConfig, FindConfig,
@@ -148,7 +148,7 @@ export interface MedusaRequest<Body = unknown>
* Custom validator to validate the `additional_data` property in * Custom validator to validate the `additional_data` property in
* requests that allows for additional_data * requests that allows for additional_data
*/ */
additionalDataValidator?: ZodObject<any, any> additionalDataValidator?: ZodOptional<ZodNullable<ZodObject<any, any>>>
} }
export interface AuthContext { export interface AuthContext {
@@ -47,7 +47,9 @@ export function defineMiddlewares<
*/ */
if (additionalDataValidator) { if (additionalDataValidator) {
customMiddleware.push((req, _, next) => { customMiddleware.push((req, _, next) => {
req.additionalDataValidator = zod.object(additionalDataValidator) req.additionalDataValidator = zod
.object(additionalDataValidator)
.nullish()
next() next()
}) })
} }
@@ -7,7 +7,7 @@ export function validateAndTransformBody(
zodSchema: zodSchema:
| z.ZodObject<any, any> | z.ZodObject<any, any>
| (( | ((
customSchema?: z.ZodObject<any, any> customSchema?: z.ZodOptional<z.ZodNullable<z.ZodObject<any, any>>>
) => z.ZodObject<any, any> | z.ZodEffects<any, any>) ) => z.ZodObject<any, any> | z.ZodEffects<any, any>)
): ( ): (
req: MedusaRequest, req: MedusaRequest,
+4 -2
View File
@@ -1,4 +1,4 @@
import { z, ZodEffects, ZodObject } from "zod" import { z, ZodEffects, ZodNullable, ZodObject, ZodOptional } from "zod"
/** /**
* Wraps the original schema to a function to accept and merge * Wraps the original schema to a function to accept and merge
@@ -8,7 +8,9 @@ export const WithAdditionalData = <T extends ZodObject<any, any>>(
originalSchema: T, originalSchema: T,
modifyCallback?: (schema: T) => ZodObject<any, any> | ZodEffects<any, any> modifyCallback?: (schema: T) => ZodObject<any, any> | ZodEffects<any, any>
) => { ) => {
return (additionalDataValidator?: ZodObject<any, any>) => { return (
additionalDataValidator?: ZodOptional<ZodNullable<ZodObject<any, any>>>
) => {
let schema: ZodObject<any, any> let schema: ZodObject<any, any>
if (!additionalDataValidator) { if (!additionalDataValidator) {