From 92884ef2350e0fe62907f03d4d413c47f31da15a Mon Sep 17 00:00:00 2001 From: svozza Date: Wed, 10 Sep 2025 12:50:26 +0100 Subject: [PATCH 1/3] chore(event-handler): rename variables to reflect that options object is now a RequestContext --- packages/event-handler/src/rest/Router.ts | 35 ++++++++--------- packages/event-handler/src/rest/utils.ts | 4 +- packages/event-handler/src/types/rest.ts | 6 +-- .../unit/rest/ErrorHandlerRegistry.test.ts | 2 +- .../unit/rest/Router/basic-routing.test.ts | 8 ++-- .../tests/unit/rest/Router/decorators.test.ts | 16 ++++---- .../unit/rest/Router/error-handling.test.ts | 8 ++-- .../tests/unit/rest/Router/middleware.test.ts | 38 +++++++++---------- .../tests/unit/rest/utils.test.ts | 14 +++---- 9 files changed, 64 insertions(+), 67 deletions(-) diff --git a/packages/event-handler/src/rest/Router.ts b/packages/event-handler/src/rest/Router.ts index 46aa21f167..d66b772e12 100644 --- a/packages/event-handler/src/rest/Router.ts +++ b/packages/event-handler/src/rest/Router.ts @@ -79,7 +79,7 @@ class Router { * Registers a custom error handler for specific error types. * * @param errorType - The error constructor(s) to handle - * @param handler - The error handler function that returns an ErrorResponse + * @param handler - The error handler function that returns a Promise */ public errorHandler( errorType: ErrorConstructor | ErrorConstructor[], @@ -106,7 +106,7 @@ class Router { /** * Registers a custom handler for 404 Not Found errors. * - * @param handler - The error handler function for NotFoundError + * @param handler - The error handler function that returns a Promise */ public notFound(handler: ErrorHandler): void; public notFound(): MethodDecorator; @@ -127,7 +127,7 @@ class Router { /** * Registers a custom handler for 405 Method Not Allowed errors. * - * @param handler - The error handler function for MethodNotAllowedError + * @param handler - The error handler function that returns a Promise */ public methodNotAllowed(handler: ErrorHandler): void; public methodNotAllowed(): MethodDecorator; @@ -158,9 +158,9 @@ class Router { * * @example * ```typescript - * const authMiddleware: Middleware = async (params, options, next) => { + * const authMiddleware: Middleware = async (params, reqCtx, next) => { * // Authentication logic - * if (!isAuthenticated(options.request)) { + * if (!isAuthenticated(reqCtx.request)) { * return new Response('Unauthorized', { status: 401 }); * } * await next(); @@ -211,7 +211,7 @@ class Router { const request = proxyEventToWebRequest(event); - const handlerOptions: RequestContext = { + const requestContext: RequestContext = { event, context, request, @@ -234,11 +234,11 @@ class Router { ? route.handler.bind(options.scope) : route.handler; - const handlerMiddleware: Middleware = async (params, options, next) => { - const handlerResult = await handler(params, options); - options.res = handlerResultToWebResponse( + const handlerMiddleware: Middleware = async (params, reqCtx, next) => { + const handlerResult = await handler(params, reqCtx); + reqCtx.res = handlerResultToWebResponse( handlerResult, - options.res.headers + reqCtx.res.headers ); await next(); @@ -252,18 +252,18 @@ class Router { const middlewareResult = await middleware( route.params, - handlerOptions, + requestContext, () => Promise.resolve() ); // middleware result takes precedence to allow short-circuiting - const result = middlewareResult ?? handlerOptions.res; + const result = middlewareResult ?? requestContext.res; return handlerResultToProxyResult(result); } catch (error) { this.logger.debug(`There was an error processing the request: ${error}`); const result = await this.handleError(error as Error, { - ...handlerOptions, + ...requestContext, scope: options?.scope, }); return await webResponseToProxyResult(result); @@ -284,7 +284,7 @@ class Router { * back to a default handler. * * @param error - The error to handle - * @param options - Optional resolve options for scope binding + * @param options - Error resolve options including request context and scope * @returns A Response object with appropriate status code and error details */ protected async handleError( @@ -294,11 +294,8 @@ class Router { const handler = this.errorHandlerRegistry.resolve(error); if (handler !== null) { try { - const { scope, ...handlerOptions } = options; - const body = await handler.apply(scope ?? this, [ - error, - handlerOptions, - ]); + const { scope, ...reqCtx } = options; + const body = await handler.apply(scope ?? this, [error, reqCtx]); return new Response(JSON.stringify(body), { status: body.statusCode, headers: { 'Content-Type': 'application/json' }, diff --git a/packages/event-handler/src/rest/utils.ts b/packages/event-handler/src/rest/utils.ts index 7c8e897a0a..652b41b17c 100644 --- a/packages/event-handler/src/rest/utils.ts +++ b/packages/event-handler/src/rest/utils.ts @@ -153,7 +153,7 @@ export const isAPIGatewayProxyResult = ( export const composeMiddleware = (middleware: Middleware[]): Middleware => { return async ( params: Record, - options: RequestContext, + reqCtx: RequestContext, next: () => Promise ): Promise => { let index = -1; @@ -172,7 +172,7 @@ export const composeMiddleware = (middleware: Middleware[]): Middleware => { } const middlewareFn = middleware[i]; - const middlewareResult = await middlewareFn(params, options, () => + const middlewareResult = await middlewareFn(params, reqCtx, () => dispatch(i + 1) ); diff --git a/packages/event-handler/src/types/rest.ts b/packages/event-handler/src/types/rest.ts index 7586c2859f..e2005d250d 100644 --- a/packages/event-handler/src/types/rest.ts +++ b/packages/event-handler/src/types/rest.ts @@ -25,7 +25,7 @@ type ErrorResolveOptions = RequestContext & ResolveOptions; type ErrorHandler = ( error: T, - options: RequestContext + reqCtx: RequestContext ) => Promise; interface ErrorConstructor { @@ -59,7 +59,7 @@ type HandlerResponse = Response | JSONObject; type RouteHandler< TParams = Record, TReturn = HandlerResponse, -> = (args: TParams, options: RequestContext) => Promise; +> = (args: TParams, reqCtx: RequestContext) => Promise; type HttpMethod = keyof typeof HttpVerbs; @@ -84,7 +84,7 @@ type NextFunction = () => Promise; type Middleware = ( params: Record, - options: RequestContext, + reqCtx: RequestContext, next: NextFunction ) => Promise; diff --git a/packages/event-handler/tests/unit/rest/ErrorHandlerRegistry.test.ts b/packages/event-handler/tests/unit/rest/ErrorHandlerRegistry.test.ts index c7bd918a75..1dbef04f6a 100644 --- a/packages/event-handler/tests/unit/rest/ErrorHandlerRegistry.test.ts +++ b/packages/event-handler/tests/unit/rest/ErrorHandlerRegistry.test.ts @@ -8,7 +8,7 @@ import type { const createErrorHandler = (statusCode: HttpStatusCode, message?: string) => - async (error: Error, _options: RequestContext) => ({ + async (error: Error, _reqCtx: RequestContext) => ({ statusCode, error: error.name, message: message ?? error.message, diff --git a/packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts b/packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts index b86a560492..67cc33def7 100644 --- a/packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts @@ -89,11 +89,11 @@ describe('Class: Router - Basic Routing', () => { const app = new Router(); const testEvent = createTestEvent('/test', 'GET'); - app.get('/test', async (_params, options) => { + app.get('/test', async (_params, reqCtx) => { return { - hasRequest: options.request instanceof Request, - hasEvent: options.event === testEvent, - hasContext: options.context === context, + hasRequest: reqCtx.request instanceof Request, + hasEvent: reqCtx.event === testEvent, + hasContext: reqCtx.context === context, }; }); diff --git a/packages/event-handler/tests/unit/rest/Router/decorators.test.ts b/packages/event-handler/tests/unit/rest/Router/decorators.test.ts index 79dd448bed..bf66020501 100644 --- a/packages/event-handler/tests/unit/rest/Router/decorators.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/decorators.test.ts @@ -395,11 +395,11 @@ describe('Class: Router - Decorators', () => { class Lambda { @app.get('/test') - public async getTest(_params: any, options: any) { + public async getTest(_params: any, reqCtx: any) { return { - hasRequest: options.request instanceof Request, - hasEvent: options.event === testEvent, - hasContext: options.context === context, + hasRequest: reqCtx.request instanceof Request, + hasEvent: reqCtx.event === testEvent, + hasContext: reqCtx.context === context, }; } @@ -427,14 +427,14 @@ describe('Class: Router - Decorators', () => { class Lambda { @app.errorHandler(BadRequestError) - public async handleBadRequest(error: BadRequestError, options: any) { + public async handleBadRequest(error: BadRequestError, reqCtx: any) { return { statusCode: HttpErrorCodes.BAD_REQUEST, error: 'Bad Request', message: error.message, - hasRequest: options.request instanceof Request, - hasEvent: options.event === testEvent, - hasContext: options.context === context, + hasRequest: reqCtx.request instanceof Request, + hasEvent: reqCtx.event === testEvent, + hasContext: reqCtx.context === context, }; } diff --git a/packages/event-handler/tests/unit/rest/Router/error-handling.test.ts b/packages/event-handler/tests/unit/rest/Router/error-handling.test.ts index ab1f9b4f4c..1119201fe5 100644 --- a/packages/event-handler/tests/unit/rest/Router/error-handling.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/error-handling.test.ts @@ -371,13 +371,13 @@ describe('Class: Router - Error Handling', () => { const app = new Router(); const testEvent = createTestEvent('/test', 'GET'); - app.errorHandler(BadRequestError, async (error, options) => ({ + app.errorHandler(BadRequestError, async (error, reqCtx) => ({ statusCode: HttpErrorCodes.BAD_REQUEST, error: 'Bad Request', message: error.message, - hasRequest: options.request instanceof Request, - hasEvent: options.event === testEvent, - hasContext: options.context === context, + hasRequest: reqCtx.request instanceof Request, + hasEvent: reqCtx.event === testEvent, + hasContext: reqCtx.context === context, })); app.get('/test', () => { diff --git a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts index ee5c192afb..c5beae9b90 100644 --- a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts @@ -44,13 +44,13 @@ describe('Class: Router - Middleware', () => { const app = new Router(); const executionOrder: string[] = []; - app.use(async (_params, _options, next) => { + app.use(async (_params, _reqCtx, next) => { executionOrder.push('global-middleware'); await next(); }); const middleware: Middleware[] = middlewareNames.map( - (name) => async (_params, _options, next) => { + (name) => async (_params, _reqCtx, next) => { executionOrder.push(name); await next(); } @@ -137,9 +137,9 @@ describe('Class: Router - Middleware', () => { let middlewareParams: Record | undefined; let middlewareOptions: RequestContext | undefined; - app.use(async (params, options, next) => { + app.use(async (params, reqCtx, next) => { middlewareParams = params; - middlewareOptions = options; + middlewareOptions = reqCtx; await next(); }); @@ -161,7 +161,7 @@ describe('Class: Router - Middleware', () => { vi.stubEnv('POWERTOOLS_DEV', 'true'); const app = new Router(); - app.use(async (_params, _options, next) => { + app.use(async (_params, _reqCtx, next) => { await next(); await next(); }); @@ -215,7 +215,7 @@ describe('Class: Router - Middleware', () => { const app = new Router(); const executionOrder: string[] = []; - app.use(async (_params, _options, next) => { + app.use(async (_params, _reqCtx, next) => { executionOrder.push('middleware1-start'); await next(); executionOrder.push('middleware1-end'); @@ -336,10 +336,10 @@ describe('Class: Router - Middleware', () => { // Prepare const app = new Router(); - app.use(async (_params, options, next) => { + app.use(async (_params, reqCtx, next) => { await next(); - options.res.headers.set('x-custom-header', 'middleware-value'); - options.res.headers.set('x-request-id', '12345'); + reqCtx.res.headers.set('x-custom-header', 'middleware-value'); + reqCtx.res.headers.set('x-request-id', '12345'); }); app.get('/test', async () => ({ success: true })); @@ -367,10 +367,10 @@ describe('Class: Router - Middleware', () => { // Prepare const app = new Router(); - app.use(async (_params, options, next) => { + app.use(async (_params, reqCtx, next) => { await next(); - const originalBody = await options.res.text(); - options.res = new Response(`Modified: ${originalBody}`, { + const originalBody = await reqCtx.res.text(); + reqCtx.res = new Response(`Modified: ${originalBody}`, { headers: { 'content-type': 'text/plain' }, }); }); @@ -396,8 +396,8 @@ describe('Class: Router - Middleware', () => { // Prepare const app = new Router(); - app.use(async (_params, options, next) => { - options.res.headers.set('x-before-handler', 'middleware-value'); + app.use(async (_params, reqCtx, next) => { + reqCtx.res.headers.set('x-before-handler', 'middleware-value'); await next(); }); @@ -425,14 +425,14 @@ describe('Class: Router - Middleware', () => { // Prepare const app = new Router(); - app.use(async (_params, options, next) => { - options.res.headers.set('x-test-header', 'before-next'); + app.use(async (_params, reqCtx, next) => { + reqCtx.res.headers.set('x-test-header', 'before-next'); await next(); }); - app.use(async (_params, options, next) => { + app.use(async (_params, reqCtx, next) => { await next(); - options.res.headers.set('x-test-header', 'after-next'); + reqCtx.res.headers.set('x-test-header', 'after-next'); }); app.get('/test', async () => ({ success: true })); @@ -460,7 +460,7 @@ describe('Class: Router - Middleware', () => { const app = new Router(); const executionOrder: string[] = []; - app.use(async (_params, _options, next) => { + app.use(async (_params, _reqCtx, next) => { executionOrder.push('middleware-start'); await next(); executionOrder.push('middleware-end'); diff --git a/packages/event-handler/tests/unit/rest/utils.test.ts b/packages/event-handler/tests/unit/rest/utils.test.ts index 58463494f0..7a85d700af 100644 --- a/packages/event-handler/tests/unit/rest/utils.test.ts +++ b/packages/event-handler/tests/unit/rest/utils.test.ts @@ -449,12 +449,12 @@ describe('Path Utilities', () => { it('executes middleware in order', async () => { const executionOrder: string[] = []; const middleware: Middleware[] = [ - async (_params, _options, next) => { + async (_params, _reqCtx, next) => { executionOrder.push('middleware1-start'); await next(); executionOrder.push('middleware1-end'); }, - async (_params, _options, next) => { + async (_params, _reqCtx, next) => { executionOrder.push('middleware2-start'); await next(); executionOrder.push('middleware2-end'); @@ -477,10 +477,10 @@ describe('Path Utilities', () => { it('returns result from middleware that short-circuits', async () => { const middleware: Middleware[] = [ - async (_params, _options, next) => { + async (_params, _reqCtx, next) => { await next(); }, - async (_params, _options, _next) => { + async (_params, _reqCtx, _next) => { return { shortCircuit: true }; }, ]; @@ -495,7 +495,7 @@ describe('Path Utilities', () => { it('returns result from next function when middleware does not return', async () => { const middleware: Middleware[] = [ - async (_params, _options, next) => { + async (_params, _reqCtx, next) => { await next(); }, ]; @@ -510,7 +510,7 @@ describe('Path Utilities', () => { it('throws error when next() is called multiple times', async () => { const middleware: Middleware[] = [ - async (_params, _options, next) => { + async (_params, _reqCtx, next) => { await next(); await next(); }, @@ -534,7 +534,7 @@ describe('Path Utilities', () => { it('returns undefined when next function returns undefined', async () => { const middleware: Middleware[] = [ - async (_params, _options, next) => { + async (_params, _reqCtx, next) => { await next(); }, ]; From 081946baef6e36d3f1c8bd6da112bb948b0fd692 Mon Sep 17 00:00:00 2001 From: svozza Date: Wed, 10 Sep 2025 15:23:29 +0100 Subject: [PATCH 2/3] address PR feedback --- packages/event-handler/src/rest/Router.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/event-handler/src/rest/Router.ts b/packages/event-handler/src/rest/Router.ts index d66b772e12..990308287b 100644 --- a/packages/event-handler/src/rest/Router.ts +++ b/packages/event-handler/src/rest/Router.ts @@ -79,7 +79,8 @@ class Router { * Registers a custom error handler for specific error types. * * @param errorType - The error constructor(s) to handle - * @param handler - The error handler function that returns a Promise + * @param handler - The error handler that returns an + * error response> */ public errorHandler( errorType: ErrorConstructor | ErrorConstructor[], @@ -106,7 +107,8 @@ class Router { /** * Registers a custom handler for 404 Not Found errors. * - * @param handler - The error handler function that returns a Promise + * @param handler - The error handler that returns an error + * response */ public notFound(handler: ErrorHandler): void; public notFound(): MethodDecorator; @@ -127,7 +129,7 @@ class Router { /** * Registers a custom handler for 405 Method Not Allowed errors. * - * @param handler - The error handler function that returns a Promise + * @param handler - The error handler that returns an error response */ public methodNotAllowed(handler: ErrorHandler): void; public methodNotAllowed(): MethodDecorator; @@ -216,7 +218,7 @@ class Router { context, request, // this response should be overwritten by the handler, if it isn't - // it means somthing went wrong with the middleware chain + // it means something went wrong with the middleware chain res: new Response('', { status: 500 }), }; From 1a98bcd790c2aaccca1ba2ea4cde40583d91524c Mon Sep 17 00:00:00 2001 From: svozza Date: Wed, 10 Sep 2025 16:36:35 +0100 Subject: [PATCH 3/3] fix formatting issue --- packages/event-handler/src/rest/Router.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/event-handler/src/rest/Router.ts b/packages/event-handler/src/rest/Router.ts index 990308287b..1c662d96a2 100644 --- a/packages/event-handler/src/rest/Router.ts +++ b/packages/event-handler/src/rest/Router.ts @@ -79,8 +79,7 @@ class Router { * Registers a custom error handler for specific error types. * * @param errorType - The error constructor(s) to handle - * @param handler - The error handler that returns an - * error response> + * @param handler - The error handler that returns an error response */ public errorHandler( errorType: ErrorConstructor | ErrorConstructor[],