diff --git a/src/presets/_types.gen.ts b/src/presets/_types.gen.ts index 22a02ea47f..8d3dc009c3 100644 --- a/src/presets/_types.gen.ts +++ b/src/presets/_types.gen.ts @@ -1,6 +1,7 @@ // Auto-generated using gen-presets script import type { PresetOptions as AwsAmplifyOptions } from "./aws-amplify/preset"; +import type { PresetOptions as AwsLambdaOptions } from "./aws-lambda/preset"; import type { PresetOptions as AzureOptions } from "./azure/preset"; import type { PresetOptions as CloudflareOptions } from "./cloudflare/preset"; import type { PresetOptions as FirebaseOptions } from "./firebase/preset"; @@ -9,6 +10,7 @@ import type { PresetOptions as VercelOptions } from "./vercel/preset"; export interface PresetOptions { awsAmplify: AwsAmplifyOptions; + awsLambda: AwsLambdaOptions; azure: AzureOptions; cloudflare: CloudflareOptions; firebase: FirebaseOptions; @@ -16,6 +18,6 @@ export interface PresetOptions { vercel: VercelOptions; } -export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "aws-lambda-streaming" | "azure" | "azure-functions" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-module-legacy" | "cloudflare-pages" | "cloudflare-pages-static" | "cloudflare-worker" | "deno" | "deno-deploy" | "deno-server" | "digital-ocean" | "edgio" | "firebase" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis" | "iis-handler" | "iis-node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlify-edge" | "netlify-legacy" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-listener" | "node-server" | "platform-sh" | "render-com" | "service-worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static"; +export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure" | "azure-functions" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-module-legacy" | "cloudflare-pages" | "cloudflare-pages-static" | "cloudflare-worker" | "deno" | "deno-deploy" | "deno-server" | "digital-ocean" | "edgio" | "firebase" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis" | "iis-handler" | "iis-node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlify-edge" | "netlify-legacy" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-listener" | "node-server" | "platform-sh" | "render-com" | "service-worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static"; -export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "aws-lambda-streaming" | "awsLambdaStreaming" | "aws_lambda_streaming" | "azure" | "azure-functions" | "azureFunctions" | "azure_functions" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-module-legacy" | "cloudflareModuleLegacy" | "cloudflare_module_legacy" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "cloudflare-worker" | "cloudflareWorker" | "cloudflare_worker" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "edgio" | "firebase" | "flight-control" | "flightControl" | "flight_control" | "genezio" | "github-pages" | "githubPages" | "github_pages" | "gitlab-pages" | "gitlabPages" | "gitlab_pages" | "heroku" | "iis" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlifyBuilder" | "netlify_builder" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-legacy" | "netlifyLegacy" | "netlify_legacy" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-listener" | "nodeListener" | "node_listener" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "service-worker" | "serviceWorker" | "service_worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercelEdge" | "vercel_edge" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {}); +export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "azure" | "azure-functions" | "azureFunctions" | "azure_functions" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-module-legacy" | "cloudflareModuleLegacy" | "cloudflare_module_legacy" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "cloudflare-worker" | "cloudflareWorker" | "cloudflare_worker" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "edgio" | "firebase" | "flight-control" | "flightControl" | "flight_control" | "genezio" | "github-pages" | "githubPages" | "github_pages" | "gitlab-pages" | "gitlabPages" | "gitlab_pages" | "heroku" | "iis" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlifyBuilder" | "netlify_builder" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-legacy" | "netlifyLegacy" | "netlify_legacy" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-listener" | "nodeListener" | "node_listener" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "service-worker" | "serviceWorker" | "service_worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercelEdge" | "vercel_edge" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {}); diff --git a/src/presets/aws-lambda/preset.ts b/src/presets/aws-lambda/preset.ts index 4d861561fb..14be332239 100644 --- a/src/presets/aws-lambda/preset.ts +++ b/src/presets/aws-lambda/preset.ts @@ -1,8 +1,19 @@ import { defineNitroPreset } from "nitropack/kit"; +export type { AwsLambdaOptions as PresetOptions } from "./types"; const awsLambda = defineNitroPreset( { entry: "./runtime/aws-lambda", + awsLambda: { + streaming: false, + }, + hooks: { + "rollup:before": (nitro, rollupConfig) => { + if (nitro.options.awsLambda.streaming) { + (rollupConfig.input as string) += "-streaming"; + } + }, + }, }, { name: "aws-lambda" as const, @@ -10,15 +21,4 @@ const awsLambda = defineNitroPreset( } ); -const awsLambdaStreaming = defineNitroPreset( - { - extends: "aws-lambda", - entry: "./runtime/aws-lambda-streaming", - }, - { - name: "aws-lambda-streaming" as const, - url: import.meta.url, - } -); - -export default [awsLambda, awsLambdaStreaming] as const; +export default [awsLambda] as const; diff --git a/src/presets/aws-lambda/runtime/aws-lambda-streaming.ts b/src/presets/aws-lambda/runtime/aws-lambda-streaming.ts index 50f54f33fa..1efaf50a22 100644 --- a/src/presets/aws-lambda/runtime/aws-lambda-streaming.ts +++ b/src/presets/aws-lambda/runtime/aws-lambda-streaming.ts @@ -1,3 +1,4 @@ +import type { Readable } from "node:stream"; import type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2, @@ -11,31 +12,6 @@ import { } from "nitropack/runtime/internal"; import { withQuery } from "ufo"; -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace awslambda { - // https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html - function streamifyResponse( - handler: ( - event: APIGatewayProxyEventV2, - responseStream: NodeJS.WritableStream, - context: Context - ) => Promise - ): any; - - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace HttpResponseStream { - function from( - stream: NodeJS.WritableStream, - metadata: { - statusCode: APIGatewayProxyStructuredResultV2["statusCode"]; - headers: APIGatewayProxyStructuredResultV2["headers"]; - } - ): NodeJS.WritableStream; - } - } -} - const nitroApp = useNitroApp(); export const handler = awslambda.streamifyResponse( @@ -72,25 +48,55 @@ export const handler = awslambda.streamifyResponse( }, }; if (r.body) { - const reader = r.body as ReadableStream; const writer = awslambda.HttpResponseStream.from( responseStream, httpResponseMetadata ); - await streamToNodeStream(reader.getReader(), responseStream); + if (!(r.body as ReadableStream).getReader) { + writer.write(r.body as any /* TODO */); + writer.end(); + return; + } + const reader = (r.body as ReadableStream).getReader(); + await streamToNodeStream(reader, responseStream); writer.end(); } } ); -const streamToNodeStream = async ( - reader: ReadableStreamDefaultReader, +async function streamToNodeStream( + reader: Readable | ReadableStreamDefaultReader, writer: NodeJS.WritableStream -) => { +) { let readResult = await reader.read(); while (!readResult.done) { writer.write(readResult.value); readResult = await reader.read(); } writer.end(); -}; +} + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace awslambda { + // https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html + function streamifyResponse( + handler: ( + event: APIGatewayProxyEventV2, + responseStream: NodeJS.WritableStream, + context: Context + ) => Promise + ): any; + + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace HttpResponseStream { + function from( + stream: NodeJS.WritableStream, + metadata: { + statusCode: APIGatewayProxyStructuredResultV2["statusCode"]; + headers: APIGatewayProxyStructuredResultV2["headers"]; + } + ): NodeJS.WritableStream; + } + } +} diff --git a/src/presets/aws-lambda/types.ts b/src/presets/aws-lambda/types.ts new file mode 100644 index 0000000000..080cad973e --- /dev/null +++ b/src/presets/aws-lambda/types.ts @@ -0,0 +1,3 @@ +export interface AwsLambdaOptions { + streaming?: boolean; +}