From ac2be4a2e53aa1596fa21643cefb3523f29d0a03 Mon Sep 17 00:00:00 2001 From: Dorseuil Nicolas Date: Mon, 20 Nov 2023 16:50:37 +0100 Subject: [PATCH] big refactoring moved files around so that it makes more sense deleted a bunch of useless files added todo to remind myself of what i still need to do --- .../open-next/src/adapters/config/util.ts | 6 +- .../open-next/src/adapters/event-mapper.ts | 338 ------------------ packages/open-next/src/adapters/http/index.ts | 3 - .../open-next/src/adapters/http/response.ts | 150 -------- .../src/adapters/http/responseStreaming.ts | 263 -------------- packages/open-next/src/adapters/http/util.ts | 50 --- .../adapters/image-optimization-adapter.ts | 2 +- .../adapters/plugins/13.5/serverHandler.ts | 5 +- .../src/adapters/plugins/routing/util.ts | 11 +- .../plugins/serverHandler.replacement.ts | 5 +- .../src/adapters/plugins/serverHandler.ts | 9 +- .../src/adapters/plugins/util.replacement.ts | 2 +- .../open-next/src/adapters/plugins/util.ts | 10 +- .../open-next/src/adapters/require-hooks.ts | 3 +- .../open-next/src/adapters/server-adapter.ts | 5 +- packages/open-next/src/adapters/util.ts | 35 +- packages/open-next/src/build.ts | 3 +- .../open-next/src/converters/aws-apigw-v1.ts | 3 +- .../open-next/src/converters/aws-apigw-v2.ts | 5 +- .../src/converters/aws-cloudfront.ts | 3 +- packages/open-next/src/converters/docker.ts | 6 +- .../open-next/src/core/createMainHandler.ts | 5 +- packages/open-next/src/core/requestHandler.ts | 11 +- .../open-next/src/core/routing/matcher.ts | 21 +- .../open-next/src/core/routing/middleware.ts | 5 +- packages/open-next/src/core/routing/util.ts | 29 +- packages/open-next/src/core/routingHandler.ts | 8 +- packages/open-next/src/http/index.ts | 2 + .../{adapters => }/http/openNextResponse.ts | 3 +- .../src/{adapters => }/http/request.ts | 0 packages/open-next/src/http/util.ts | 42 +++ .../src/{adapters => }/types/aws-lambda.ts | 0 .../src/{adapters => }/types/next-types.ts | 9 +- .../src/{adapters => }/types/open-next.ts | 26 +- .../src/{adapters => }/types/plugin.ts | 6 +- .../src/wrappers/aws-lambda-streaming.ts | 7 +- packages/open-next/src/wrappers/aws-lambda.ts | 4 +- packages/open-next/src/wrappers/docker.ts | 4 +- packages/open-next/tsconfig.json | 7 +- 39 files changed, 182 insertions(+), 924 deletions(-) delete mode 100644 packages/open-next/src/adapters/event-mapper.ts delete mode 100644 packages/open-next/src/adapters/http/index.ts delete mode 100644 packages/open-next/src/adapters/http/response.ts delete mode 100644 packages/open-next/src/adapters/http/responseStreaming.ts delete mode 100644 packages/open-next/src/adapters/http/util.ts create mode 100644 packages/open-next/src/http/index.ts rename packages/open-next/src/{adapters => }/http/openNextResponse.ts (97%) rename packages/open-next/src/{adapters => }/http/request.ts (100%) create mode 100644 packages/open-next/src/http/util.ts rename packages/open-next/src/{adapters => }/types/aws-lambda.ts (100%) rename packages/open-next/src/{adapters => }/types/next-types.ts (91%) rename packages/open-next/src/{adapters => }/types/open-next.ts (86%) rename packages/open-next/src/{adapters => }/types/plugin.ts (81%) diff --git a/packages/open-next/src/adapters/config/util.ts b/packages/open-next/src/adapters/config/util.ts index b0455ed5..30932811 100644 --- a/packages/open-next/src/adapters/config/util.ts +++ b/packages/open-next/src/adapters/config/util.ts @@ -1,12 +1,12 @@ import fs from "fs"; import path from "path"; - -import { PublicFiles } from "../../build"; import { NextConfig, PrerenderManifest, RoutesManifest, -} from "../types/next-types"; +} from "types/next-types"; + +import { PublicFiles } from "../../build"; export function loadConfig(nextDir: string) { const filePath = path.join(nextDir, "required-server-files.json"); diff --git a/packages/open-next/src/adapters/event-mapper.ts b/packages/open-next/src/adapters/event-mapper.ts deleted file mode 100644 index b0a343c7..00000000 --- a/packages/open-next/src/adapters/event-mapper.ts +++ /dev/null @@ -1,338 +0,0 @@ -import type { - APIGatewayProxyEvent, - APIGatewayProxyEventV2, - APIGatewayProxyResult, - APIGatewayProxyResultV2, - CloudFrontHeaders, - CloudFrontRequestEvent, - CloudFrontRequestResult, -} from "aws-lambda"; - -import { debug } from "./logger.js"; -import { parseCookies } from "./util.js"; - -export type InternalEvent = { - readonly type: "v1" | "v2" | "cf"; - readonly method: string; - readonly rawPath: string; - readonly url: string; - readonly body: Buffer; - readonly headers: Record; - readonly query: Record; - readonly cookies: Record; - readonly remoteAddress: string; -}; - -export type InternalResult = { - readonly type: "v1" | "v2" | "cf"; - statusCode: number; - headers: Record; - body: string; - isBase64Encoded: boolean; -}; - -export function isAPIGatewayProxyEventV2( - event: any, -): event is APIGatewayProxyEventV2 { - return event.version === "2.0"; -} - -export function isAPIGatewayProxyEvent( - event: any, -): event is APIGatewayProxyEvent { - return event.version === undefined && !isCloudFrontRequestEvent(event); -} - -export function isCloudFrontRequestEvent( - event: any, -): event is CloudFrontRequestEvent { - return event.Records !== undefined; -} - -export function convertFrom( - event: APIGatewayProxyEventV2 | APIGatewayProxyEvent | CloudFrontRequestEvent, -): InternalEvent { - let internalEvent: InternalEvent; - if (isCloudFrontRequestEvent(event)) { - internalEvent = convertFromCloudFrontRequestEvent(event); - } else if (isAPIGatewayProxyEventV2(event)) { - internalEvent = convertFromAPIGatewayProxyEventV2(event); - } else if (isAPIGatewayProxyEvent(event)) { - internalEvent = convertFromAPIGatewayProxyEvent(event); - } else throw new Error("Unsupported event type"); - - return internalEvent; -} - -export function convertTo( - result: InternalResult, -): APIGatewayProxyResultV2 | APIGatewayProxyResult | CloudFrontRequestResult { - if (result.type === "v2") { - return convertToApiGatewayProxyResultV2(result); - } else if (result.type === "v1") { - return convertToApiGatewayProxyResult(result); - } else if (result.type === "cf") { - return convertToCloudFrontRequestResult(result); - } - throw new Error("Unsupported event type"); -} - -function removeUndefinedFromQuery( - query: Record, -) { - const newQuery: Record = {}; - for (const [key, value] of Object.entries(query)) { - if (value !== undefined) { - newQuery[key] = value; - } - } - return newQuery; -} -function convertFromAPIGatewayProxyEvent( - event: APIGatewayProxyEvent, -): InternalEvent { - const { path, body, httpMethod, requestContext, isBase64Encoded } = event; - return { - type: "v1", - method: httpMethod, - rawPath: path, - url: path + normalizeAPIGatewayProxyEventQueryParams(event), - body: Buffer.from(body ?? "", isBase64Encoded ? "base64" : "utf8"), - headers: normalizeAPIGatewayProxyEventHeaders(event), - remoteAddress: requestContext.identity.sourceIp, - query: removeUndefinedFromQuery( - event.multiValueQueryStringParameters ?? {}, - ), - cookies: - event.multiValueHeaders?.cookie?.reduce((acc, cur) => { - const [key, value] = cur.split("="); - return { ...acc, [key]: value }; - }, {}) ?? {}, - }; -} - -function convertFromAPIGatewayProxyEventV2( - event: APIGatewayProxyEventV2, -): InternalEvent { - const { rawPath, rawQueryString, requestContext } = event; - return { - type: "v2", - method: requestContext.http.method, - rawPath, - url: rawPath + (rawQueryString ? `?${rawQueryString}` : ""), - body: normalizeAPIGatewayProxyEventV2Body(event), - headers: normalizeAPIGatewayProxyEventV2Headers(event), - remoteAddress: requestContext.http.sourceIp, - query: removeUndefinedFromQuery(event.queryStringParameters ?? {}), - cookies: - event.cookies?.reduce((acc, cur) => { - const [key, value] = cur.split("="); - return { ...acc, [key]: value }; - }, {}) ?? {}, - }; -} - -function convertFromCloudFrontRequestEvent( - event: CloudFrontRequestEvent, -): InternalEvent { - const { method, uri, querystring, body, headers, clientIp } = - event.Records[0].cf.request; - return { - type: "cf", - method, - rawPath: uri, - url: uri + (querystring ? `?${querystring}` : ""), - body: Buffer.from( - body?.data ?? "", - body?.encoding === "base64" ? "base64" : "utf8", - ), - headers: normalizeCloudFrontRequestEventHeaders(headers), - remoteAddress: clientIp, - query: querystring.split("&").reduce( - (acc, cur) => ({ - ...acc, - [cur.split("=")[0]]: cur.split("=")[1], - }), - {}, - ), - cookies: - headers.cookie?.reduce((acc, cur) => { - const { key, value } = cur; - return { ...acc, [key ?? ""]: value }; - }, {}) ?? {}, - }; -} - -function convertToApiGatewayProxyResult( - result: InternalResult, -): APIGatewayProxyResult { - const headers: Record = {}; - const multiValueHeaders: Record = {}; - Object.entries(result.headers).forEach(([key, value]) => { - if (Array.isArray(value)) { - multiValueHeaders[key] = value; - } else { - if (value === null) { - headers[key] = ""; - return; - } - headers[key] = value; - } - }); - - const response: APIGatewayProxyResult = { - statusCode: result.statusCode, - headers, - body: result.body, - isBase64Encoded: result.isBase64Encoded, - multiValueHeaders, - }; - debug(response); - return response; -} - -function convertToApiGatewayProxyResultV2( - result: InternalResult, -): APIGatewayProxyResultV2 { - const headers: Record = {}; - Object.entries(result.headers) - .filter(([key]) => key.toLowerCase() !== "set-cookie") - .forEach(([key, value]) => { - if (value === null) { - headers[key] = ""; - return; - } - headers[key] = Array.isArray(value) ? value.join(", ") : value.toString(); - }); - - const response: APIGatewayProxyResultV2 = { - statusCode: result.statusCode, - headers, - cookies: parseCookies(result.headers["set-cookie"]), - body: result.body, - isBase64Encoded: result.isBase64Encoded, - }; - debug(response); - return response; -} - -function convertToCloudFrontRequestResult( - result: InternalResult, -): CloudFrontRequestResult { - const headers: CloudFrontHeaders = {}; - Object.entries(result.headers) - .filter(([key]) => key.toLowerCase() !== "content-length") - .forEach(([key, value]) => { - headers[key] = [ - ...(headers[key] || []), - ...(Array.isArray(value) - ? value.map((v) => ({ key, value: v })) - : [{ key, value: value.toString() }]), - ]; - }); - - const response: CloudFrontRequestResult = { - status: result.statusCode.toString(), - statusDescription: "OK", - headers, - bodyEncoding: result.isBase64Encoded ? "base64" : "text", - body: result.body, - }; - debug(response); - return response; -} - -function normalizeAPIGatewayProxyEventV2Headers( - event: APIGatewayProxyEventV2, -): Record { - const { headers: rawHeaders, cookies } = event; - - const headers: Record = {}; - - if (Array.isArray(cookies)) { - headers["cookie"] = cookies.join("; "); - } - - for (const [key, value] of Object.entries(rawHeaders || {})) { - headers[key.toLowerCase()] = value!; - } - - return headers; -} - -function normalizeAPIGatewayProxyEventV2Body( - event: APIGatewayProxyEventV2, -): Buffer { - const { body, isBase64Encoded } = event; - if (Buffer.isBuffer(body)) { - return body; - } else if (typeof body === "string") { - return Buffer.from(body, isBase64Encoded ? "base64" : "utf8"); - } else if (typeof body === "object") { - return Buffer.from(JSON.stringify(body)); - } - return Buffer.from("", "utf8"); -} - -function normalizeAPIGatewayProxyEventQueryParams( - event: APIGatewayProxyEvent, -): string { - // Note that the same query string values are returned in both - // "multiValueQueryStringParameters" and "queryStringParameters". - // We only need to use one of them. - // For example: - // "?name=foo" appears in the event object as - // { - // ... - // queryStringParameters: { name: 'foo' }, - // multiValueQueryStringParameters: { name: [ 'foo' ] }, - // ... - // } - const params = new URLSearchParams(); - for (const [key, value] of Object.entries( - event.multiValueQueryStringParameters || {}, - )) { - if (value !== undefined) { - for (const v of value) { - params.append(key, v); - } - } - } - const value = params.toString(); - return value ? `?${value}` : ""; -} - -function normalizeAPIGatewayProxyEventHeaders( - event: APIGatewayProxyEvent, -): Record { - event.multiValueHeaders; - const headers: Record = {}; - - for (const [key, values] of Object.entries(event.multiValueHeaders || {})) { - if (values) { - headers[key.toLowerCase()] = values.join(","); - } - } - for (const [key, value] of Object.entries(event.headers || {})) { - if (value) { - headers[key.toLowerCase()] = value; - } - } - return headers; -} - -function normalizeCloudFrontRequestEventHeaders( - rawHeaders: CloudFrontHeaders, -): Record { - const headers: Record = {}; - - for (const [key, values] of Object.entries(rawHeaders)) { - for (const { value } of values) { - if (value) { - headers[key.toLowerCase()] = value; - } - } - } - - return headers; -} diff --git a/packages/open-next/src/adapters/http/index.ts b/packages/open-next/src/adapters/http/index.ts deleted file mode 100644 index 82e9e941..00000000 --- a/packages/open-next/src/adapters/http/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./request.js"; -export * from "./response.js"; -export * from "./responseStreaming.js"; diff --git a/packages/open-next/src/adapters/http/response.ts b/packages/open-next/src/adapters/http/response.ts deleted file mode 100644 index 9731f55d..00000000 --- a/packages/open-next/src/adapters/http/response.ts +++ /dev/null @@ -1,150 +0,0 @@ -// Copied and modified from serverless-http by Doug Moscrop -// https://github.com/dougmoscrop/serverless-http/blob/master/lib/response.js -// Licensed under the MIT License - -import http from "node:http"; -import { Socket } from "node:net"; - -import { - convertHeader, - getString, - headerEnd, - NO_OP, - parseHeaders, -} from "./util.js"; - -const BODY = Symbol(); -const HEADERS = Symbol(); - -function addData(stream: ServerlessResponse, data: Uint8Array | string) { - if ( - Buffer.isBuffer(data) || - ArrayBuffer.isView(data) || - typeof data === "string" - ) { - stream[BODY].push(Buffer.from(data)); - } else { - throw new Error(`response.addData() of unexpected type: ${typeof data}`); - } -} - -export interface ServerlessResponseProps { - method: string; - headers: Record; -} - -export class ServerlessResponse extends http.ServerResponse { - [BODY]: Buffer[]; - [HEADERS]: Record; - private _wroteHeader = false; - private _header = ""; - private _initialHeaders: Record = {}; - - constructor({ method, headers }: ServerlessResponseProps) { - super({ method, headers } as any); - - this[BODY] = []; - this[HEADERS] = parseHeaders(headers) || {}; - this._initialHeaders = this[HEADERS]; - - this.useChunkedEncodingByDefault = false; - this.chunkedEncoding = false; - this._header = ""; - - const socket: Partial & { _writableState: any } = { - _writableState: {}, - writable: true, - on: NO_OP, - removeListener: NO_OP, - destroy: NO_OP, - cork: NO_OP, - uncork: NO_OP, - write: ( - data: Uint8Array | string, - encoding?: string | null | (() => void), - cb?: () => void, - ) => { - if (typeof encoding === "function") { - cb = encoding; - encoding = null; - } - - if (this._header === "" || this._wroteHeader) { - addData(this, data); - } else { - const string = getString(data); - const index = string.indexOf(headerEnd); - - if (index !== -1) { - const remainder = string.slice(index + headerEnd.length); - - if (remainder) { - addData(this, remainder); - } - - this._wroteHeader = true; - } - } - - if (typeof cb === "function") { - cb(); - } - return true; - }, - }; - - this.assignSocket(socket as Socket); - - this.once("finish", () => { - this.emit("close"); - }); - } - - static body(res: ServerlessResponse) { - return Buffer.concat(res[BODY]); - } - - static headers(res: ServerlessResponse) { - const headers = - typeof res.getHeaders === "function" ? res.getHeaders() : res[HEADERS]; - - return { - ...parseHeaders(headers), - ...res[HEADERS], - ...res._initialHeaders, - }; - } - - get headers() { - return this[HEADERS]; - } - - setHeader(key: string, value: string | number | string[]): this { - if (this._wroteHeader) { - this[HEADERS][key] = convertHeader(value); - } else { - super.setHeader(key, value); - } - return this; - } - - writeHead( - statusCode: number, - reason?: string | any | any[], - obj?: any | any[], - ) { - const headers = typeof reason === "string" ? obj : reason; - - for (const name in headers) { - this.setHeader(name, headers[name]); - - if (!this._wroteHeader) { - // we only need to initiate super.headers once - // writeHead will add the other headers itself - break; - } - } - - return super.writeHead(statusCode, reason, obj); - } -} diff --git a/packages/open-next/src/adapters/http/responseStreaming.ts b/packages/open-next/src/adapters/http/responseStreaming.ts deleted file mode 100644 index d41eefb2..00000000 --- a/packages/open-next/src/adapters/http/responseStreaming.ts +++ /dev/null @@ -1,263 +0,0 @@ -import http from "node:http"; -import { Socket } from "node:net"; -import zlib from "node:zlib"; - -import { Writable } from "stream"; - -import { debug, error } from "../logger.js"; -// import type { ResponseStream } from "../types/aws-lambda.js"; -import { parseCookies } from "../util.js"; -import { convertHeader, getString, NO_OP, parseHeaders } from "./util.js"; - -const HEADERS = Symbol(); - -export interface ResponseStream extends Writable { - writeHeaders( - prelude: { - statusCode: number; - cookies: string[]; - headers: Record; - }, - onFinish: () => void, - ): void; - // Just to fix an issue with aws lambda streaming with empty body - onFirstWrite?: () => void; -} - -export interface StreamingServerResponseProps { - method?: string; - headers?: Record; - responseStream: ResponseStream; - fixHeaders: (headers: Record) => void; - onEnd: (headers: Record) => Promise; -} -export class StreamingServerResponse extends http.ServerResponse { - [HEADERS]: Record = {}; - responseStream: ResponseStream; - fixHeaders: (headers: Record) => void; - onEnd: (headers: Record) => Promise; - private _wroteHeader = false; - private _hasWritten = false; - private _initialHeaders: Record = {}; - private _cookies: string[] = []; - private _compressed = false; - - constructor({ - method, - headers, - responseStream, - fixHeaders, - onEnd, - }: StreamingServerResponseProps) { - super({ method } as any); - if (headers && headers["set-cookie"]) { - this._cookies = parseCookies(headers["set-cookie"]) as string[]; - delete headers["set-cookie"]; - } - this[HEADERS] = parseHeaders(headers) || {}; - this._initialHeaders = { ...this[HEADERS] }; - - this.fixHeaders = fixHeaders; - this.onEnd = onEnd; - this.responseStream = responseStream; - - this.useChunkedEncodingByDefault = false; - this.chunkedEncoding = false; - - this.responseStream.cork(); - - const socket: Partial & { _writableState: any } = { - _writableState: {}, - writable: true, - on: NO_OP, - removeListener: NO_OP, - destroy: NO_OP, - cork: NO_OP, - uncork: NO_OP, - write: ( - data: Uint8Array | string, - encoding?: string | null | (() => void), - cb?: () => void, - ) => { - if (typeof encoding === "function") { - cb = encoding; - encoding = undefined; - } - const d = getString(data); - const isSse = d.endsWith("\n\n"); - this.internalWrite(data, isSse, cb); - - return !this.responseStream.writableNeedDrain; - }, - }; - - this.assignSocket(socket as Socket); - - this.responseStream.on("close", this.cancel.bind(this)); - this.responseStream.on("error", this.cancel.bind(this)); - - this.on("close", this.cancel.bind(this)); - this.on("error", this.cancel.bind(this)); - this.once("finish", () => { - this.emit("close"); - }); - } - - get headers() { - return this[HEADERS]; - } - - setHeader(key: string, value: string | number | string[]): this { - key = key.toLowerCase(); - // There can be multiple set-cookie response headers - // They need to be returned as a special "cookies" array, eg: - // {statusCode: xxx, cookies: ['Cookie=Yum'], ...} - if (key === "set-cookie") { - this._cookies.push(convertHeader(value)); - } else { - this[HEADERS][key] = convertHeader(value); - } - return this; - } - - removeHeader(key: string): this { - key = key.toLowerCase(); - if (key === "set-cookie") { - this._cookies.length = 0; - } else { - delete this[HEADERS][key]; - } - return this; - } - - writeHead( - statusCode: number, - _statusMessage?: - | string - | http.OutgoingHttpHeaders - | http.OutgoingHttpHeader[], - _headers?: http.OutgoingHttpHeaders | http.OutgoingHttpHeader[], - ): this { - const headers = - typeof _statusMessage === "string" ? _headers : _statusMessage; - const statusMessage = - typeof _statusMessage === "string" ? _statusMessage : undefined; - if (this._wroteHeader) { - return this; - } - try { - debug("writeHead", statusCode, statusMessage, headers); - const parsedHeaders = parseHeaders(headers); - this[HEADERS] = { - ...this[HEADERS], - ...parsedHeaders, - }; - - this.fixHeaders(this[HEADERS]); - this[HEADERS] = { - ...this[HEADERS], - ...this._initialHeaders, - }; - - this._compressed = this[HEADERS]["accept-encoding"]?.includes("br"); - if (this._compressed) { - this[HEADERS]["content-encoding"] = "br"; - } - delete this[HEADERS]["accept-encoding"]; - - debug("writeHead", this[HEADERS]); - - this._wroteHeader = true; - this.statusCode = statusCode; - this.responseStream.writeHeaders( - { - statusCode, - cookies: this._cookies, - headers: this[HEADERS], - }, - () => { - if (this._compressed) { - const br = zlib.createBrotliCompress({ - flush: zlib.constants.BROTLI_OPERATION_FLUSH, - }); - br.setMaxListeners(100); - br.pipe(this.responseStream); - this.responseStream = br as unknown as ResponseStream; - } - }, - ); - - debug("writeHead", this[HEADERS]); - } catch (e) { - this.responseStream.end(); - error(e); - } - - return this; - } - - end( - _chunk?: Uint8Array | string | (() => void), - _encoding?: BufferEncoding | (() => void), - _cb?: (() => void) | undefined, - ): this { - const chunk = typeof _chunk === "function" ? undefined : _chunk; - const cb = typeof _cb === "function" ? _cb : undefined; - - if (!this._wroteHeader) { - // When next directly returns with end, the writeHead is not called, - // so we need to call it here - this.writeHead(this.statusCode ?? 200); - } - - if (!this._hasWritten && !chunk) { - // We need to send data here if there is none, otherwise the stream will not end at all - this.internalWrite(new Uint8Array(8), false, cb); - } - - const _end = () => { - setImmediate(() => { - this.responseStream.end(_chunk, async () => { - if (this._compressed) { - (this.responseStream as unknown as zlib.BrotliCompress).flush( - zlib.constants.BROTLI_OPERATION_FINISH, - ); - } - await this.onEnd(this[HEADERS]); - cb?.(); - }); - }); - }; - - if (this.responseStream.writableNeedDrain) { - this.responseStream.once("drain", _end); - } else { - _end(); - } - return this; - } - - private internalWrite(chunk: any, isSse: boolean = false, cb?: () => void) { - this._hasWritten = true; - setImmediate(() => { - this.responseStream.write(chunk, cb); - - // SSE need to flush to send to client ASAP - if (isSse) { - setImmediate(() => { - this.responseStream.write("\n\n"); - this.responseStream.uncork(); - }); - } - }); - } - - cancel(error?: Error) { - this.responseStream.off("close", this.cancel.bind(this)); - this.responseStream.off("error", this.cancel.bind(this)); - - if (error) { - this.responseStream.destroy(error); - } - } -} diff --git a/packages/open-next/src/adapters/http/util.ts b/packages/open-next/src/adapters/http/util.ts deleted file mode 100644 index 132f6798..00000000 --- a/packages/open-next/src/adapters/http/util.ts +++ /dev/null @@ -1,50 +0,0 @@ -import http from "node:http"; - -export function getString(data: any) { - // Note: use `ArrayBuffer.isView()` to check for Uint8Array. Using - // `instanceof Uint8Array` returns false in some cases. For example, - // when the buffer is created in middleware and passed to NextServer. - if (Buffer.isBuffer(data)) { - return data.toString("utf8"); - } else if (ArrayBuffer.isView(data)) { - //@ts-ignore - return Buffer.from(data).toString("utf8"); - } else if (typeof data === "string") { - return data; - } else { - throw new Error(`response.getString() of unexpected type: ${typeof data}`); - } -} - -export const headerEnd = "\r\n\r\n"; - -export const NO_OP: (...args: any[]) => any = () => void 0; - -export const parseHeaders = ( - headers?: http.OutgoingHttpHeader[] | http.OutgoingHttpHeaders, -) => { - const result: Record = {}; - if (!headers) { - return result; - } - - for (const [key, value] of Object.entries(headers)) { - if (value === undefined) { - continue; - } else { - result[key] = convertHeader(value); - } - } - - return result; -}; - -export const convertHeader = (header: http.OutgoingHttpHeader) => { - if (typeof header === "string") { - return header; - } else if (Array.isArray(header)) { - return header.join(","); - } else { - return String(header); - } -}; diff --git a/packages/open-next/src/adapters/image-optimization-adapter.ts b/packages/open-next/src/adapters/image-optimization-adapter.ts index f5fbb26b..19f2f94e 100644 --- a/packages/open-next/src/adapters/image-optimization-adapter.ts +++ b/packages/open-next/src/adapters/image-optimization-adapter.ts @@ -11,6 +11,7 @@ import type { APIGatewayProxyEventV2, APIGatewayProxyResultV2, } from "aws-lambda"; +import { loadConfig } from "config/util.js"; // @ts-ignore import { defaultConfig } from "next/dist/server/config-shared"; import { @@ -21,7 +22,6 @@ import { // @ts-ignore import type { NextUrlWithParsedQuery } from "next/dist/server/request-meta"; -import { loadConfig } from "./config/util.js"; import { awsLogger, debug, error } from "./logger.js"; import { setNodeEnv } from "./util.js"; diff --git a/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts b/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts index 7ad3a75c..099a7e3e 100644 --- a/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts +++ b/packages/open-next/src/adapters/plugins/13.5/serverHandler.ts @@ -1,12 +1,11 @@ /*eslint-disable simple-import-sort/imports */ -import type { Options, PluginHandler } from "../../types/next-types.js"; -import type { IncomingMessage } from "../../http/request.js"; +import type { Options, PluginHandler } from "types/next-types.js"; +import type { IncomingMessage, OpenNextNodeResponse } from "http/index.js"; //#override imports //@ts-ignore import { requestHandler } from "./util.js"; //@ts-ignore import { proxyRequest } from "./routing/util.js"; -import { OpenNextNodeResponse } from "../../http/openNextResponse.js"; //#endOverride //#override handler diff --git a/packages/open-next/src/adapters/plugins/routing/util.ts b/packages/open-next/src/adapters/plugins/routing/util.ts index 2f45b7b8..9d14520f 100644 --- a/packages/open-next/src/adapters/plugins/routing/util.ts +++ b/packages/open-next/src/adapters/plugins/routing/util.ts @@ -1,13 +1,13 @@ +import { BuildId, HtmlPages } from "config/index.js"; import crypto from "crypto"; import { OutgoingHttpHeaders, ServerResponse } from "http"; - -import { BuildId, HtmlPages } from "../../config/index.js"; -import { InternalEvent } from "../../event-mapper.js"; import { + IncomingMessage, OpenNextNodeResponse, StreamCreator, -} from "../../http/openNextResponse.js"; -import { IncomingMessage } from "../../http/request.js"; +} from "http/index.js"; +import { InternalEvent } from "types/open-next"; + import { debug } from "../../logger.js"; declare global { @@ -25,6 +25,7 @@ export async function proxyRequest( req: IncomingMessage, res: OpenNextNodeResponse, ) { + // TODO: we should use our own version instead of the one bundled with Next.js const HttpProxy = require("next/dist/compiled/http-proxy") as any; const proxy = new HttpProxy({ diff --git a/packages/open-next/src/adapters/plugins/serverHandler.replacement.ts b/packages/open-next/src/adapters/plugins/serverHandler.replacement.ts index a110609e..1059affc 100644 --- a/packages/open-next/src/adapters/plugins/serverHandler.replacement.ts +++ b/packages/open-next/src/adapters/plugins/serverHandler.replacement.ts @@ -1,11 +1,10 @@ /*eslint-disable simple-import-sort/imports */ -import type { Options, PluginHandler } from "../types/next-types.js"; -import type { IncomingMessage } from "../http/request.js"; +import type { Options, PluginHandler } from "types/next-types.js"; +import type { IncomingMessage, OpenNextNodeResponse } from "http/index.js"; //#override imports import { proxyRequest } from "./routing/util.js"; import { requestHandler, setNextjsPrebundledReact } from "./util.js"; -import { OpenNextNodeResponse } from "../http/openNextResponse.js"; //#endOverride //#override handler diff --git a/packages/open-next/src/adapters/plugins/serverHandler.ts b/packages/open-next/src/adapters/plugins/serverHandler.ts index 62faf332..050ce287 100644 --- a/packages/open-next/src/adapters/plugins/serverHandler.ts +++ b/packages/open-next/src/adapters/plugins/serverHandler.ts @@ -1,10 +1,13 @@ -import type { OpenNextNodeResponse } from "../http/openNextResponse.js"; -import type { IncomingMessage } from "../http/request.js"; -import type { Options, PluginHandler } from "../types/next-types.js"; +import type { IncomingMessage, OpenNextNodeResponse } from "http/index.js"; +import type { Options, PluginHandler } from "types/next-types.js"; + //#override imports import { requestHandler, setNextjsPrebundledReact } from "./util.js"; //#endOverride +//TODO: refactor this, we don't need to override this anymore, we could use the replacement +// and remove setNextjsPrebundledReact where we need to +// It would be handy to change the plugin to allow delete without having to create a replacement file //#override handler export const handler: PluginHandler = async ( req: IncomingMessage, diff --git a/packages/open-next/src/adapters/plugins/util.replacement.ts b/packages/open-next/src/adapters/plugins/util.replacement.ts index 6d44b404..585b9617 100644 --- a/packages/open-next/src/adapters/plugins/util.replacement.ts +++ b/packages/open-next/src/adapters/plugins/util.replacement.ts @@ -1,4 +1,4 @@ -import { NextConfig } from "../config"; +import { NextConfig } from "config/index"; //#override requestHandler // @ts-ignore diff --git a/packages/open-next/src/adapters/plugins/util.ts b/packages/open-next/src/adapters/plugins/util.ts index 5f846897..373cc48c 100644 --- a/packages/open-next/src/adapters/plugins/util.ts +++ b/packages/open-next/src/adapters/plugins/util.ts @@ -1,20 +1,20 @@ import fs from "node:fs"; import path from "node:path"; -// @ts-ignore -import NextServer from "next/dist/server/next-server.js"; - import { AppPathsManifestKeys, NextConfig, RoutesManifest, -} from "../config/index.js"; +} from "config/index.js"; +// @ts-ignore +import NextServer from "next/dist/server/next-server.js"; +import type { MiddlewareManifest } from "types/next-types.js"; + import { debug } from "../logger.js"; import { applyOverride as applyNextjsRequireHooksOverride, overrideHooks as overrideNextjsRequireHooks, } from "../require-hooks.js"; -import { MiddlewareManifest } from "../types/next-types.js"; // WORKAROUND: Set `__NEXT_PRIVATE_PREBUNDLED_REACT` to use prebundled React — https://github.com/serverless-stack/open-next#workaround-set-__next_private_prebundled_react-to-use-prebundled-react // Step 1: Need to override the require hooks for React before Next.js server diff --git a/packages/open-next/src/adapters/require-hooks.ts b/packages/open-next/src/adapters/require-hooks.ts index 255fe2f0..2dfb27dc 100644 --- a/packages/open-next/src/adapters/require-hooks.ts +++ b/packages/open-next/src/adapters/require-hooks.ts @@ -2,8 +2,9 @@ // This is needed for userland plugins to attach to the same webpack instance as Next.js'. // Individually compiled modules are as defined for the compilation in bundles/webpack/packages/*. +import type { NextConfig } from "types/next-types.js"; + import { error } from "./logger.js"; -import type { NextConfig } from "./types/next-types.js"; // This module will only be loaded once per process. diff --git a/packages/open-next/src/adapters/server-adapter.ts b/packages/open-next/src/adapters/server-adapter.ts index cd9108bd..3fa6df50 100644 --- a/packages/open-next/src/adapters/server-adapter.ts +++ b/packages/open-next/src/adapters/server-adapter.ts @@ -1,7 +1,8 @@ -import { createMainHandler } from "../core/createMainHandler.js"; // We load every config here so that they are only loaded once // and during cold starts -import { BuildId } from "./config/index.js"; +import { BuildId } from "config/index.js"; + +import { createMainHandler } from "../core/createMainHandler.js"; import { setNodeEnv } from "./util.js"; // We load every config here so that they are only loaded once diff --git a/packages/open-next/src/adapters/util.ts b/packages/open-next/src/adapters/util.ts index 62cd2d79..d35545e8 100644 --- a/packages/open-next/src/adapters/util.ts +++ b/packages/open-next/src/adapters/util.ts @@ -1,3 +1,5 @@ +//TODO: We should probably move all the utils to a separate location + export function setNodeEnv() { process.env.NODE_ENV = process.env.NODE_ENV ?? "production"; } @@ -6,39 +8,6 @@ export function generateUniqueId() { return Math.random().toString(36).slice(2, 8); } -export function escapeRegex(str: string) { - let path = str.replace(/\(\.\)/g, "_µ1_"); - - path = path.replace(/\(\.{2}\)/g, "_µ2_"); - - path = path.replace(/\(\.{3}\)/g, "_µ3_"); - - return path; -} - -export function unescapeRegex(str: string) { - let path = str.replace(/_µ1_/g, "(.)"); - - path = path.replace(/_µ2_/g, "(..)"); - - path = path.replace(/_µ3_/g, "(...)"); - - return path; -} - -// AWS cookies are in a single `set-cookie` string, delimited by a comma -export function parseCookies( - cookies?: string | string[], -): string[] | undefined { - if (!cookies) return; - - if (typeof cookies === "string") { - return cookies.split(/(? c.trim()); - } - - return cookies; -} - /** * Create an array of arrays of size `chunkSize` from `items` * @param items Array of T diff --git a/packages/open-next/src/build.ts b/packages/open-next/src/build.ts index 5733d522..0ce6d665 100644 --- a/packages/open-next/src/build.ts +++ b/packages/open-next/src/build.ts @@ -10,10 +10,9 @@ import { buildSync, } from "esbuild"; -import { BuildOptions, DangerousOptions } from "./adapters/types/open-next.js"; -import logger from "./logger.js"; import { minifyAll } from "./minimize-js.js"; import openNextPlugin from "./plugin.js"; +import { BuildOptions, DangerousOptions } from "./types/open-next.js"; const require = topLevelCreateRequire(import.meta.url); const __dirname = url.fileURLToPath(new URL(".", import.meta.url)); diff --git a/packages/open-next/src/converters/aws-apigw-v1.ts b/packages/open-next/src/converters/aws-apigw-v1.ts index 19411ef8..dc275ed0 100644 --- a/packages/open-next/src/converters/aws-apigw-v1.ts +++ b/packages/open-next/src/converters/aws-apigw-v1.ts @@ -1,8 +1,7 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda"; +import type { Converter, InternalEvent, InternalResult } from "types/open-next"; -import { InternalEvent, InternalResult } from "../adapters/event-mapper"; import { debug } from "../adapters/logger"; -import { Converter } from "../adapters/types/open-next"; import { removeUndefinedFromQuery } from "./utils"; function normalizeAPIGatewayProxyEventHeaders( diff --git a/packages/open-next/src/converters/aws-apigw-v2.ts b/packages/open-next/src/converters/aws-apigw-v2.ts index 52a9c815..cd96638a 100644 --- a/packages/open-next/src/converters/aws-apigw-v2.ts +++ b/packages/open-next/src/converters/aws-apigw-v2.ts @@ -1,9 +1,8 @@ import { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from "aws-lambda"; +import { parseCookies } from "http/util"; +import type { Converter, InternalEvent, InternalResult } from "types/open-next"; -import { InternalEvent, InternalResult } from "../adapters/event-mapper"; import { debug } from "../adapters/logger"; -import { Converter } from "../adapters/types/open-next"; -import { parseCookies } from "../adapters/util"; import { removeUndefinedFromQuery } from "./utils"; function normalizeAPIGatewayProxyEventV2Body( diff --git a/packages/open-next/src/converters/aws-cloudfront.ts b/packages/open-next/src/converters/aws-cloudfront.ts index f2560466..b25bcd1c 100644 --- a/packages/open-next/src/converters/aws-cloudfront.ts +++ b/packages/open-next/src/converters/aws-cloudfront.ts @@ -3,10 +3,9 @@ import { CloudFrontRequestEvent, CloudFrontRequestResult, } from "aws-lambda"; +import type { Converter, InternalEvent, InternalResult } from "types/open-next"; -import { InternalEvent, InternalResult } from "../adapters/event-mapper"; import { debug } from "../adapters/logger"; -import { Converter } from "../adapters/types/open-next"; function normalizeCloudFrontRequestEventHeaders( rawHeaders: CloudFrontHeaders, diff --git a/packages/open-next/src/converters/docker.ts b/packages/open-next/src/converters/docker.ts index c2278673..8561aa7a 100644 --- a/packages/open-next/src/converters/docker.ts +++ b/packages/open-next/src/converters/docker.ts @@ -1,8 +1,6 @@ import { IncomingMessage } from "http"; - -import { InternalResult } from "../adapters/event-mapper"; -import { Converter } from "../adapters/types/open-next"; -import { parseCookies } from "../adapters/util"; +import { parseCookies } from "http/util"; +import type { Converter, InternalResult } from "types/open-next"; const converter: Converter = { convertFrom: async (req: IncomingMessage) => { diff --git a/packages/open-next/src/core/createMainHandler.ts b/packages/open-next/src/core/createMainHandler.ts index 2986fd9d..33300624 100644 --- a/packages/open-next/src/core/createMainHandler.ts +++ b/packages/open-next/src/core/createMainHandler.ts @@ -1,9 +1,10 @@ -import { +import type { BuildOptions, Converter, OverrideOptions, Wrapper, -} from "../adapters/types/open-next"; +} from "types/open-next"; + import type { IncrementalCache } from "../cache/incremental/types"; import type { Queue } from "../queue/types"; import { openNextHandler } from "./requestHandler"; diff --git a/packages/open-next/src/core/requestHandler.ts b/packages/open-next/src/core/requestHandler.ts index 7d955680..c2a0b46e 100644 --- a/packages/open-next/src/core/requestHandler.ts +++ b/packages/open-next/src/core/requestHandler.ts @@ -1,10 +1,11 @@ -import { BuildId } from "../adapters/config"; -import { InternalEvent, InternalResult } from "../adapters/event-mapper"; -import { IncomingMessage } from "../adapters/http"; +import { BuildId } from "config/index"; import { + IncomingMessage, OpenNextNodeResponse, StreamCreator, -} from "../adapters/http/openNextResponse"; +} from "http/index.js"; +import { InternalEvent, InternalResult } from "types/open-next"; + import { error } from "../adapters/logger"; import { createServerResponse } from "../adapters/plugins/routing/util"; import { handler as serverHandler } from "../adapters/plugins/serverHandler"; @@ -94,7 +95,7 @@ async function processRequest( }); } catch (e: any) { error("NextJS request failed.", e); - + //TODO: we could return the next 500 page here res.setHeader("Content-Type", "application/json"); res.end( JSON.stringify( diff --git a/packages/open-next/src/core/routing/matcher.ts b/packages/open-next/src/core/routing/matcher.ts index 43aefcbe..41da33e7 100644 --- a/packages/open-next/src/core/routing/matcher.ts +++ b/packages/open-next/src/core/routing/matcher.ts @@ -1,17 +1,22 @@ +import { NextConfig } from "config/index"; import { compile, Match, match, PathFunction } from "path-to-regexp"; - -import { NextConfig } from "../../adapters/config"; -import { InternalEvent, InternalResult } from "../../adapters/event-mapper"; -import { debug } from "../../adapters/logger"; -import { +import type { Header, PrerenderManifest, RedirectDefinition, RewriteDefinition, RouteHas, -} from "../../adapters/types/next-types"; -import { escapeRegex, unescapeRegex } from "../../adapters/util"; -import { convertQuery, getUrlParts, isExternal } from "./util"; +} from "types/next-types"; +import { InternalEvent, InternalResult } from "types/open-next"; + +import { debug } from "../../adapters/logger"; +import { + convertQuery, + escapeRegex, + getUrlParts, + isExternal, + unescapeRegex, +} from "./util"; const routeHasMatcher = ( diff --git a/packages/open-next/src/core/routing/middleware.ts b/packages/open-next/src/core/routing/middleware.ts index c6cff5e0..dc25e60f 100644 --- a/packages/open-next/src/core/routing/middleware.ts +++ b/packages/open-next/src/core/routing/middleware.ts @@ -1,7 +1,8 @@ import path from "node:path"; -import { NEXT_DIR, NextConfig } from "../../adapters/config/index.js"; -import { InternalEvent, InternalResult } from "../../adapters/event-mapper.js"; +import { NEXT_DIR, NextConfig } from "config/index.js"; +import { InternalEvent, InternalResult } from "types/open-next.js"; + //NOTE: we should try to avoid importing stuff from next as much as possible // every release of next could break this // const { run } = require("next/dist/server/web/sandbox"); diff --git a/packages/open-next/src/core/routing/util.ts b/packages/open-next/src/core/routing/util.ts index 7acfbf4c..17d9b6ce 100644 --- a/packages/open-next/src/core/routing/util.ts +++ b/packages/open-next/src/core/routing/util.ts @@ -1,10 +1,11 @@ import fs from "node:fs"; import path from "node:path"; -import { isBinaryContentType } from "../../adapters/binary"; -import { OpenNextNodeResponse } from "../../adapters/http/openNextResponse"; -import { parseHeaders } from "../../adapters/http/util"; -import { MiddlewareManifest } from "../../adapters/types/next-types"; +import { OpenNextNodeResponse } from "http/index.js"; +import { parseHeaders } from "http/util.js"; +import type { MiddlewareManifest } from "types/next-types"; + +import { isBinaryContentType } from "../../adapters/binary.js"; export function isExternal(url?: string, host?: string) { if (!url) return false; @@ -75,3 +76,23 @@ export function loadMiddlewareManifest(nextDir: string) { const json = fs.readFileSync(filePath, "utf-8"); return JSON.parse(json) as MiddlewareManifest; } + +export function escapeRegex(str: string) { + let path = str.replace(/\(\.\)/g, "_µ1_"); + + path = path.replace(/\(\.{2}\)/g, "_µ2_"); + + path = path.replace(/\(\.{3}\)/g, "_µ3_"); + + return path; +} + +export function unescapeRegex(str: string) { + let path = str.replace(/_µ1_/g, "(.)"); + + path = path.replace(/_µ2_/g, "(..)"); + + path = path.replace(/_µ3_/g, "(...)"); + + return path; +} diff --git a/packages/open-next/src/core/routingHandler.ts b/packages/open-next/src/core/routingHandler.ts index fc0d0a98..fa2ab18d 100644 --- a/packages/open-next/src/core/routingHandler.ts +++ b/packages/open-next/src/core/routingHandler.ts @@ -1,5 +1,3 @@ -import type { OutgoingHttpHeaders } from "http"; - //TODO: Replace this with injected values in case of external routing // We could use open-next plugins to replace these values at build time import { @@ -7,8 +5,10 @@ import { ConfigHeaders, PrerenderManifest, RoutesManifest, -} from "../adapters/config"; -import { InternalEvent, InternalResult } from "../adapters/event-mapper"; +} from "config/index"; +import type { OutgoingHttpHeaders } from "http"; +import { InternalEvent, InternalResult } from "types/open-next"; + import { addNextConfigHeaders, fixDataPage, diff --git a/packages/open-next/src/http/index.ts b/packages/open-next/src/http/index.ts new file mode 100644 index 00000000..e7e2b8a4 --- /dev/null +++ b/packages/open-next/src/http/index.ts @@ -0,0 +1,2 @@ +export * from "./openNextResponse.js"; +export * from "./request.js"; diff --git a/packages/open-next/src/adapters/http/openNextResponse.ts b/packages/open-next/src/http/openNextResponse.ts similarity index 97% rename from packages/open-next/src/adapters/http/openNextResponse.ts rename to packages/open-next/src/http/openNextResponse.ts index b986735f..b0d1fafd 100644 --- a/packages/open-next/src/adapters/http/openNextResponse.ts +++ b/packages/open-next/src/http/openNextResponse.ts @@ -1,8 +1,7 @@ import { OutgoingHttpHeader, OutgoingHttpHeaders } from "http"; import { Transform, TransformCallback, Writable } from "stream"; -import { parseCookies } from "../util"; -import { convertHeader, parseHeaders } from "./util"; +import { convertHeader, parseCookies, parseHeaders } from "./util"; const SET_COOKIE_HEADER = "set-cookie"; diff --git a/packages/open-next/src/adapters/http/request.ts b/packages/open-next/src/http/request.ts similarity index 100% rename from packages/open-next/src/adapters/http/request.ts rename to packages/open-next/src/http/request.ts diff --git a/packages/open-next/src/http/util.ts b/packages/open-next/src/http/util.ts new file mode 100644 index 00000000..0e3be5fd --- /dev/null +++ b/packages/open-next/src/http/util.ts @@ -0,0 +1,42 @@ +import http from "node:http"; + +export const parseHeaders = ( + headers?: http.OutgoingHttpHeader[] | http.OutgoingHttpHeaders, +) => { + const result: Record = {}; + if (!headers) { + return result; + } + + for (const [key, value] of Object.entries(headers)) { + if (value === undefined) { + continue; + } else { + result[key] = convertHeader(value); + } + } + + return result; +}; + +export const convertHeader = (header: http.OutgoingHttpHeader) => { + if (typeof header === "string") { + return header; + } else if (Array.isArray(header)) { + return header.join(","); + } else { + return String(header); + } +}; + +export function parseCookies( + cookies?: string | string[], +): string[] | undefined { + if (!cookies) return; + + if (typeof cookies === "string") { + return cookies.split(/(? c.trim()); + } + + return cookies; +} diff --git a/packages/open-next/src/adapters/types/aws-lambda.ts b/packages/open-next/src/types/aws-lambda.ts similarity index 100% rename from packages/open-next/src/adapters/types/aws-lambda.ts rename to packages/open-next/src/types/aws-lambda.ts diff --git a/packages/open-next/src/adapters/types/next-types.ts b/packages/open-next/src/types/next-types.ts similarity index 91% rename from packages/open-next/src/adapters/types/next-types.ts rename to packages/open-next/src/types/next-types.ts index 296be2d3..1221368a 100644 --- a/packages/open-next/src/adapters/types/next-types.ts +++ b/packages/open-next/src/types/next-types.ts @@ -1,9 +1,8 @@ // NOTE: add more next config typings as they become relevant -import { InternalEvent } from "../event-mapper.js"; -import { OpenNextNodeResponse } from "../http/openNextResponse.js"; -import { IncomingMessage } from "../http/request.js"; -import { ServerlessResponse } from "../http/response.js"; +import { IncomingMessage, OpenNextNodeResponse } from "http/index.js"; + +import { InternalEvent } from "./open-next"; type RemotePattern = { protocol?: "http" | "https"; @@ -154,5 +153,5 @@ export interface PluginHandler { req: IncomingMessage, res: OpenNextNodeResponse, options: Options, - ): Promise; + ): Promise; } diff --git a/packages/open-next/src/adapters/types/open-next.ts b/packages/open-next/src/types/open-next.ts similarity index 86% rename from packages/open-next/src/adapters/types/open-next.ts rename to packages/open-next/src/types/open-next.ts index 12abd51a..3c88413e 100644 --- a/packages/open-next/src/adapters/types/open-next.ts +++ b/packages/open-next/src/types/open-next.ts @@ -1,6 +1,26 @@ -import { Queue } from "../../queue/types"; -import { InternalEvent, InternalResult } from "../event-mapper"; -import { StreamCreator } from "../http/openNextResponse"; +import { StreamCreator } from "http/index.js"; + +import { Queue } from "../queue/types"; + +export type InternalEvent = { + readonly type: "v1" | "v2" | "cf"; + readonly method: string; + readonly rawPath: string; + readonly url: string; + readonly body: Buffer; + readonly headers: Record; + readonly query: Record; + readonly cookies: Record; + readonly remoteAddress: string; +}; + +export type InternalResult = { + readonly type: "v1" | "v2" | "cf"; + statusCode: number; + headers: Record; + body: string; + isBase64Encoded: boolean; +}; export interface DangerousOptions { /** diff --git a/packages/open-next/src/adapters/types/plugin.ts b/packages/open-next/src/types/plugin.ts similarity index 81% rename from packages/open-next/src/adapters/types/plugin.ts rename to packages/open-next/src/types/plugin.ts index a2ece3e9..22fd00e8 100644 --- a/packages/open-next/src/adapters/types/plugin.ts +++ b/packages/open-next/src/types/plugin.ts @@ -1,6 +1,6 @@ -import type { InternalEvent, InternalResult } from "../event-mapper"; -import { OpenNextNodeResponse } from "../http/openNextResponse"; -import type { IncomingMessage } from "../http/request"; +import { IncomingMessage, OpenNextNodeResponse } from "http/index.js"; + +import { InternalEvent, InternalResult } from "./open-next"; export type ProcessInternalEventResult = | { diff --git a/packages/open-next/src/wrappers/aws-lambda-streaming.ts b/packages/open-next/src/wrappers/aws-lambda-streaming.ts index a1a61e36..198ee8c1 100644 --- a/packages/open-next/src/wrappers/aws-lambda-streaming.ts +++ b/packages/open-next/src/wrappers/aws-lambda-streaming.ts @@ -2,11 +2,10 @@ import { Writable } from "node:stream"; import zlib from "node:zlib"; import { APIGatewayProxyEventV2 } from "aws-lambda"; +import { StreamCreator } from "http/index.js"; +import { parseCookies, parseHeaders } from "http/util.js"; +import { Wrapper } from "types/open-next"; -import { StreamCreator } from "../adapters/http/openNextResponse"; -import { parseHeaders } from "../adapters/http/util"; -import { Wrapper } from "../adapters/types/open-next"; -import { parseCookies } from "../adapters/util"; import { WarmerEvent } from "../adapters/warmer-function"; type AwsLambdaEvent = APIGatewayProxyEventV2 | WarmerEvent; diff --git a/packages/open-next/src/wrappers/aws-lambda.ts b/packages/open-next/src/wrappers/aws-lambda.ts index 709843ec..ba002852 100644 --- a/packages/open-next/src/wrappers/aws-lambda.ts +++ b/packages/open-next/src/wrappers/aws-lambda.ts @@ -1,4 +1,4 @@ -import { +import type { APIGatewayProxyEvent, APIGatewayProxyEventV2, APIGatewayProxyResult, @@ -6,8 +6,8 @@ import { CloudFrontRequestEvent, CloudFrontRequestResult, } from "aws-lambda"; +import type { Wrapper } from "types/open-next"; -import { Wrapper } from "../adapters/types/open-next"; import { WarmerEvent } from "../adapters/warmer-function"; type AwsLambdaEvent = diff --git a/packages/open-next/src/wrappers/docker.ts b/packages/open-next/src/wrappers/docker.ts index cb36c66a..1908d2f2 100644 --- a/packages/open-next/src/wrappers/docker.ts +++ b/packages/open-next/src/wrappers/docker.ts @@ -1,9 +1,9 @@ import debug from "debug"; import { createServer } from "http"; +import { StreamCreator } from "http/index.js"; +import type { Wrapper } from "types/open-next"; -import { StreamCreator } from "../adapters/http/openNextResponse"; import { error } from "../adapters/logger"; -import { Wrapper } from "../adapters/types/open-next"; const wrapper: Wrapper = async (handler, converter) => { const server = createServer(async (req, res) => { diff --git a/packages/open-next/tsconfig.json b/packages/open-next/tsconfig.json index 6d832295..c4c987fd 100644 --- a/packages/open-next/tsconfig.json +++ b/packages/open-next/tsconfig.json @@ -5,6 +5,11 @@ "module": "esnext", "lib": ["DOM", "ESNext"], "outDir": "./dist", - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "paths": { + "types/*": ["./src/types/*"], + "config/*": ["./src/adapters/config/*"], + "http/*": ["./src/http/*"], + } } }