Skip to content
This repository was archived by the owner on Jun 9, 2025. It is now read-only.
6 changes: 3 additions & 3 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
node-version: [8.17.0, '*']
node-version: [14.0.0, '*']
exclude:
- os: macOS-latest
node-version: 8.17.0
node-version: 14.0.0
- os: windows-latest
node-version: 8.17.0
node-version: 14.0.0
fail-fast: false
steps:
- name: Git checkout
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@
"typescript": "^4.4.4"
},
"engines": {
"node": ">=8.3.0"
"node": ">=14.0.0"
}
}
6 changes: 5 additions & 1 deletion src/function/handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Context } from './context.js'
import type { Event } from './event.js'
import type { Response, BuilderResponse } from './response.js'
import type { Response, BuilderResponse, StreamingResponse } from './response.js'

export interface HandlerCallback<ResponseType extends Response = Response> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -17,3 +17,7 @@ export interface BackgroundHandler<C extends Context = Context> {

export type Handler = BaseHandler<Response, Context>
export type BuilderHandler = BaseHandler<BuilderResponse, Context>

export interface StreamingHandler {
(event: Event, context: Context): Promise<StreamingResponse>
}
2 changes: 1 addition & 1 deletion src/function/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { Context as HandlerContext } from './context.js'
export { Event as HandlerEvent } from './event.js'
export { BuilderHandler, Handler, BackgroundHandler, HandlerCallback } from './handler.js'
export { BuilderHandler, Handler, BackgroundHandler, HandlerCallback, StreamingHandler } from './handler.js'
export { BuilderResponse, Response as HandlerResponse } from './response.js'
export {
getSecrets,
Expand Down
4 changes: 4 additions & 0 deletions src/function/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ export interface Response {
export interface BuilderResponse extends Response {
ttl?: number
}

export interface StreamingResponse extends Omit<Response, 'body'> {
body?: string | NodeJS.ReadableStream
}
1 change: 0 additions & 1 deletion src/lib/secrets_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ const findLoggedInServicesQuery = `query FindLoggedInServicesQuery {
const getSecretsForToken = async (token: string): Promise<NetlifySecrets> => {
const body = JSON.stringify({ query: findLoggedInServicesQuery })

// eslint-disable-next-line n/no-unsupported-features/node-builtins
const resultBody = await graphRequest(token, new TextEncoder().encode(body))
const result: GraphSecretsResponse = JSON.parse(resultBody)

Expand Down
55 changes: 55 additions & 0 deletions src/lib/stream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { pipeline } from 'stream'

import type { Handler, HandlerEvent, HandlerContext, HandlerResponse, StreamingHandler } from '../function/index.js'

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace awslambda {
function streamifyResponse(
handler: (
event: HandlerEvent,
responseStream: NodeJS.WritableStream,
context: HandlerContext,
) => Promise<HandlerResponse>,
): Handler
}
}

/**
* Enables streaming responses.
*
* @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,
* }
* })
* ```
*
* @param handler
* @see https://ntl.fyi/streaming-func
*/
const stream = (handler: StreamingHandler): Handler =>
awslambda.streamifyResponse(async (event, responseStream, context) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the plan for making this with in local development? Should we add this to https://github.com/ashiina/lambda-local?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's probably the best way forward, yes. I think we already got one PR in there.

const { body, ...rest } = await handler(event, context)

if (typeof body === 'undefined' || typeof body === 'string') {
return {
body,
...rest,
}
}

pipeline(body, responseStream)

return {
...rest,
}
})

export { stream }
1 change: 1 addition & 0 deletions src/main.ts
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'
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */

/* Language and Environment */
"target": "es5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"target": "ES2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
Expand Down