Skip to content

Commit df92e5d

Browse files
committed
address PR comments
1 parent 50444dd commit df92e5d

File tree

8 files changed

+67
-36
lines changed

8 files changed

+67
-36
lines changed

package-lock.json

Lines changed: 1 addition & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/event-handler/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@
125125
"url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues"
126126
},
127127
"dependencies": {
128-
"@aws-lambda-powertools/commons": "2.27.0",
129-
"lambda-stream": "0.6.0"
128+
"@aws-lambda-powertools/commons": "2.27.0"
130129
},
131130
"keywords": [
132131
"aws",

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
isDevMode,
88
} from '@aws-lambda-powertools/commons/utils/env';
99
import type { APIGatewayProxyResult, Context } from 'aws-lambda';
10-
import type { ResolveStreamOptions } from '../types/common.js';
1110
import type { HandlerResponse, ResolveOptions } from '../types/index.js';
1211
import type {
1312
ErrorConstructor,
@@ -17,6 +16,7 @@ import type {
1716
Middleware,
1817
Path,
1918
RequestContext,
19+
ResolveStreamOptions,
2020
ResponseStream,
2121
RestRouteOptions,
2222
RestRouterOptions,

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Readable } from 'node:stream';
1+
import { Readable, Writable } from 'node:stream';
22
import { isRecord, isString } from '@aws-lambda-powertools/commons/typeutils';
33
import type { APIGatewayProxyEvent } from 'aws-lambda';
44
import type {
@@ -239,7 +239,13 @@ export const resolvePrefixedPath = (path: Path, prefix?: Path): Path => {
239239

240240
export const HttpResponseStream =
241241
globalThis.awslambda?.HttpResponseStream ??
242-
class HttpResponseStream {
242+
class LocalHttpResponseStream extends Writable {
243+
#contentType: string | undefined;
244+
245+
setContentType(contentType: string) {
246+
this.#contentType = contentType;
247+
}
248+
243249
static from(
244250
underlyingStream: ResponseStream,
245251
prelude: Record<string, string>

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

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import type { AppSyncEventsResolver } from '../appsync-events/AppSyncEventsResolver.js';
2-
import type { AppSyncGraphQLResolver } from '../appsync-graphql/AppSyncGraphQLResolver.js';
3-
import type { ResponseStream } from './rest.js';
4-
51
// biome-ignore lint/suspicious/noExplicitAny: We intentionally use `any` here to represent any type of data and keep the logger is as flexible as possible.
62
type Anything = any;
73

@@ -43,9 +39,4 @@ type ResolveOptions = {
4339
scope?: unknown;
4440
};
4541

46-
type ResolveStreamOptions = {
47-
scope?: unknown;
48-
responseStream: ResponseStream;
49-
};
50-
51-
export type { Anything, ResolveOptions, ResolveStreamOptions };
42+
export type { Anything, ResolveOptions };

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

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import type {
88
APIGatewayProxyResult,
99
Context,
1010
} from 'aws-lambda';
11-
import type { ResponseStream as LambdaResponseStream } from 'lambda-stream';
1211
import type { HttpStatusCodes, HttpVerbs } from '../rest/constants.js';
1312
import type { Route } from '../rest/Route.js';
13+
import type { HttpResponseStream } from '../rest/utils.js';
1414
import type { ResolveOptions } from './common.js';
1515

1616
type RequestContext = {
@@ -65,10 +65,6 @@ type ExtendedAPIGatewayProxyResult = Omit<APIGatewayProxyResult, 'body'> & {
6565
body: ExtendedAPIGatewayProxyResultBody;
6666
};
6767

68-
type ResponseStream = LambdaResponseStream & {
69-
_onBeforeFirstWrite?: (write: (data: Uint8Array | string) => void) => void;
70-
};
71-
7268
type HandlerResponse = Response | JSONObject | ExtendedAPIGatewayProxyResult;
7369

7470
type RouteHandler<TReturn = HandlerResponse> = (
@@ -126,6 +122,51 @@ type ValidationResult = {
126122
issues: string[];
127123
};
128124

125+
type ResponseStream = InstanceType<typeof HttpResponseStream> & {
126+
_onBeforeFirstWrite?: (write: (data: Uint8Array | string) => void) => void;
127+
};
128+
129+
/**
130+
* Object to pass to the {@link Router.resolveStream | `Router.resolveStream()`} method.
131+
*/
132+
type ResolveStreamOptions = {
133+
/**
134+
* Reference to `this` instance of the class that is calling the `resolveStream` method.
135+
*
136+
* This parameter should be used only when using {@link Router} route decorators like
137+
* {@link Router.get | `Router.get()`}, {@link Router.post | `Router.post()`}, etc. as class method decorators, and
138+
* it's used to bind the decorated methods to your class instance.
139+
*
140+
* @example
141+
* ```ts
142+
* import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
143+
*
144+
* const app = new Router();
145+
*
146+
* class Lambda {
147+
* public scope = 'scoped';
148+
*
149+
* @app.get('/test')
150+
* public async getTest() {
151+
* return { message: `${this.scope}: success` };
152+
* }
153+
*
154+
* public async handler(event: unknown, context: Context, responseStream: ResponseStream) {
155+
* return app.resolveStream(event, context, { scope: this, responseStream });
156+
* }
157+
* }
158+
* const lambda = new Lambda();
159+
* const handler = lambda.handler.bind(lambda);
160+
* ```
161+
*/
162+
scope?: unknown;
163+
/**
164+
* The Lambda response stream used for streaming responses directly to the client.
165+
* This stream is provided by the AWS Lambda runtime for response streaming.
166+
*/
167+
responseStream: ResponseStream;
168+
};
169+
129170
/**
130171
* Configuration options for CORS middleware
131172
*/
@@ -190,8 +231,9 @@ export type {
190231
Path,
191232
RequestContext,
192233
RestRouterOptions,
193-
ResponseStream,
194234
RouteHandler,
235+
ResolveStreamOptions,
236+
ResponseStream,
195237
RestRouteOptions,
196238
RestRouteHandlerOptions,
197239
RouteRegistryOptions,

packages/event-handler/tests/unit/rest/Router/middleware.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,9 @@ describe('Class: Router - Middleware', () => {
191191
await next();
192192
});
193193

194-
app.use(({ next }) => {
194+
// biome-ignore lint/suspicious/useAwait: This specifically tests a missing await call in an async function
195+
app.use(async ({ next }) => {
195196
next();
196-
return Promise.resolve();
197197
});
198198

199199
// Act

packages/event-handler/tests/unit/rest/helpers.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { APIGatewayProxyEvent } from 'aws-lambda';
2-
import { ResponseStream } from 'lambda-stream';
2+
import { HttpResponseStream } from '../../../src/rest/utils.js';
33
import type { HandlerResponse, Middleware } from '../../../src/types/rest.js';
44

55
export const createTestEvent = (
@@ -92,19 +92,19 @@ export const createHeaderCheckMiddleware = (headers: {
9292
};
9393

9494
// Mock ResponseStream that extends the actual ResponseStream class
95-
export class MockResponseStream extends ResponseStream {
95+
export class MockResponseStream extends HttpResponseStream {
9696
public chunks: Buffer[] = [];
9797
public _onBeforeFirstWrite?: (
9898
write: (data: Uint8Array | string) => void
9999
) => void;
100-
private firstWrite = true;
100+
#firstWrite = true;
101101

102102
_write(chunk: Buffer, _encoding: string, callback: () => void): void {
103-
if (this.firstWrite && this._onBeforeFirstWrite) {
103+
if (this.#firstWrite && this._onBeforeFirstWrite) {
104104
this._onBeforeFirstWrite((data: Uint8Array | string) => {
105105
this.chunks.push(Buffer.from(data));
106106
});
107-
this.firstWrite = false;
107+
this.#firstWrite = false;
108108
}
109109
this.chunks.push(chunk);
110110
callback();

0 commit comments

Comments
 (0)