From a4a7175a7f42b05cd5beb228426ff0905d908474 Mon Sep 17 00:00:00 2001 From: Matt Mower <135273348+mdmower-csnw@users.noreply.github.com> Date: Sat, 1 Jun 2024 18:44:13 -0700 Subject: [PATCH] Support async operation handler resolver (#921) - Let users define operationHandlers.resolver as a synchronous or asynchronous function that returns a request handler - Make installOperationHandlers and asynchronous function that awaits a resolver promise (automatically wraps resolver with promise if needed) - Update operation handlers middleware to handle an async installOperationHandlers. --- src/framework/types.ts | 11 ++++++++--- src/openapi.validator.ts | 15 +++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/framework/types.ts b/src/framework/types.ts index 7cc4167a..420f42dc 100644 --- a/src/framework/types.ts +++ b/src/framework/types.ts @@ -1,7 +1,8 @@ import * as ajv from 'ajv'; import * as multer from 'multer'; -import { FormatsPluginOptions, FormatOptions } from 'ajv-formats'; -import { Request, Response, NextFunction } from 'express'; +import { FormatsPluginOptions } from 'ajv-formats'; +import { Request, Response, NextFunction, RequestHandler } from 'express'; +import { RouteMetadata } from './openapi.spec.loader'; export { OpenAPIFrameworkArgs }; export type BodySchema = @@ -63,7 +64,11 @@ export type ValidateSecurityOpts = { export type OperationHandlerOptions = { basePath: string; - resolver: Function; + resolver: ( + handlersPath: string, + route: RouteMetadata, + apiDoc: OpenAPIV3.Document, + ) => RequestHandler | Promise; }; export type Format = { diff --git a/src/openapi.validator.ts b/src/openapi.validator.ts index 43073be0..3265c187 100644 --- a/src/openapi.validator.ts +++ b/src/openapi.validator.ts @@ -221,11 +221,8 @@ export class OpenApiValidator { middlewares.push(function operationHandlersMiddleware(req, res, next) { if (router) return router(req, res, next); return pContext - .then( - ({ context }) => - (router = self.installOperationHandlers(req.baseUrl, context)), - ) - .then((router) => router(req, res, next)) + .then(({context}) => self.installOperationHandlers(req.baseUrl, context)) + .then((installedRouter) => (router = installedRouter)(req, res, next)) .catch(next); }); } @@ -304,7 +301,7 @@ export class OpenApiValidator { ).validate(); } - installOperationHandlers(baseUrl: string, context: OpenApiContext): Router { + async installOperationHandlers(baseUrl: string, context: OpenApiContext): Promise { const router = express.Router({ mergeParams: true }); this.installPathParams(router, context); @@ -324,10 +321,8 @@ export class OpenApiValidator { expressRoute.indexOf(baseUrl) === 0 ? expressRoute.substring(baseUrl.length) : expressRoute; - router[method.toLowerCase()]( - path, - resolver(basePath, route, context.apiDoc), - ); + const handler = await resolver(basePath, route, context.apiDoc); + router[method.toLowerCase()](path, handler); } } return router;