feat: Add zod middleware (#6961)
This commit is contained in:
1 parent
ee73031d0e
commit
5ba74ec5fc
4 files changed
+125
-2
No files matched your search
@@ -102,7 +102,8 @@
|
|||||||
"scrypt-kdf": "^2.0.1",
|
"scrypt-kdf": "^2.0.1",
|
||||||
"ulid": "^2.3.0",
|
"ulid": "^2.3.0",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"winston": "^3.8.2"
|
"winston": "^3.8.2",
|
||||||
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"gitHead": "cd1f5afa5aa8c0b15ea957008ee19f1d695cbd2e"
|
"gitHead": "cd1f5afa5aa8c0b15ea957008ee19f1d695cbd2e"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
import { zodValidator } from "../validate-body"
|
||||||
|
|
||||||
|
describe("zodValidator", () => {
|
||||||
|
it("should validate and return validated", async () => {
|
||||||
|
const schema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const toValidate = {
|
||||||
|
id: "1",
|
||||||
|
name: "Tony Stark",
|
||||||
|
}
|
||||||
|
|
||||||
|
const validated = await zodValidator(schema, toValidate)
|
||||||
|
|
||||||
|
expect(JSON.stringify(validated)).toBe(
|
||||||
|
JSON.stringify({
|
||||||
|
id: "1",
|
||||||
|
name: "Tony Stark",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should show human readable error message", async () => {
|
||||||
|
const schema = z
|
||||||
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
test: z.object({
|
||||||
|
name: z.string(),
|
||||||
|
test2: z.object({
|
||||||
|
name: z.string(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
|
const toValidate = {
|
||||||
|
id: "1",
|
||||||
|
name: "Tony Stark",
|
||||||
|
company: "Stark Industries",
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorMessage = await zodValidator(schema, toValidate).catch(
|
||||||
|
(e) => e.message
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(errorMessage).toContain(
|
||||||
|
"Invalid request body: "
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should allow for non-strict parsing", async () => {
|
||||||
|
const schema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const toValidate = {
|
||||||
|
id: "1",
|
||||||
|
name: "Tony Stark",
|
||||||
|
company: "Stark Industries",
|
||||||
|
}
|
||||||
|
|
||||||
|
const validated = await zodValidator(schema, toValidate, { strict: false })
|
||||||
|
|
||||||
|
expect(JSON.stringify(validated)).toBe(
|
||||||
|
JSON.stringify({
|
||||||
|
id: "1",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { MedusaError } from "@medusajs/utils"
|
||||||
|
import { NextFunction } from "express"
|
||||||
|
import { z, ZodError } from "zod"
|
||||||
|
import { MedusaRequest, MedusaResponse } from "../../types/routing"
|
||||||
|
|
||||||
|
export async function zodValidator<T>(
|
||||||
|
zodSchema: z.ZodObject<any, any>,
|
||||||
|
body: T,
|
||||||
|
config: { strict?: boolean } = { strict: true }
|
||||||
|
): Promise<z.ZodRawShape> {
|
||||||
|
try {
|
||||||
|
let schema = zodSchema
|
||||||
|
if (config.strict) {
|
||||||
|
schema = schema.strict()
|
||||||
|
}
|
||||||
|
|
||||||
|
return await schema.parseAsync(body)
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof ZodError) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_DATA,
|
||||||
|
`Invalid request body: ${JSON.stringify(err.errors)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateAndTransformBody(
|
||||||
|
zodSchema: z.ZodObject<any, any>,
|
||||||
|
config?: {
|
||||||
|
strict?: boolean
|
||||||
|
}
|
||||||
|
): (
|
||||||
|
req: MedusaRequest,
|
||||||
|
res: MedusaResponse,
|
||||||
|
next: NextFunction
|
||||||
|
) => Promise<void> {
|
||||||
|
return async (req: MedusaRequest, _: MedusaResponse, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
req.validatedBody = await zodValidator(zodSchema, req.body, config)
|
||||||
|
next()
|
||||||
|
} catch (e) {
|
||||||
|
next(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8577,6 +8577,7 @@ __metadata:
|
|||||||
ulid: ^2.3.0
|
ulid: ^2.3.0
|
||||||
uuid: ^9.0.0
|
uuid: ^9.0.0
|
||||||
winston: ^3.8.2
|
winston: ^3.8.2
|
||||||
|
zod: ^3.22.4
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
medusa-interfaces: ^1.3.7
|
medusa-interfaces: ^1.3.7
|
||||||
typeorm: ^0.3.16
|
typeorm: ^0.3.16
|
||||||
@@ -52991,7 +52992,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"zod@npm:3.22.4":
|
"zod@npm:3.22.4, zod@npm:^3.22.4":
|
||||||
version: 3.22.4
|
version: 3.22.4
|
||||||
resolution: "zod@npm:3.22.4"
|
resolution: "zod@npm:3.22.4"
|
||||||
checksum: 7578ab283dac0eee66a0ad0fc4a7f28c43e6745aadb3a529f59a4b851aa10872b3890398b3160f257f4b6817b4ce643debdda4fb21a2c040adda7862cab0a587
|
checksum: 7578ab283dac0eee66a0ad0fc4a7f28c43e6745aadb3a529f59a4b851aa10872b3890398b3160f257f4b6817b4ce643debdda4fb21a2c040adda7862cab0a587
|
||||||
|
|||||||
Reference in new issue
Block a user