Skip to content

Commit 9ec4b6f

Browse files
authored
Merge branch 'main' into docs/remove-dataKeywordArgument
2 parents 92838d6 + f08b366 commit 9ec4b6f

File tree

9 files changed

+223
-26
lines changed

9 files changed

+223
-26
lines changed

.github/workflows/make-release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ jobs:
5252
with:
5353
node-version: "22"
5454
cache: "npm"
55+
registry-url: 'https://registry.npmjs.org'
5556
- name: Setup auth tokens
5657
env:
5758
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

.github/workflows/publish-package.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
with:
4444
node-version: "22"
4545
cache: "npm"
46+
registry-url: 'https://registry.npmjs.org'
4647
- name: Setup auth tokens
4748
env:
4849
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
![GitHub Release](https://img.shields.io/github/v/release/aws-powertools/powertools-lambda-typescript?style=flat)
66
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=aws-powertools_powertools-lambda-typescript&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=aws-powertools_powertools-lambda-typescript)
77
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=aws-powertools_powertools-lambda-typescript&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=aws-powertools_powertools-lambda-typescript)
8-
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/aws-powertools/powertools-lambda-typescript/badge)](https://api.securityscorecards.dev/projects/github.com/aws-powertools/powertools-lambda-typescript)
8+
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/aws-powertools/powertools-lambda-typescript/badge)](https://scorecard.dev/viewer/?uri=github.com/aws-powertools/powertools-lambda-typescript)
9+
910
[![Discord](https://img.shields.io/badge/Discord-Join_Community-7289da.svg)](https://discord.gg/B8zZKbbyET)
1011

1112
Powertools for AWS Lambda (TypeScript) is a developer toolkit to implement Serverless [best practices and increase developer velocity](https://docs.powertools.aws.dev/lambda/typescript/latest/#features).

packages/event-handler/src/rest/Router.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import {
44
isDevMode,
55
} from '@aws-lambda-powertools/commons/utils/env';
66
import type { APIGatewayProxyResult, Context } from 'aws-lambda';
7-
import type { ResolveOptions } from '../types/index.js';
7+
import type {
8+
HandlerResponse,
9+
HttpStatusCode,
10+
ResolveOptions,
11+
} from '../types/index.js';
812
import type {
913
ErrorConstructor,
1014
ErrorHandler,
@@ -22,7 +26,6 @@ import {
2226
handlerResultToProxyResult,
2327
handlerResultToWebResponse,
2428
proxyEventToWebRequest,
25-
webResponseToProxyResult,
2629
} from './converters.js';
2730
import { ErrorHandlerRegistry } from './ErrorHandlerRegistry.js';
2831
import {
@@ -36,6 +39,7 @@ import { RouteHandlerRegistry } from './RouteHandlerRegistry.js';
3639
import {
3740
composeMiddleware,
3841
isAPIGatewayProxyEvent,
42+
isAPIGatewayProxyResult,
3943
isHttpMethod,
4044
} from './utils.js';
4145

@@ -280,7 +284,9 @@ class Router {
280284
...requestContext,
281285
scope: options?.scope,
282286
});
283-
return await webResponseToProxyResult(result);
287+
const statusCode =
288+
result instanceof Response ? result.status : result.statusCode;
289+
return handlerResultToProxyResult(result, statusCode as HttpStatusCode);
284290
}
285291
}
286292

@@ -310,17 +316,31 @@ class Router {
310316
protected async handleError(
311317
error: Error,
312318
options: ErrorResolveOptions
313-
): Promise<Response> {
319+
): Promise<HandlerResponse> {
314320
const handler = this.errorHandlerRegistry.resolve(error);
315321
if (handler !== null) {
316322
try {
317323
const { scope, ...reqCtx } = options;
318324
const body = await handler.apply(scope ?? this, [error, reqCtx]);
325+
if (body instanceof Response || isAPIGatewayProxyResult(body)) {
326+
return body;
327+
}
328+
if (!body.statusCode) {
329+
if (error instanceof NotFoundError) {
330+
body.statusCode = HttpErrorCodes.NOT_FOUND;
331+
} else if (error instanceof MethodNotAllowedError) {
332+
body.statusCode = HttpErrorCodes.METHOD_NOT_ALLOWED;
333+
}
334+
}
319335
return new Response(JSON.stringify(body), {
320-
status: body.statusCode,
336+
status:
337+
(body.statusCode as number) ?? HttpErrorCodes.INTERNAL_SERVER_ERROR,
321338
headers: { 'Content-Type': 'application/json' },
322339
});
323340
} catch (handlerError) {
341+
if (handlerError instanceof ServiceError) {
342+
return await this.handleError(handlerError, options);
343+
}
324344
return this.#defaultErrorHandler(handlerError as Error);
325345
}
326346
}

packages/event-handler/src/rest/converters.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import type { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
2-
import type { CompressionOptions, HandlerResponse } from '../types/rest.js';
3-
import { COMPRESSION_ENCODING_TYPES } from './constants.js';
2+
import type {
3+
CompressionOptions,
4+
HandlerResponse,
5+
HttpStatusCode,
6+
} from '../types/rest.js';
7+
import { COMPRESSION_ENCODING_TYPES, HttpErrorCodes } from './constants.js';
48
import { isAPIGatewayProxyResult } from './utils.js';
59

610
/**
@@ -181,10 +185,12 @@ export const handlerResultToWebResponse = (
181185
* Handles APIGatewayProxyResult, Response objects, and plain objects.
182186
*
183187
* @param response - The handler response (APIGatewayProxyResult, Response, or plain object)
188+
* @param statusCode - The response status code to return
184189
* @returns An API Gateway proxy result
185190
*/
186191
export const handlerResultToProxyResult = async (
187-
response: HandlerResponse
192+
response: HandlerResponse,
193+
statusCode: HttpStatusCode = HttpErrorCodes.OK
188194
): Promise<APIGatewayProxyResult> => {
189195
if (isAPIGatewayProxyResult(response)) {
190196
return response;
@@ -193,7 +199,7 @@ export const handlerResultToProxyResult = async (
193199
return await webResponseToProxyResult(response);
194200
}
195201
return {
196-
statusCode: 200,
202+
statusCode,
197203
body: JSON.stringify(response),
198204
headers: { 'content-type': 'application/json' },
199205
isBase64Encoded: false,

packages/event-handler/src/rest/errors.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { ErrorResponse, HttpStatusCode } from '../types/rest.js';
1+
import type { JSONValue } from '@aws-lambda-powertools/commons/types';
2+
import type { HandlerResponse, HttpStatusCode } from '../types/rest.js';
23
import { HttpErrorCodes } from './constants.js';
34

45
export class RouteMatchingError extends Error {
@@ -34,12 +35,14 @@ export abstract class ServiceError extends Error {
3435
this.details = details;
3536
}
3637

37-
toJSON(): ErrorResponse {
38+
toJSON(): HandlerResponse {
3839
return {
3940
statusCode: this.statusCode,
4041
error: this.errorType,
4142
message: this.message,
42-
...(this.details && { details: this.details }),
43+
...(this.details && {
44+
details: this.details as Record<string, JSONValue>,
45+
}),
4346
};
4447
}
4548
}

packages/event-handler/src/types/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export type {
3535
CorsOptions,
3636
ErrorHandler,
3737
ErrorResolveOptions,
38-
ErrorResponse,
3938
HandlerResponse,
4039
HttpMethod,
4140
HttpStatusCode,

packages/event-handler/src/types/rest.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@ import type { Route } from '../rest/Route.js';
88
import type { Router } from '../rest/Router.js';
99
import type { ResolveOptions } from './common.js';
1010

11-
type ErrorResponse = {
12-
statusCode: HttpStatusCode;
13-
error: string;
14-
message: string;
15-
};
16-
1711
type RequestContext = {
1812
req: Request;
1913
event: APIGatewayProxyEvent;
@@ -27,7 +21,7 @@ type ErrorResolveOptions = RequestContext & ResolveOptions;
2721
type ErrorHandler<T extends Error = Error> = (
2822
error: T,
2923
reqCtx: RequestContext
30-
) => Promise<ErrorResponse>;
24+
) => Promise<HandlerResponse>;
3125

3226
interface ErrorConstructor<T extends Error = Error> {
3327
new (...args: any[]): T;
@@ -165,7 +159,6 @@ export type {
165159
CompiledRoute,
166160
CorsOptions,
167161
DynamicRoute,
168-
ErrorResponse,
169162
ErrorConstructor,
170163
ErrorHandlerRegistryOptions,
171164
ErrorHandler,

0 commit comments

Comments
 (0)