Created
December 19, 2022 00:45
-
-
Save adamgarcia4/7b5644bb6bb5d3daabf5f8377c5b66b4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const swaggerValidationMiddleware = | |
(routeConfig: ISwaggerParams) => { | |
const AdditionalResponses: { [statusCode: string]: ResponseConfig } = { | |
422: { | |
description: 'Invalid input', | |
content: { | |
'application/json': { | |
schema: z.object({ | |
code: z.string(), | |
message: z.string(), | |
expected: z.string(), | |
received: z.string(), | |
path: z.array(z.string()), | |
}), | |
}, | |
}, | |
}, | |
500: { | |
description: 'Internal Server Error', | |
}, | |
} | |
Object.assign(routeConfig.responses, AdditionalResponses) | |
registerRoute(routeConfig) // This calls registry.registerPath. | |
return (req: Request, res: Response, next: NextFunction) => { | |
if (!routeConfig.request) { | |
return next() | |
} | |
const send = res.send | |
const { headers, params, query, body } = routeConfig.request | |
try { | |
if (headers) { | |
for (const header of (headers)) { | |
try { | |
Object.assign(req.headers, header.parse(req.headers)) | |
} catch (error) { | |
throw new Error(JSON.stringify({ type: 'headers', error } as ErrorStructure)) | |
} | |
} | |
} | |
if (params) { | |
const requestSchema = params | |
try { | |
Object.assign(req.params, requestSchema.parse(req.params)) | |
} catch (error) { | |
throw new Error(JSON.stringify({ type: 'params', error } as ErrorStructure)) | |
} | |
} | |
if (query) { | |
const requestSchema = query | |
try { | |
Object.assign(req.query, requestSchema.parse(req.query)) | |
} catch (error) { | |
throw new Error(JSON.stringify({ type: 'query', error } as ErrorStructure)) | |
} | |
} | |
if (body) { | |
const requestSchema = body | |
let isSuccess = false | |
let error: z.ZodError | null = null | |
for (const content of Object.values(requestSchema.content || {})) { | |
const { schema } = content | |
if ('safeParse' in schema) { | |
const test = schema.safeParse(req.body) | |
if (test.success) { | |
isSuccess = true | |
break | |
} | |
error = test.error | |
} | |
} | |
if (!isSuccess) { | |
throw new Error(JSON.stringify({ type: 'body', error } as ErrorStructure)) | |
} | |
} | |
res.send = function (body) { | |
// Override once! | |
res.send = send | |
if (!routeConfig.responses?.[res.statusCode]) { | |
console.log('No response schema for status code: ', res.statusCode) | |
return res.send('No response schema for status code: ' + res.statusCode) | |
} | |
const responseSchema = routeConfig.responses[res.statusCode] | |
let isSuccess = false | |
let error: ZodError | null = null | |
for (const content of Object.values(responseSchema.content || {})) { | |
const { schema } = content | |
if ('safeParse' in schema) { | |
const test = schema.safeParse(body) as any | |
if (test.success) { | |
return res.send(body) | |
} | |
error = test.error | |
} | |
} | |
if (!isSuccess) { | |
console.log('No response schema for status code: ', res.statusCode) | |
return res.status(422).send({ | |
response: error?.issues ?? [] | |
}) | |
} | |
return res.send(body) | |
} | |
next() | |
} catch (error) { | |
console.log('error!') | |
const errorObj = JSON.parse(error.message) as ErrorStructure | |
return res.send({ | |
[errorObj.type]: errorObj.error.issues | |
}) | |
} | |
} | |
} | |
// Usage | |
router.get( | |
'/pathName', | |
swaggerMiddleware({ | |
method: 'get', | |
path: '/pathName', | |
description: 'Description', | |
summary: 'Summary...', | |
request: { | |
query: z.object({queryParam: z.string()}), | |
}, | |
responses: { | |
200: { | |
description: 'This is the happy path', | |
content: { | |
'application/json': { | |
schema: z.object({data: z.string()}), | |
}, | |
}, | |
}, | |
}, | |
}), | |
(req, res) => {...} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment