From 1b19590c9933ac6a4c129337d6988d724589bb54 Mon Sep 17 00:00:00 2001 From: Evert De Spiegeleer Date: Sun, 7 Jan 2024 20:51:13 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20allow=20non-async=20handler?= =?UTF-8?q?s=20on=20endpoints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/endpoint.ts | 17 +++++++++++------ src/util/endpoint.unit.test.ts | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/util/endpoint.ts b/src/util/endpoint.ts index 3094a56..0b4e62f 100644 --- a/src/util/endpoint.ts +++ b/src/util/endpoint.ts @@ -4,6 +4,7 @@ import type { NextFunction, Request, Response } from 'express' import { type Middleware } from './middleware.js' import { type EndpointOasInfo } from '../oas.js' import { NotImplementedError, ValidationError } from './errors.js' +import { isPromise } from 'util/types' const methods = [ 'get', @@ -51,7 +52,7 @@ export interface EndpointOptions< inputs: z.infer, req: Request, res: Response, - ) => Promise> + ) => Promise> | z.infer inputValidationSchema?: InputsSchema responseValidationSchema?: OutputSchema responseContentType: string @@ -267,14 +268,18 @@ export const endpointToExpressHandler = (endpoint: AnyEndpoint) => { const { params, query, body } = req - if (endpoint.getHandler() == null) { + const handler = endpoint.getHandler() + + if (handler == null) { next(new NotImplementedError()) return } - endpoint - .getHandler()?.({ params, query, body }, req, res) - .then((responseObj) => { + // Turn any hanler, async or not, into an async handler + const asyncHandler = isPromise(handler) ? handler : async (input: Parameters[0], req: Parameters[1], res: Parameters[2]): Promise> => handler(input, req, res) + + asyncHandler({ params, query, body }, req, res) + .then((responseObj: any) => { // Output validation try { endpoint.getResponseValidationSchema()?.parse(responseObj) @@ -287,7 +292,7 @@ export const endpointToExpressHandler = (endpoint: AnyEndpoint) => { res.header('content-type', endpoint.getResponseContentType()) res.send(responseObj) }) - .catch((e) => { + .catch((e: any) => { next(e) }) } diff --git a/src/util/endpoint.unit.test.ts b/src/util/endpoint.unit.test.ts index 264a6a0..be45548 100644 --- a/src/util/endpoint.unit.test.ts +++ b/src/util/endpoint.unit.test.ts @@ -57,7 +57,7 @@ describe('endpoint', () => { }) ) .response(zApiOutput(z.string())) - .handler(async ({ query }) => { + .handler(({ query }) => { return apiResponse(`Hello ${query.name ?? 'everyone'}!`) }) })