-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds a helper to support streaming responses in Netlify Functions. The decorator handles all the `awslambda` things under the hood, all that devs have to do is return a `NodeJS.Readable` or a Web Stream as the `body`. It also updates the Node.js version to v14, so that `pipeline` is available, which makes this a breaking change technically - but as @ascorbic notes, not an actual one. --------- Co-authored-by: Eduardo Bouças <mail@eduardoboucas.com>
- Loading branch information
1 parent
88274d8
commit 7b305cf
Showing
9 changed files
with
91 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,6 @@ | |
"typescript": "^4.4.4" | ||
}, | ||
"engines": { | ||
"node": ">=8.3.0" | ||
"node": ">=14.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
export { Context as HandlerContext } from './context.js' | ||
export { Event as HandlerEvent } from './event.js' | ||
export { BuilderHandler, Handler, BackgroundHandler, HandlerCallback } from './handler.js' | ||
export { BuilderResponse, Response as HandlerResponse } from './response.js' | ||
export { BuilderHandler, Handler, BackgroundHandler, HandlerCallback, StreamingHandler } from './handler.js' | ||
export { BuilderResponse, Response as HandlerResponse, StreamingResponse } from './response.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { pipeline as pipelineSync } from 'node:stream' | ||
import { promisify } from 'node:util' | ||
|
||
import type { Handler, HandlerEvent, HandlerContext, StreamingHandler, StreamingResponse } from '../function/index.js' | ||
|
||
// Node v14 doesn't have node:stream/promises | ||
const pipeline = promisify(pipelineSync) | ||
|
||
declare global { | ||
// eslint-disable-next-line @typescript-eslint/no-namespace | ||
namespace awslambda { | ||
function streamifyResponse( | ||
handler: (event: HandlerEvent, responseStream: NodeJS.WritableStream, context: HandlerContext) => Promise<void>, | ||
): Handler | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-namespace | ||
namespace HttpResponseStream { | ||
function from(stream: NodeJS.WritableStream, metadata: Omit<StreamingResponse, 'body'>): NodeJS.WritableStream | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Enables streaming responses. `body` accepts a Node.js `Readable` stream or a WHATWG `ReadableStream`. | ||
* | ||
* @example | ||
* ``` | ||
* const { Readable } = require('stream'); | ||
* | ||
* export const handler = stream(async (event, context) => { | ||
* const stream = Readable.from(Buffer.from(JSON.stringify(event))) | ||
* return { | ||
* statusCode: 200, | ||
* body: stream, | ||
* } | ||
* }) | ||
* ``` | ||
* | ||
* @example | ||
* ``` | ||
* export const handler = stream(async (event, context) => { | ||
* const response = await fetch('https://api.openai.com/', { ... }) | ||
* // ... | ||
* return { | ||
* statusCode: 200, | ||
* body: response.body, // Web stream | ||
* } | ||
* }) | ||
* ``` | ||
* | ||
* @param handler | ||
* @see https://ntl.fyi/streaming-func | ||
*/ | ||
const stream = (handler: StreamingHandler): Handler => | ||
awslambda.streamifyResponse(async (event, responseStream, context) => { | ||
const { body, ...httpResponseMetadata } = await handler(event, context) | ||
|
||
const responseBody = awslambda.HttpResponseStream.from(responseStream, httpResponseMetadata) | ||
|
||
if (typeof body === 'undefined') { | ||
responseBody.end() | ||
} else if (typeof body === 'string') { | ||
responseBody.write(body) | ||
responseBody.end() | ||
} else { | ||
await pipeline(body, responseBody) | ||
} | ||
}) | ||
|
||
export { stream } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export { builder } from './lib/builder.js' | ||
export { schedule } from './lib/schedule.js' | ||
export { stream } from './lib/stream.js' | ||
export * from './function/index.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters