diff --git a/examples/snippets/event-handler/rest/gettingStarted_error_handling.ts b/examples/snippets/event-handler/rest/gettingStarted_error_handling.ts index 9465fa6d02..87431c151a 100644 --- a/examples/snippets/event-handler/rest/gettingStarted_error_handling.ts +++ b/examples/snippets/event-handler/rest/gettingStarted_error_handling.ts @@ -2,7 +2,7 @@ declare function getTodoById(todoId: unknown): Promise<{ id: string } & T>; declare class GetTodoError extends Error {} import { - HttpErrorCodes, + HttpStatusCodes, Router, } from '@aws-lambda-powertools/event-handler/experimental-rest'; import { Logger } from '@aws-lambda-powertools/logger'; @@ -15,7 +15,7 @@ app.errorHandler(GetTodoError, async (error, reqCtx) => { logger.error('Unable to get todo', { error }); return { - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, message: `Bad request: ${error.message} - ${reqCtx.request.headers.get('x-correlation-id')}`, error: 'BadRequest', }; diff --git a/examples/snippets/event-handler/rest/gettingStarted_handle_not_found.ts b/examples/snippets/event-handler/rest/gettingStarted_handle_not_found.ts index 970fc7b294..7a44fbf0fd 100644 --- a/examples/snippets/event-handler/rest/gettingStarted_handle_not_found.ts +++ b/examples/snippets/event-handler/rest/gettingStarted_handle_not_found.ts @@ -1,5 +1,5 @@ import { - HttpErrorCodes, + HttpStatusCodes, Router, } from '@aws-lambda-powertools/event-handler/experimental-rest'; import { Logger } from '@aws-lambda-powertools/logger'; @@ -12,7 +12,7 @@ app.notFound(async (error, reqCtx) => { logger.error('Unable to get todo', { error }); return { - statusCode: HttpErrorCodes.IM_A_TEAPOT, + statusCode: HttpStatusCodes.IM_A_TEAPOT, body: "I'm a teapot!", headers: { 'x-correlation-id': reqCtx.request.headers.get('x-correlation-id'), diff --git a/packages/event-handler/src/rest/Router.ts b/packages/event-handler/src/rest/Router.ts index 8d1766a2dc..cbff596d09 100644 --- a/packages/event-handler/src/rest/Router.ts +++ b/packages/event-handler/src/rest/Router.ts @@ -21,7 +21,7 @@ import type { RestRouterOptions, RouteHandler, } from '../types/rest.js'; -import { HttpErrorCodes, HttpVerbs } from './constants.js'; +import { HttpStatusCodes, HttpVerbs } from './constants.js'; import { handlerResultToProxyResult, handlerResultToWebResponse, @@ -214,7 +214,7 @@ class Router { // We can't throw a MethodNotAllowedError outside the try block as it // will be converted to an internal server error by the API Gateway runtime return { - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, body: '', }; } @@ -327,14 +327,15 @@ class Router { } if (!body.statusCode) { if (error instanceof NotFoundError) { - body.statusCode = HttpErrorCodes.NOT_FOUND; + body.statusCode = HttpStatusCodes.NOT_FOUND; } else if (error instanceof MethodNotAllowedError) { - body.statusCode = HttpErrorCodes.METHOD_NOT_ALLOWED; + body.statusCode = HttpStatusCodes.METHOD_NOT_ALLOWED; } } return new Response(JSON.stringify(body), { status: - (body.statusCode as number) ?? HttpErrorCodes.INTERNAL_SERVER_ERROR, + (body.statusCode as number) ?? + HttpStatusCodes.INTERNAL_SERVER_ERROR, headers: { 'Content-Type': 'application/json' }, }); } catch (handlerError) { diff --git a/packages/event-handler/src/rest/constants.ts b/packages/event-handler/src/rest/constants.ts index ae9a80103f..5ec0377e6d 100644 --- a/packages/event-handler/src/rest/constants.ts +++ b/packages/event-handler/src/rest/constants.ts @@ -1,4 +1,4 @@ -export const HttpVerbs = { +const HttpVerbs = { GET: 'GET', POST: 'POST', PUT: 'PUT', @@ -8,7 +8,7 @@ export const HttpVerbs = { OPTIONS: 'OPTIONS', } as const; -export const HttpErrorCodes = { +const HttpStatusCodes = { // 1xx Informational CONTINUE: 100, SWITCHING_PROTOCOLS: 101, @@ -82,16 +82,16 @@ export const HttpErrorCodes = { NETWORK_AUTHENTICATION_REQUIRED: 511, } as const; -export const PARAM_PATTERN = /:([a-zA-Z_]\w*)(?=\/|$)/g; +const PARAM_PATTERN = /:([a-zA-Z_]\w*)(?=\/|$)/g; -export const SAFE_CHARS = "-._~()'!*:@,;=+&$"; +const SAFE_CHARS = "-._~()'!*:@,;=+&$"; -export const UNSAFE_CHARS = '%<> \\[\\]{}|^'; +const UNSAFE_CHARS = '%<> \\[\\]{}|^'; /** * Default CORS configuration */ -export const DEFAULT_CORS_OPTIONS = { +const DEFAULT_CORS_OPTIONS = { origin: '*', allowMethods: ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT'], allowHeaders: [ @@ -102,17 +102,28 @@ export const DEFAULT_CORS_OPTIONS = { 'X-Amz-Security-Token', ], exposeHeaders: [], - credentials: false + credentials: false, }; -export const DEFAULT_COMPRESSION_RESPONSE_THRESHOLD = 1024; +const DEFAULT_COMPRESSION_RESPONSE_THRESHOLD = 1024; -export const CACHE_CONTROL_NO_TRANSFORM_REGEX = - /(?:^|,)\s*?no-transform\s*?(?:,|$)/i; +const CACHE_CONTROL_NO_TRANSFORM_REGEX = /(?:^|,)\s*?no-transform\s*?(?:,|$)/i; -export const COMPRESSION_ENCODING_TYPES = { +const COMPRESSION_ENCODING_TYPES = { GZIP: 'gzip', DEFLATE: 'deflate', IDENTITY: 'identity', ANY: '*', } as const; + +export { + HttpVerbs, + HttpStatusCodes, + PARAM_PATTERN, + SAFE_CHARS, + UNSAFE_CHARS, + DEFAULT_CORS_OPTIONS, + DEFAULT_COMPRESSION_RESPONSE_THRESHOLD, + CACHE_CONTROL_NO_TRANSFORM_REGEX, + COMPRESSION_ENCODING_TYPES, +}; diff --git a/packages/event-handler/src/rest/converters.ts b/packages/event-handler/src/rest/converters.ts index 30948b3d9b..d47302ebf6 100644 --- a/packages/event-handler/src/rest/converters.ts +++ b/packages/event-handler/src/rest/converters.ts @@ -4,7 +4,7 @@ import type { HandlerResponse, HttpStatusCode, } from '../types/rest.js'; -import { COMPRESSION_ENCODING_TYPES, HttpErrorCodes } from './constants.js'; +import { COMPRESSION_ENCODING_TYPES, HttpStatusCodes } from './constants.js'; import { isAPIGatewayProxyResult } from './utils.js'; /** @@ -190,7 +190,7 @@ export const handlerResultToWebResponse = ( */ export const handlerResultToProxyResult = async ( response: HandlerResponse, - statusCode: HttpStatusCode = HttpErrorCodes.OK + statusCode: HttpStatusCode = HttpStatusCodes.OK ): Promise => { if (isAPIGatewayProxyResult(response)) { return response; diff --git a/packages/event-handler/src/rest/errors.ts b/packages/event-handler/src/rest/errors.ts index 80fa0cbc2a..ceef79a7e9 100644 --- a/packages/event-handler/src/rest/errors.ts +++ b/packages/event-handler/src/rest/errors.ts @@ -1,8 +1,8 @@ import type { JSONValue } from '@aws-lambda-powertools/commons/types'; import type { HandlerResponse, HttpStatusCode } from '../types/rest.js'; -import { HttpErrorCodes } from './constants.js'; +import { HttpStatusCodes } from './constants.js'; -export class RouteMatchingError extends Error { +class RouteMatchingError extends Error { constructor( message: string, public readonly path: string, @@ -13,14 +13,14 @@ export class RouteMatchingError extends Error { } } -export class ParameterValidationError extends RouteMatchingError { +class ParameterValidationError extends RouteMatchingError { constructor(public readonly issues: string[]) { super(`Parameter validation failed: ${issues.join(', ')}`, '', ''); this.name = 'ParameterValidationError'; } } -export abstract class ServiceError extends Error { +abstract class ServiceError extends Error { abstract readonly statusCode: HttpStatusCode; abstract readonly errorType: string; public readonly details?: Record; @@ -47,8 +47,8 @@ export abstract class ServiceError extends Error { } } -export class BadRequestError extends ServiceError { - readonly statusCode = HttpErrorCodes.BAD_REQUEST; +class BadRequestError extends ServiceError { + readonly statusCode = HttpStatusCodes.BAD_REQUEST; readonly errorType = 'BadRequestError'; constructor( @@ -57,11 +57,12 @@ export class BadRequestError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'BadRequestError'; } } -export class UnauthorizedError extends ServiceError { - readonly statusCode = HttpErrorCodes.UNAUTHORIZED; +class UnauthorizedError extends ServiceError { + readonly statusCode = HttpStatusCodes.UNAUTHORIZED; readonly errorType = 'UnauthorizedError'; constructor( @@ -70,11 +71,12 @@ export class UnauthorizedError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'UnauthorizedError'; } } -export class ForbiddenError extends ServiceError { - readonly statusCode = HttpErrorCodes.FORBIDDEN; +class ForbiddenError extends ServiceError { + readonly statusCode = HttpStatusCodes.FORBIDDEN; readonly errorType = 'ForbiddenError'; constructor( @@ -83,11 +85,12 @@ export class ForbiddenError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'ForbiddenError'; } } -export class NotFoundError extends ServiceError { - readonly statusCode = HttpErrorCodes.NOT_FOUND; +class NotFoundError extends ServiceError { + readonly statusCode = HttpStatusCodes.NOT_FOUND; readonly errorType = 'NotFoundError'; constructor( @@ -96,11 +99,12 @@ export class NotFoundError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'NotFoundError'; } } -export class MethodNotAllowedError extends ServiceError { - readonly statusCode = HttpErrorCodes.METHOD_NOT_ALLOWED; +class MethodNotAllowedError extends ServiceError { + readonly statusCode = HttpStatusCodes.METHOD_NOT_ALLOWED; readonly errorType = 'MethodNotAllowedError'; constructor( @@ -109,11 +113,12 @@ export class MethodNotAllowedError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'MethodNotAllowedError'; } } -export class RequestTimeoutError extends ServiceError { - readonly statusCode = HttpErrorCodes.REQUEST_TIMEOUT; +class RequestTimeoutError extends ServiceError { + readonly statusCode = HttpStatusCodes.REQUEST_TIMEOUT; readonly errorType = 'RequestTimeoutError'; constructor( @@ -122,11 +127,12 @@ export class RequestTimeoutError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'RequestTimeoutError'; } } -export class RequestEntityTooLargeError extends ServiceError { - readonly statusCode = HttpErrorCodes.REQUEST_ENTITY_TOO_LARGE; +class RequestEntityTooLargeError extends ServiceError { + readonly statusCode = HttpStatusCodes.REQUEST_ENTITY_TOO_LARGE; readonly errorType = 'RequestEntityTooLargeError'; constructor( @@ -135,11 +141,12 @@ export class RequestEntityTooLargeError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'RequestEntityTooLargeError'; } } -export class InternalServerError extends ServiceError { - readonly statusCode = HttpErrorCodes.INTERNAL_SERVER_ERROR; +class InternalServerError extends ServiceError { + readonly statusCode = HttpStatusCodes.INTERNAL_SERVER_ERROR; readonly errorType = 'InternalServerError'; constructor( @@ -148,11 +155,12 @@ export class InternalServerError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'InternalServerError'; } } -export class ServiceUnavailableError extends ServiceError { - readonly statusCode = HttpErrorCodes.SERVICE_UNAVAILABLE; +class ServiceUnavailableError extends ServiceError { + readonly statusCode = HttpStatusCodes.SERVICE_UNAVAILABLE; readonly errorType = 'ServiceUnavailableError'; constructor( @@ -161,5 +169,21 @@ export class ServiceUnavailableError extends ServiceError { details?: Record ) { super(message, options, details); + this.name = 'ServiceUnavailableError'; } } + +export { + BadRequestError, + ForbiddenError, + InternalServerError, + MethodNotAllowedError, + NotFoundError, + ParameterValidationError, + RequestEntityTooLargeError, + RequestTimeoutError, + RouteMatchingError, + ServiceError, + ServiceUnavailableError, + UnauthorizedError, +}; diff --git a/packages/event-handler/src/rest/index.ts b/packages/event-handler/src/rest/index.ts index 06efe93224..2a4d605ea4 100644 --- a/packages/event-handler/src/rest/index.ts +++ b/packages/event-handler/src/rest/index.ts @@ -1,4 +1,4 @@ -export { HttpErrorCodes, HttpVerbs } from './constants.js'; +export { HttpStatusCodes, HttpVerbs } from './constants.js'; export { handlerResultToProxyResult, handlerResultToWebResponse, diff --git a/packages/event-handler/src/rest/middleware/cors.ts b/packages/event-handler/src/rest/middleware/cors.ts index a1ac697bfb..25c780e39b 100644 --- a/packages/event-handler/src/rest/middleware/cors.ts +++ b/packages/event-handler/src/rest/middleware/cors.ts @@ -1,7 +1,7 @@ import type { CorsOptions, Middleware } from '../../types/rest.js'; import { DEFAULT_CORS_OPTIONS, - HttpErrorCodes, + HttpStatusCodes, HttpVerbs, } from '../constants.js'; @@ -123,7 +123,7 @@ export const cors = (options?: CorsOptions): Middleware => { reqCtx.res.headers.append('access-control-allow-headers', header); } return new Response(null, { - status: HttpErrorCodes.NO_CONTENT, + status: HttpStatusCodes.NO_CONTENT, headers: reqCtx.res.headers, }); } diff --git a/packages/event-handler/src/types/rest.ts b/packages/event-handler/src/types/rest.ts index 188d3ff29a..1c9925ce22 100644 --- a/packages/event-handler/src/types/rest.ts +++ b/packages/event-handler/src/types/rest.ts @@ -3,7 +3,7 @@ import type { JSONObject, } from '@aws-lambda-powertools/commons/types'; import type { APIGatewayProxyEvent, Context } from 'aws-lambda'; -import type { HttpErrorCodes, HttpVerbs } from '../rest/constants.js'; +import type { HttpStatusCodes, HttpVerbs } from '../rest/constants.js'; import type { Route } from '../rest/Route.js'; import type { Router } from '../rest/Router.js'; import type { ResolveOptions } from './common.js'; @@ -61,7 +61,7 @@ type RouteHandler = ( type HttpMethod = keyof typeof HttpVerbs; -type HttpStatusCode = (typeof HttpErrorCodes)[keyof typeof HttpErrorCodes]; +type HttpStatusCode = (typeof HttpStatusCodes)[keyof typeof HttpStatusCodes]; type Path = `/${string}`; diff --git a/packages/event-handler/tests/unit/rest/ErrorHandlerRegistry.test.ts b/packages/event-handler/tests/unit/rest/ErrorHandlerRegistry.test.ts index 1dbef04f6a..7b0fc9a857 100644 --- a/packages/event-handler/tests/unit/rest/ErrorHandlerRegistry.test.ts +++ b/packages/event-handler/tests/unit/rest/ErrorHandlerRegistry.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; import { ErrorHandlerRegistry } from '../../../src/rest/ErrorHandlerRegistry.js'; -import { HttpErrorCodes } from '../../../src/rest/index.js'; +import { HttpStatusCodes } from '../../../src/rest/index.js'; import type { HttpStatusCode, RequestContext, @@ -39,8 +39,8 @@ describe('Class: ErrorHandlerRegistry', () => { it('logs a warning when registering a duplicate error handler', () => { // Prepare const registry = new ErrorHandlerRegistry({ logger: console }); - const handler1 = createErrorHandler(HttpErrorCodes.BAD_REQUEST, 'first'); - const handler2 = createErrorHandler(HttpErrorCodes.NOT_FOUND, 'second'); + const handler1 = createErrorHandler(HttpStatusCodes.BAD_REQUEST, 'first'); + const handler2 = createErrorHandler(HttpStatusCodes.NOT_FOUND, 'second'); // Act registry.register(CustomError, handler1); @@ -58,7 +58,7 @@ describe('Class: ErrorHandlerRegistry', () => { it('registers handlers for multiple error types', () => { // Prepare const registry = new ErrorHandlerRegistry({ logger: console }); - const handler = createErrorHandler(HttpErrorCodes.BAD_REQUEST); + const handler = createErrorHandler(HttpStatusCodes.BAD_REQUEST); // Act registry.register([CustomError, AnotherError], handler); @@ -71,9 +71,9 @@ describe('Class: ErrorHandlerRegistry', () => { it('resolves handlers using exact constructor match', () => { // Prepare const registry = new ErrorHandlerRegistry({ logger: console }); - const customHandler = createErrorHandler(HttpErrorCodes.BAD_REQUEST); + const customHandler = createErrorHandler(HttpStatusCodes.BAD_REQUEST); const anotherHandler = createErrorHandler( - HttpErrorCodes.INTERNAL_SERVER_ERROR + HttpStatusCodes.INTERNAL_SERVER_ERROR ); // Act @@ -88,7 +88,7 @@ describe('Class: ErrorHandlerRegistry', () => { it('resolves handlers using instanceof for inheritance', () => { // Prepare const registry = new ErrorHandlerRegistry({ logger: console }); - const baseHandler = createErrorHandler(HttpErrorCodes.BAD_REQUEST); + const baseHandler = createErrorHandler(HttpStatusCodes.BAD_REQUEST); // Act registry.register(CustomError, baseHandler); @@ -101,7 +101,7 @@ describe('Class: ErrorHandlerRegistry', () => { it('resolves handlers using name-based matching', () => { // Prepare const registry = new ErrorHandlerRegistry({ logger: console }); - const handler = createErrorHandler(HttpErrorCodes.BAD_REQUEST); + const handler = createErrorHandler(HttpStatusCodes.BAD_REQUEST); // Act registry.register(CustomError, handler); @@ -116,7 +116,7 @@ describe('Class: ErrorHandlerRegistry', () => { it('returns null when no handler is found', () => { // Prepare const registry = new ErrorHandlerRegistry({ logger: console }); - const handler = createErrorHandler(HttpErrorCodes.BAD_REQUEST); + const handler = createErrorHandler(HttpStatusCodes.BAD_REQUEST); // Act registry.register(CustomError, handler); @@ -129,9 +129,9 @@ describe('Class: ErrorHandlerRegistry', () => { it('prioritizes exact constructor match over instanceof', () => { // Prepare const registry = new ErrorHandlerRegistry({ logger: console }); - const baseHandler = createErrorHandler(HttpErrorCodes.BAD_REQUEST); + const baseHandler = createErrorHandler(HttpStatusCodes.BAD_REQUEST); const specificHandler = createErrorHandler( - HttpErrorCodes.INTERNAL_SERVER_ERROR + HttpStatusCodes.INTERNAL_SERVER_ERROR ); // Act @@ -145,9 +145,9 @@ describe('Class: ErrorHandlerRegistry', () => { it('prioritizes instanceof match over name-based matching', () => { // Prepare const registry = new ErrorHandlerRegistry({ logger: console }); - const baseHandler = createErrorHandler(HttpErrorCodes.BAD_REQUEST); + const baseHandler = createErrorHandler(HttpStatusCodes.BAD_REQUEST); const nameHandler = createErrorHandler( - HttpErrorCodes.INTERNAL_SERVER_ERROR + HttpStatusCodes.INTERNAL_SERVER_ERROR ); // Create a class with different name but register with name matching diff --git a/packages/event-handler/tests/unit/rest/RouteHandlerRegistry.test.ts b/packages/event-handler/tests/unit/rest/RouteHandlerRegistry.test.ts index 24dac6f6f9..42dccf5f24 100644 --- a/packages/event-handler/tests/unit/rest/RouteHandlerRegistry.test.ts +++ b/packages/event-handler/tests/unit/rest/RouteHandlerRegistry.test.ts @@ -559,11 +559,9 @@ describe('Class: RouteHandlerRegistry', () => { // Prepare const registry = new RouteHandlerRegistry({ logger: console }); const handler = async () => ({ message: 'test' }); - - // Act registry.register(new Route(HttpVerbs.GET, '/users/:id', handler)); - // Assess + // Act & Assess expect(() => { registry.resolve(HttpVerbs.GET, '/users/%20'); }).toThrow("Parameter 'id' cannot be empty"); @@ -573,40 +571,19 @@ describe('Class: RouteHandlerRegistry', () => { // Prepare const registry = new RouteHandlerRegistry({ logger: console }); const handler = async () => ({ message: 'test' }); - - // Act - registry.register( - new Route(HttpVerbs.GET, '/users/:userId/posts/:postId', handler) - ); - - // Assess - expect(() => { - registry.resolve(HttpVerbs.GET, '/users/%20/posts/%20%20'); - }).toThrow('Parameter validation failed'); - }); - - it('includes all validation issues in error message', () => { - // Prepare - const registry = new RouteHandlerRegistry({ logger: console }); - const handler = async () => ({ message: 'test' }); - - // Act registry.register( new Route(HttpVerbs.GET, '/api/:version/:resource/:id', handler) ); - // Assess - expect(() => { - registry.resolve(HttpVerbs.GET, '/api/%20/users/%20'); - }).toThrow(); - - try { + // Act & Assess + expect(async () => { registry.resolve(HttpVerbs.GET, '/api/%20/users/%20'); - } catch (error: any) { - expect(error.message).toContain('Parameter validation failed'); - expect(error.issues).toContain("Parameter 'version' cannot be empty"); - expect(error.issues).toContain("Parameter 'id' cannot be empty"); - } + }).rejects.toMatchObject({ + issues: [ + "Parameter 'version' cannot be empty", + "Parameter 'id' cannot be empty", + ], + }); }); }); }); 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 fa58f23c87..d4dffadb44 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 @@ -1,7 +1,7 @@ import context from '@aws-lambda-powertools/testing-utils/context'; import { describe, expect, it } from 'vitest'; import { - HttpErrorCodes, + HttpStatusCodes, HttpVerbs, InternalServerError, Router, @@ -50,7 +50,7 @@ describe('Class: Router - Basic Routing', () => { context ); - expect(result.statusCode).toBe(HttpErrorCodes.METHOD_NOT_ALLOWED); + expect(result.statusCode).toBe(HttpStatusCodes.METHOD_NOT_ALLOWED); expect(result.body).toEqual(''); } ); 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 4b6be75101..0528e7a963 100644 --- a/packages/event-handler/tests/unit/rest/Router/decorators.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/decorators.test.ts @@ -3,11 +3,12 @@ import type { Context } from 'aws-lambda'; import { describe, expect, it } from 'vitest'; import { BadRequestError, - HttpErrorCodes, + HttpStatusCodes, MethodNotAllowedError, type NotFoundError, Router, } from '../../../../src/rest/index.js'; +import type { RequestContext } from '../../../../src/types/rest.js'; import { createTestEvent, createTrackingMiddleware } from '../helpers.js'; describe('Class: Router - Decorators', () => { @@ -219,7 +220,7 @@ describe('Class: Router - Decorators', () => { @app.errorHandler(BadRequestError) public async handleBadRequest(error: BadRequestError) { return { - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: `Decorated: ${error.message}`, }; @@ -245,9 +246,9 @@ describe('Class: Router - Decorators', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, body: JSON.stringify({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: 'Decorated: test error', }), @@ -266,7 +267,7 @@ describe('Class: Router - Decorators', () => { @app.notFound() public async handleNotFound(error: NotFoundError) { return { - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, error: 'Not Found', message: `${this.scope}: ${error.message}`, }; @@ -288,9 +289,9 @@ describe('Class: Router - Decorators', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, body: JSON.stringify({ - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, error: 'Not Found', message: 'scoped: Route /nonexistent for method GET not found', }), @@ -307,7 +308,7 @@ describe('Class: Router - Decorators', () => { @app.methodNotAllowed() public async handleMethodNotAllowed(error: MethodNotAllowedError) { return { - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, error: 'Method Not Allowed', message: `Decorated: ${error.message}`, }; @@ -333,9 +334,9 @@ describe('Class: Router - Decorators', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, body: JSON.stringify({ - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, error: 'Method Not Allowed', message: 'Decorated: POST not allowed', }), @@ -354,7 +355,7 @@ describe('Class: Router - Decorators', () => { @app.errorHandler(BadRequestError) public async handleBadRequest(error: BadRequestError) { return { - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: `${this.scope}: ${error.message}`, }; @@ -378,9 +379,9 @@ describe('Class: Router - Decorators', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, body: JSON.stringify({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: 'scoped: test error', }), @@ -398,7 +399,7 @@ describe('Class: Router - Decorators', () => { class Lambda { @app.get('/test') - public async getTest(reqCtx: any) { + public async getTest(reqCtx: RequestContext) { return { hasRequest: reqCtx.req instanceof Request, hasEvent: reqCtx.event === testEvent, @@ -430,9 +431,12 @@ describe('Class: Router - Decorators', () => { class Lambda { @app.errorHandler(BadRequestError) - public async handleBadRequest(error: BadRequestError, reqCtx: any) { + public async handleBadRequest( + error: BadRequestError, + reqCtx: RequestContext + ) { return { - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: error.message, hasRequest: reqCtx.req instanceof Request, 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 9795117dc1..f3921aa42b 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 @@ -2,7 +2,7 @@ import context from '@aws-lambda-powertools/testing-utils/context'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { BadRequestError, - HttpErrorCodes, + HttpStatusCodes, InternalServerError, MethodNotAllowedError, NotFoundError, @@ -20,7 +20,7 @@ describe('Class: Router - Error Handling', () => { vi.stubEnv('POWERTOOLS_DEV', 'true'); app.errorHandler(BadRequestError, async (error) => ({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: `Handled: ${error.message}`, })); @@ -34,9 +34,9 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, body: JSON.stringify({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: 'Handled: test error', }), @@ -62,11 +62,11 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, body: JSON.stringify({ error: 'Not Found', message: 'Custom: Route /nonexistent for method GET not found', - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, }), headers: { 'content-type': 'application/json' }, isBase64Encoded: false, @@ -91,11 +91,11 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, body: JSON.stringify({ error: 'Method Not Allowed', message: 'Custom: POST not allowed', - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, }), headers: { 'content-type': 'application/json' }, isBase64Encoded: false, @@ -119,9 +119,9 @@ describe('Class: Router - Error Handling', () => { const result = await app.resolve(createTestEvent('/test', 'GET'), context); // Assess - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); const body = JSON.parse(result.body); - expect(body.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(body.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); expect(body.error).toBe('Internal Server Error'); expect(body.message).toBe('Internal Server Error'); }); @@ -139,9 +139,9 @@ describe('Class: Router - Error Handling', () => { const result = await app.resolve(createTestEvent('/test', 'GET'), context); // Assess - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); const body = JSON.parse(result.body); - expect(body.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(body.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); expect(body.error).toBe('Internal Server Error'); expect(body.message).toBe('Internal Server Error'); }); @@ -151,13 +151,13 @@ describe('Class: Router - Error Handling', () => { const app = new Router(); app.errorHandler(Error, async () => ({ - statusCode: HttpErrorCodes.INTERNAL_SERVER_ERROR, + statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR, error: 'Generic Error', message: 'Generic handler', })); app.errorHandler(BadRequestError, async () => ({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: 'Specific handler', })); @@ -171,9 +171,9 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, body: JSON.stringify({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: 'Specific handler', }), @@ -195,9 +195,9 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.INTERNAL_SERVER_ERROR, + statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR, body: JSON.stringify({ - statusCode: HttpErrorCodes.INTERNAL_SERVER_ERROR, + statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR, error: 'InternalServerError', message: 'service error', }), @@ -219,9 +219,9 @@ describe('Class: Router - Error Handling', () => { const result = await app.resolve(createTestEvent('/test', 'GET'), context); // Assess - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); const body = JSON.parse(result.body); - expect(body.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(body.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); expect(body.error).toBe('Internal Server Error'); expect(body.message).toBe('Internal Server Error'); expect(body.stack).toBeUndefined(); @@ -241,9 +241,9 @@ describe('Class: Router - Error Handling', () => { const result = await app.resolve(createTestEvent('/test', 'GET'), context); // Assess - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); const body = JSON.parse(result.body); - expect(body.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(body.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); expect(body.error).toBe('Internal Server Error'); expect(body.message).toBe('debug error details'); expect(body.stack).toBeDefined(); @@ -258,7 +258,7 @@ describe('Class: Router - Error Handling', () => { app.errorHandler( [BadRequestError, MethodNotAllowedError], async (error: Error) => ({ - statusCode: HttpErrorCodes.UNPROCESSABLE_ENTITY, + statusCode: HttpStatusCodes.UNPROCESSABLE_ENTITY, error: 'Validation Error', message: `Array handler: ${error.message}`, }) @@ -284,9 +284,9 @@ describe('Class: Router - Error Handling', () => { // Assess const expectedBadResult = { - statusCode: HttpErrorCodes.UNPROCESSABLE_ENTITY, + statusCode: HttpStatusCodes.UNPROCESSABLE_ENTITY, body: JSON.stringify({ - statusCode: HttpErrorCodes.UNPROCESSABLE_ENTITY, + statusCode: HttpStatusCodes.UNPROCESSABLE_ENTITY, error: 'Validation Error', message: 'Array handler: bad request', }), @@ -294,9 +294,9 @@ describe('Class: Router - Error Handling', () => { isBase64Encoded: false, }; const expectedMethodResult = { - statusCode: HttpErrorCodes.UNPROCESSABLE_ENTITY, + statusCode: HttpStatusCodes.UNPROCESSABLE_ENTITY, body: JSON.stringify({ - statusCode: HttpErrorCodes.UNPROCESSABLE_ENTITY, + statusCode: HttpStatusCodes.UNPROCESSABLE_ENTITY, error: 'Validation Error', message: 'Array handler: method not allowed', }), @@ -313,13 +313,13 @@ describe('Class: Router - Error Handling', () => { const app = new Router(); app.errorHandler(BadRequestError, async () => ({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'First Handler', message: 'first', })); app.errorHandler(BadRequestError, async (error) => ({ - statusCode: HttpErrorCodes.UNPROCESSABLE_ENTITY, + statusCode: HttpStatusCodes.UNPROCESSABLE_ENTITY, error: 'Second Handler', message: `second: ${error.message}`, })); @@ -333,9 +333,9 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.UNPROCESSABLE_ENTITY, + statusCode: HttpStatusCodes.UNPROCESSABLE_ENTITY, body: JSON.stringify({ - statusCode: HttpErrorCodes.UNPROCESSABLE_ENTITY, + statusCode: HttpStatusCodes.UNPROCESSABLE_ENTITY, error: 'Second Handler', message: 'second: test error', }), @@ -349,7 +349,7 @@ describe('Class: Router - Error Handling', () => { const app = new Router(); app.errorHandler(BadRequestError, async (error) => ({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: error.message, })); @@ -371,7 +371,7 @@ describe('Class: Router - Error Handling', () => { const testEvent = createTestEvent('/test', 'GET'); app.errorHandler(BadRequestError, async (error, reqCtx) => ({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'Bad Request', message: error.message, hasRequest: reqCtx.req instanceof Request, @@ -405,7 +405,7 @@ describe('Class: Router - Error Handling', () => { foo: 'bar', }), { - status: HttpErrorCodes.BAD_REQUEST, + status: HttpStatusCodes.BAD_REQUEST, headers: { 'content-type': 'application/json', }, @@ -422,7 +422,7 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, body: JSON.stringify({ foo: 'bar', }), @@ -436,7 +436,7 @@ describe('Class: Router - Error Handling', () => { const app = new Router(); app.errorHandler(BadRequestError, async () => ({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, body: JSON.stringify({ foo: 'bar', }), @@ -451,7 +451,7 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, body: JSON.stringify({ foo: 'bar', }), @@ -473,7 +473,7 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.INTERNAL_SERVER_ERROR, + statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR, body: JSON.stringify({ foo: 'bar', }), @@ -499,9 +499,9 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, body: JSON.stringify({ - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, error: 'NotFoundError', message: 'This error is thrown from the error handler', }), @@ -529,9 +529,9 @@ describe('Class: Router - Error Handling', () => { // Assess expect(result).toEqual({ - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, body: JSON.stringify({ - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, error: 'MethodNotAllowedError', message: 'This error is thrown from the error handler', }), @@ -557,7 +557,7 @@ describe('Class: Router - Error Handling', () => { const result = await app.resolve(createTestEvent('/test', 'GET'), context); // Assess - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); const body = JSON.parse(result.body); expect(body.error).toBe('Internal Server Error'); expect(body.message).toBe('This error is thrown from the error handler'); 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 a5080eb654..4d66055914 100644 --- a/packages/event-handler/tests/unit/rest/Router/middleware.test.ts +++ b/packages/event-handler/tests/unit/rest/Router/middleware.test.ts @@ -1,7 +1,7 @@ import context from '@aws-lambda-powertools/testing-utils/context'; import type { Context } from 'aws-lambda'; import { describe, expect, it, vi } from 'vitest'; -import { HttpErrorCodes, Router } from '../../../../src/rest/index.js'; +import { HttpStatusCodes, Router } from '../../../../src/rest/index.js'; import type { Middleware, Path, @@ -176,7 +176,7 @@ describe('Class: Router - Middleware', () => { ); // Assess - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); const body = JSON.parse(result.body); expect(body.message).toContain('next() called multiple times'); }); @@ -234,7 +234,7 @@ describe('Class: Router - Middleware', () => { // Assess expect(executionOrder).toEqual(['middleware1']); - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); }); it('handles errors thrown in middleware after next()', async () => { @@ -266,7 +266,7 @@ describe('Class: Router - Middleware', () => { 'handler', 'middleware1-end', ]); - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); }); it('propagates handler errors through middleware chain', async () => { @@ -294,7 +294,7 @@ describe('Class: Router - Middleware', () => { 'middleware2-start', 'handler', ]); - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); }); it('handles middleware not calling next()', async () => { @@ -318,7 +318,7 @@ describe('Class: Router - Middleware', () => { // Assess expect(executionOrder).toEqual(['middleware1']); - expect(result.statusCode).toBe(HttpErrorCodes.INTERNAL_SERVER_ERROR); + expect(result.statusCode).toBe(HttpStatusCodes.INTERNAL_SERVER_ERROR); }); it('handles middleware returning JSON objects', async () => { diff --git a/packages/event-handler/tests/unit/rest/errors.test.ts b/packages/event-handler/tests/unit/rest/errors.test.ts index 6f26cf678c..95db647802 100644 --- a/packages/event-handler/tests/unit/rest/errors.test.ts +++ b/packages/event-handler/tests/unit/rest/errors.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'; import { BadRequestError, ForbiddenError, - HttpErrorCodes, + HttpStatusCodes, InternalServerError, MethodNotAllowedError, NotFoundError, @@ -17,55 +17,55 @@ describe('HTTP Error Classes', () => { { ErrorClass: BadRequestError, errorType: 'BadRequestError', - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, customMessage: 'Invalid input', }, { ErrorClass: UnauthorizedError, errorType: 'UnauthorizedError', - statusCode: HttpErrorCodes.UNAUTHORIZED, + statusCode: HttpStatusCodes.UNAUTHORIZED, customMessage: 'Token expired', }, { ErrorClass: ForbiddenError, errorType: 'ForbiddenError', - statusCode: HttpErrorCodes.FORBIDDEN, + statusCode: HttpStatusCodes.FORBIDDEN, customMessage: 'Access denied', }, { ErrorClass: NotFoundError, errorType: 'NotFoundError', - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, customMessage: 'Resource not found', }, { ErrorClass: MethodNotAllowedError, errorType: 'MethodNotAllowedError', - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, customMessage: 'POST not allowed', }, { ErrorClass: RequestTimeoutError, errorType: 'RequestTimeoutError', - statusCode: HttpErrorCodes.REQUEST_TIMEOUT, + statusCode: HttpStatusCodes.REQUEST_TIMEOUT, customMessage: 'Operation timed out', }, { ErrorClass: RequestEntityTooLargeError, errorType: 'RequestEntityTooLargeError', - statusCode: HttpErrorCodes.REQUEST_ENTITY_TOO_LARGE, + statusCode: HttpStatusCodes.REQUEST_ENTITY_TOO_LARGE, customMessage: 'File too large', }, { ErrorClass: InternalServerError, errorType: 'InternalServerError', - statusCode: HttpErrorCodes.INTERNAL_SERVER_ERROR, + statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR, customMessage: 'Database connection failed', }, { ErrorClass: ServiceUnavailableError, errorType: 'ServiceUnavailableError', - statusCode: HttpErrorCodes.SERVICE_UNAVAILABLE, + statusCode: HttpStatusCodes.SERVICE_UNAVAILABLE, customMessage: 'Maintenance mode', }, ])( @@ -83,55 +83,55 @@ describe('HTTP Error Classes', () => { { ErrorClass: BadRequestError, errorType: 'BadRequestError', - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, message: 'Invalid input', }, { ErrorClass: UnauthorizedError, errorType: 'UnauthorizedError', - statusCode: HttpErrorCodes.UNAUTHORIZED, + statusCode: HttpStatusCodes.UNAUTHORIZED, message: 'Token expired', }, { ErrorClass: ForbiddenError, errorType: 'ForbiddenError', - statusCode: HttpErrorCodes.FORBIDDEN, + statusCode: HttpStatusCodes.FORBIDDEN, message: 'Access denied', }, { ErrorClass: NotFoundError, errorType: 'NotFoundError', - statusCode: HttpErrorCodes.NOT_FOUND, + statusCode: HttpStatusCodes.NOT_FOUND, message: 'Resource not found', }, { ErrorClass: MethodNotAllowedError, errorType: 'MethodNotAllowedError', - statusCode: HttpErrorCodes.METHOD_NOT_ALLOWED, + statusCode: HttpStatusCodes.METHOD_NOT_ALLOWED, message: 'POST not allowed', }, { ErrorClass: RequestTimeoutError, errorType: 'RequestTimeoutError', - statusCode: HttpErrorCodes.REQUEST_TIMEOUT, + statusCode: HttpStatusCodes.REQUEST_TIMEOUT, message: 'Operation timed out', }, { ErrorClass: RequestEntityTooLargeError, errorType: 'RequestEntityTooLargeError', - statusCode: HttpErrorCodes.REQUEST_ENTITY_TOO_LARGE, + statusCode: HttpStatusCodes.REQUEST_ENTITY_TOO_LARGE, message: 'File too large', }, { ErrorClass: InternalServerError, errorType: 'InternalServerError', - statusCode: HttpErrorCodes.INTERNAL_SERVER_ERROR, + statusCode: HttpStatusCodes.INTERNAL_SERVER_ERROR, message: 'Database connection failed', }, { ErrorClass: ServiceUnavailableError, errorType: 'ServiceUnavailableError', - statusCode: HttpErrorCodes.SERVICE_UNAVAILABLE, + statusCode: HttpStatusCodes.SERVICE_UNAVAILABLE, message: 'Maintenance mode', }, ])( @@ -154,7 +154,7 @@ describe('HTTP Error Classes', () => { const json = error.toJSON(); expect(json).toEqual({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'BadRequestError', message: 'Invalid input', details, @@ -166,7 +166,7 @@ describe('HTTP Error Classes', () => { const json = error.toJSON(); expect(json).toEqual({ - statusCode: HttpErrorCodes.BAD_REQUEST, + statusCode: HttpStatusCodes.BAD_REQUEST, error: 'BadRequestError', message: 'Invalid input', }); diff --git a/packages/event-handler/tests/unit/rest/helpers.ts b/packages/event-handler/tests/unit/rest/helpers.ts index 960fe2c437..4f04e0e3c1 100644 --- a/packages/event-handler/tests/unit/rest/helpers.ts +++ b/packages/event-handler/tests/unit/rest/helpers.ts @@ -1,5 +1,5 @@ import type { APIGatewayProxyEvent } from 'aws-lambda'; -import type { Middleware } from '../../../src/types/rest.js'; +import type { HandlerResponse, Middleware } from '../../../src/types/rest.js'; export const createTestEvent = ( path: string, @@ -20,7 +20,7 @@ export const createTestEvent = ( httpMethod, path, domainName: 'localhost', - } as any, + } as APIGatewayProxyEvent['requestContext'], resource: '', }); @@ -49,7 +49,7 @@ export const createThrowingMiddleware = ( export const createReturningMiddleware = ( name: string, executionOrder: string[], - response: any + response: HandlerResponse ): Middleware => { return async () => { executionOrder.push(name); diff --git a/packages/event-handler/tests/unit/rest/utils.test.ts b/packages/event-handler/tests/unit/rest/utils.test.ts index db8308cd63..5082eb6608 100644 --- a/packages/event-handler/tests/unit/rest/utils.test.ts +++ b/packages/event-handler/tests/unit/rest/utils.test.ts @@ -1,4 +1,8 @@ -import type { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda'; +import type { + APIGatewayProxyEvent, + APIGatewayProxyResult, + Context, +} from 'aws-lambda'; import { describe, expect, it } from 'vitest'; import { composeMiddleware, @@ -440,9 +444,10 @@ describe('Path Utilities', () => { describe('composeMiddleware', () => { const mockOptions: RequestContext = { + params: {}, event: {} as APIGatewayProxyEvent, - context: {} as any, - request: new Request('https://example.com'), + context: {} as Context, + req: new Request('https://example.com'), res: new Response(), }; @@ -463,7 +468,6 @@ describe('Path Utilities', () => { const composed = composeMiddleware(middleware); await composed({ - params: {}, reqCtx: mockOptions, next: async () => { executionOrder.push('handler'); @@ -491,7 +495,6 @@ describe('Path Utilities', () => { const composed = composeMiddleware(middleware); const result = await composed({ - params: {}, reqCtx: mockOptions, next: async () => { return { handler: true }; @@ -510,7 +513,6 @@ describe('Path Utilities', () => { const composed = composeMiddleware(middleware); const result = await composed({ - params: {}, reqCtx: mockOptions, next: async () => { return { handler: true }; @@ -531,14 +533,13 @@ describe('Path Utilities', () => { const composed = composeMiddleware(middleware); await expect( - composed({ params: {}, reqCtx: mockOptions, next: async () => {} }) + composed({ reqCtx: mockOptions, next: async () => {} }) ).rejects.toThrow('next() called multiple times'); }); it('handles empty middleware array', async () => { const composed = composeMiddleware([]); const result = await composed({ - params: {}, reqCtx: mockOptions, next: async () => { return { handler: true }; @@ -557,7 +558,6 @@ describe('Path Utilities', () => { const composed = composeMiddleware(middleware); const result = await composed({ - params: {}, reqCtx: mockOptions, next: async () => { return undefined;