@opennextjs/aws 3.2.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +15 -1
  2. package/dist/adapters/cache.d.ts +1 -23
  3. package/dist/adapters/cache.js +22 -18
  4. package/dist/adapters/config/index.js +1 -1
  5. package/dist/adapters/config/util.js +2 -2
  6. package/dist/adapters/dynamo-provider.js +3 -5
  7. package/dist/adapters/edge-adapter.d.ts +0 -3
  8. package/dist/adapters/edge-adapter.js +43 -38
  9. package/dist/adapters/image-optimization-adapter.js +4 -4
  10. package/dist/adapters/logger.d.ts +0 -3
  11. package/dist/adapters/logger.js +3 -5
  12. package/dist/adapters/middleware.js +42 -18
  13. package/dist/adapters/plugins/image-optimization/image-optimization.d.ts +0 -3
  14. package/dist/adapters/plugins/image-optimization/image-optimization.replacement.d.ts +0 -3
  15. package/dist/adapters/revalidate.js +2 -2
  16. package/dist/adapters/server-adapter.d.ts +0 -3
  17. package/dist/adapters/server-adapter.js +3 -1
  18. package/dist/adapters/util.js +2 -2
  19. package/dist/build/bundleNextServer.d.ts +3 -1
  20. package/dist/build/bundleNextServer.js +3 -3
  21. package/dist/build/compileConfig.js +3 -3
  22. package/dist/build/copyTracedFiles.js +16 -27
  23. package/dist/build/createAssets.js +35 -26
  24. package/dist/build/createImageOptimizationBundle.js +4 -1
  25. package/dist/build/createMiddleware.d.ts +4 -4
  26. package/dist/build/createMiddleware.js +16 -19
  27. package/dist/build/createRevalidationBundle.js +1 -1
  28. package/dist/build/createServerBundle.js +34 -45
  29. package/dist/build/createWarmerBundle.js +1 -1
  30. package/dist/build/edge/createEdgeBundle.d.ts +9 -7
  31. package/dist/build/edge/createEdgeBundle.js +19 -14
  32. package/dist/build/generateOutput.js +7 -13
  33. package/dist/build/helper.d.ts +22 -4
  34. package/dist/build/helper.js +26 -12
  35. package/dist/build/installDeps.js +12 -2
  36. package/dist/build/patch/patchedAsyncStorage.js +1 -1
  37. package/dist/build/utils.js +3 -2
  38. package/dist/build/validateConfig.js +1 -0
  39. package/dist/core/createGenericHandler.d.ts +2 -4
  40. package/dist/core/createGenericHandler.js +6 -7
  41. package/dist/core/createMainHandler.d.ts +0 -17
  42. package/dist/core/createMainHandler.js +10 -9
  43. package/dist/core/edgeFunctionHandler.d.ts +1 -51
  44. package/dist/core/patchAsyncStorage.js +5 -6
  45. package/dist/core/requestHandler.js +98 -89
  46. package/dist/core/require-hooks.js +8 -7
  47. package/dist/core/resolve.d.ts +13 -7
  48. package/dist/core/resolve.js +29 -35
  49. package/dist/core/routing/cacheInterceptor.js +12 -13
  50. package/dist/core/routing/i18n/accept-header.js +3 -2
  51. package/dist/core/routing/matcher.d.ts +2 -4
  52. package/dist/core/routing/matcher.js +29 -31
  53. package/dist/core/routing/middleware.js +22 -18
  54. package/dist/core/routing/util.d.ts +0 -13
  55. package/dist/core/routing/util.js +32 -91
  56. package/dist/core/routingHandler.d.ts +2 -0
  57. package/dist/core/routingHandler.js +30 -12
  58. package/dist/core/util.js +5 -3
  59. package/dist/helpers/withSST.d.ts +1 -1
  60. package/dist/http/openNextResponse.d.ts +5 -9
  61. package/dist/http/openNextResponse.js +29 -31
  62. package/dist/http/request.d.ts +0 -3
  63. package/dist/http/request.js +4 -2
  64. package/dist/http/util.d.ts +1 -1
  65. package/dist/http/util.js +8 -12
  66. package/dist/minimize-js.js +19 -19
  67. package/dist/overrides/converters/aws-apigw-v1.d.ts +2 -2
  68. package/dist/overrides/converters/aws-apigw-v1.js +2 -1
  69. package/dist/overrides/converters/aws-apigw-v2.d.ts +2 -2
  70. package/dist/overrides/converters/aws-apigw-v2.js +6 -7
  71. package/dist/overrides/converters/aws-cloudfront.d.ts +2 -2
  72. package/dist/overrides/converters/aws-cloudfront.js +11 -30
  73. package/dist/overrides/converters/dummy.d.ts +1 -1
  74. package/dist/overrides/converters/edge.d.ts +5 -1
  75. package/dist/overrides/converters/edge.js +16 -17
  76. package/dist/overrides/converters/node.d.ts +1 -1
  77. package/dist/overrides/converters/node.js +1 -1
  78. package/dist/overrides/converters/sqs-revalidate.d.ts +1 -1
  79. package/dist/overrides/imageLoader/dummy.d.ts +1 -1
  80. package/dist/overrides/imageLoader/host.d.ts +1 -1
  81. package/dist/overrides/imageLoader/s3.d.ts +1 -1
  82. package/dist/overrides/imageLoader/s3.js +1 -1
  83. package/dist/overrides/incrementalCache/dummy.d.ts +1 -1
  84. package/dist/overrides/incrementalCache/s3-lite.d.ts +1 -1
  85. package/dist/overrides/incrementalCache/s3-lite.js +15 -19
  86. package/dist/overrides/incrementalCache/s3.d.ts +1 -1
  87. package/dist/overrides/incrementalCache/s3.js +1 -1
  88. package/dist/overrides/originResolver/dummy.d.ts +1 -1
  89. package/dist/overrides/originResolver/pattern-env.d.ts +1 -1
  90. package/dist/overrides/originResolver/pattern-env.js +10 -11
  91. package/dist/overrides/proxyExternalRequest/dummy.d.ts +3 -0
  92. package/dist/overrides/proxyExternalRequest/dummy.js +7 -0
  93. package/dist/overrides/proxyExternalRequest/fetch.d.ts +3 -0
  94. package/dist/overrides/proxyExternalRequest/fetch.js +25 -0
  95. package/dist/overrides/proxyExternalRequest/node.d.ts +3 -0
  96. package/dist/overrides/proxyExternalRequest/node.js +67 -0
  97. package/dist/overrides/queue/dummy.d.ts +1 -1
  98. package/dist/overrides/queue/sqs-lite.d.ts +1 -1
  99. package/dist/overrides/queue/sqs-lite.js +7 -9
  100. package/dist/overrides/queue/sqs.d.ts +1 -1
  101. package/dist/overrides/queue/sqs.js +1 -1
  102. package/dist/overrides/tagCache/constants.js +2 -2
  103. package/dist/overrides/tagCache/dummy.d.ts +1 -1
  104. package/dist/overrides/tagCache/dynamodb-lite.d.ts +1 -1
  105. package/dist/overrides/tagCache/dynamodb-lite.js +10 -12
  106. package/dist/overrides/tagCache/dynamodb.d.ts +1 -1
  107. package/dist/overrides/tagCache/dynamodb.js +2 -2
  108. package/dist/overrides/warmer/aws-lambda.d.ts +1 -1
  109. package/dist/overrides/warmer/dummy.d.ts +1 -1
  110. package/dist/overrides/wrappers/aws-lambda-streaming.d.ts +2 -2
  111. package/dist/overrides/wrappers/aws-lambda.d.ts +2 -2
  112. package/dist/overrides/wrappers/cloudflare.d.ts +2 -1
  113. package/dist/overrides/wrappers/cloudflare.js +21 -3
  114. package/dist/overrides/wrappers/dummy.d.ts +2 -2
  115. package/dist/overrides/wrappers/node.d.ts +2 -2
  116. package/dist/overrides/wrappers/node.js +3 -3
  117. package/dist/plugins/edge.d.ts +3 -2
  118. package/dist/plugins/edge.js +33 -34
  119. package/dist/plugins/replacement.d.ts +1 -1
  120. package/dist/plugins/replacement.js +5 -6
  121. package/dist/plugins/resolve.d.ts +3 -1
  122. package/dist/plugins/resolve.js +4 -1
  123. package/dist/types/aws-lambda.d.ts +2 -5
  124. package/dist/types/cache.d.ts +0 -2
  125. package/dist/types/global.d.ts +188 -0
  126. package/dist/types/next-types.d.ts +1 -3
  127. package/dist/types/open-next.d.ts +24 -45
  128. package/dist/types/overrides.d.ts +87 -0
  129. package/dist/utils/promise.d.ts +3 -0
  130. package/dist/utils/promise.js +44 -0
  131. package/dist/utils/stream.d.ts +0 -1
  132. package/package.json +2 -2
  133. package/dist/adapters/plugins/without-routing/requestHandler.d.ts +0 -2
  134. package/dist/adapters/plugins/without-routing/requestHandler.js +0 -10
  135. package/dist/overrides/incrementalCache/types.d.ts +0 -34
  136. package/dist/overrides/queue/types.d.ts +0 -12
  137. package/dist/overrides/tagCache/types.d.ts +0 -11
  138. package/dist/overrides/tagCache/types.js +0 -1
  139. /package/dist/{overrides/incrementalCache/types.js → types/global.js} +0 -0
  140. /package/dist/{overrides/queue/types.js → types/overrides.js} +0 -0
@@ -6,15 +6,11 @@ async function canStream(opts) {
6
6
  if (!opts.override?.wrapper) {
7
7
  return false;
8
8
  }
9
- else {
10
- if (typeof opts.override.wrapper === "string") {
11
- return opts.override.wrapper === "aws-lambda-streaming";
12
- }
13
- else {
14
- const wrapper = await opts.override.wrapper();
15
- return wrapper.supportStreaming;
16
- }
9
+ if (typeof opts.override.wrapper === "string") {
10
+ return opts.override.wrapper === "aws-lambda-streaming";
17
11
  }
12
+ const wrapper = await opts.override.wrapper();
13
+ return wrapper.supportStreaming;
18
14
  }
19
15
  async function extractOverrideName(defaultName, override) {
20
16
  if (!override) {
@@ -23,10 +19,8 @@ async function extractOverrideName(defaultName, override) {
23
19
  if (typeof override === "string") {
24
20
  return override;
25
21
  }
26
- else {
27
- const overrideModule = await override();
28
- return overrideModule.name;
29
- }
22
+ const overrideModule = await override();
23
+ return overrideModule.name;
30
24
  }
31
25
  async function extractOverrideFn(override) {
32
26
  if (!override) {
@@ -190,7 +184,7 @@ export async function generateOutput(options) {
190
184
  edgeFunction: isExternalMiddleware ? "middleware" : undefined,
191
185
  });
192
186
  behaviors.push({
193
- pattern: "*",
187
+ pattern: "*", // This is the default behavior
194
188
  origin: "default",
195
189
  edgeFunction: isExternalMiddleware ? "middleware" : undefined,
196
190
  });
@@ -19,15 +19,33 @@ export declare function normalizeOptions(config: OpenNextConfig, distDir: string
19
19
  };
20
20
  export declare function esbuildSync(esbuildOptions: ESBuildOptions, options: BuildOptions): void;
21
21
  export declare function esbuildAsync(esbuildOptions: ESBuildOptions, options: BuildOptions): Promise<void>;
22
- export declare function removeFiles(root: string, conditionFn: (file: string) => boolean, searchingDir?: string): void;
22
+ /**
23
+ * Type of the parameter of `traverseFiles` callbacks
24
+ */
25
+ export type TraversePath = {
26
+ absolutePath: string;
27
+ relativePath: string;
28
+ };
23
29
  /**
24
30
  * Recursively traverse files in a directory and call `callbackFn` when `conditionFn` returns true
31
+ *
32
+ * The callbacks are passed both the absolute and relative (to root) path to files.
33
+ *
25
34
  * @param root - Root directory to search
26
- * @param conditionFn - Called to determine if `callbackFn` should be called
27
- * @param callbackFn - Called when `conditionFn` returns true
35
+ * @param conditionFn - Called to determine if `callbackFn` should be called.
36
+ * @param callbackFn - Called when `conditionFn` returns true.
28
37
  * @param searchingDir - Directory to search (used for recursion)
29
38
  */
30
- export declare function traverseFiles(root: string, conditionFn: (file: string) => boolean, callbackFn: (filePath: string) => void, searchingDir?: string): void;
39
+ export declare function traverseFiles(root: string, conditionFn: (paths: TraversePath) => boolean, callbackFn: (paths: TraversePath) => void, searchingDir?: string): void;
40
+ /**
41
+ * Recursively delete files.
42
+ *
43
+ * @see `traverseFiles`.
44
+ *
45
+ * @param root Root directory to search.
46
+ * @param conditionFn Predicate used to delete the files.
47
+ */
48
+ export declare function removeFiles(root: string, conditionFn: (paths: TraversePath) => boolean): void;
31
49
  export declare function getHtmlPages(dotNextPath: string): Set<string>;
32
50
  export declare function getBuildId(dotNextPath: string): string;
33
51
  export declare function getOpenNextVersion(): string;
@@ -74,7 +74,7 @@ export function esbuildSync(esbuildOptions, options) {
74
74
  format: "esm",
75
75
  platform: "node",
76
76
  bundle: true,
77
- minify: debug ? false : true,
77
+ minify: !debug,
78
78
  mainFields: ["module", "main"],
79
79
  sourcemap: debug ? "inline" : false,
80
80
  sourcesContent: false,
@@ -101,7 +101,7 @@ export async function esbuildAsync(esbuildOptions, options) {
101
101
  format: "esm",
102
102
  platform: "node",
103
103
  bundle: true,
104
- minify: debug ? false : true,
104
+ minify: !debug,
105
105
  mainFields: ["module", "main"],
106
106
  sourcemap: debug ? "inline" : false,
107
107
  sourcesContent: false,
@@ -125,28 +125,40 @@ export async function esbuildAsync(esbuildOptions, options) {
125
125
  throw new Error(`There was a problem bundling ${esbuildOptions.entryPoints[0]}.`);
126
126
  }
127
127
  }
128
- export function removeFiles(root, conditionFn, searchingDir = "") {
129
- traverseFiles(root, conditionFn, (filePath) => fs.rmSync(filePath, { force: true }), searchingDir);
130
- }
131
128
  /**
132
129
  * Recursively traverse files in a directory and call `callbackFn` when `conditionFn` returns true
130
+ *
131
+ * The callbacks are passed both the absolute and relative (to root) path to files.
132
+ *
133
133
  * @param root - Root directory to search
134
- * @param conditionFn - Called to determine if `callbackFn` should be called
135
- * @param callbackFn - Called when `conditionFn` returns true
134
+ * @param conditionFn - Called to determine if `callbackFn` should be called.
135
+ * @param callbackFn - Called when `conditionFn` returns true.
136
136
  * @param searchingDir - Directory to search (used for recursion)
137
137
  */
138
138
  export function traverseFiles(root, conditionFn, callbackFn, searchingDir = "") {
139
139
  fs.readdirSync(path.join(root, searchingDir)).forEach((file) => {
140
- const filePath = path.join(root, searchingDir, file);
141
- if (fs.statSync(filePath).isDirectory()) {
142
- traverseFiles(root, conditionFn, callbackFn, path.join(searchingDir, file));
140
+ const relativePath = path.join(searchingDir, file);
141
+ const absolutePath = path.join(root, relativePath);
142
+ if (fs.statSync(absolutePath).isDirectory()) {
143
+ traverseFiles(root, conditionFn, callbackFn, relativePath);
143
144
  return;
144
145
  }
145
- if (conditionFn(path.join(searchingDir, file))) {
146
- callbackFn(filePath);
146
+ if (conditionFn({ absolutePath, relativePath })) {
147
+ callbackFn({ absolutePath, relativePath });
147
148
  }
148
149
  });
149
150
  }
151
+ /**
152
+ * Recursively delete files.
153
+ *
154
+ * @see `traverseFiles`.
155
+ *
156
+ * @param root Root directory to search.
157
+ * @param conditionFn Predicate used to delete the files.
158
+ */
159
+ export function removeFiles(root, conditionFn) {
160
+ traverseFiles(root, conditionFn, ({ absolutePath }) => fs.rmSync(absolutePath, { force: true }));
161
+ }
150
162
  export function getHtmlPages(dotNextPath) {
151
163
  // Get a list of HTML pages
152
164
  //
@@ -187,9 +199,11 @@ export function compareSemver(v1, v2) {
187
199
  if (v1 === "latest")
188
200
  return 1;
189
201
  if (/^[^\d]/.test(v1)) {
202
+ // biome-ignore lint/style/noParameterAssign:
190
203
  v1 = v1.substring(1);
191
204
  }
192
205
  if (/^[^\d]/.test(v2)) {
206
+ // biome-ignore lint/style/noParameterAssign:
193
207
  v2 = v2.substring(1);
194
208
  }
195
209
  const [major1, minor1, patch1] = v1.split(".").map(Number);
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
- import { execSync } from "child_process";
4
+ import { execSync } from "node:child_process";
5
5
  import logger from "../logger.js";
6
6
  export function installDependencies(outputDir, installOptions) {
7
7
  try {
@@ -14,7 +14,17 @@ export function installDependencies(outputDir, installOptions) {
14
14
  logger.info(`Installing dependencies for ${name}...`);
15
15
  // We then need to run install in the tempDir
16
16
  // We don't install in the output dir directly because it could contain a package.json, and npm would then try to reinstall not complete deps from tracing the files
17
- const installCommand = `npm install --arch=${installOptions.arch ?? "arm64"} --platform=linux --target=${installOptions.nodeVersion ?? "18"} --libc=${installOptions.libc ?? "glibc"} ${installOptions.packages.join(" ")}`;
17
+ const archOption = installOptions.arch
18
+ ? `--arch=${installOptions.arch}`
19
+ : "";
20
+ const targetOption = installOptions.nodeVersion
21
+ ? `--target=${installOptions.nodeVersion}`
22
+ : "";
23
+ const libcOption = installOptions.libc
24
+ ? `--libc=${installOptions.libc}`
25
+ : "";
26
+ const additionalArgs = installOptions.additionalArgs ?? "";
27
+ const installCommand = `npm install --platform=linux ${archOption} ${targetOption} ${libcOption} ${additionalArgs} ${installOptions.packages.join(" ")}`;
18
28
  execSync(installCommand, {
19
29
  stdio: "pipe",
20
30
  cwd: tempInstallDir,
@@ -8,7 +8,7 @@ const staticGenerationAsyncStorage = {
8
8
  if (store) {
9
9
  store.isOnDemandRevalidate =
10
10
  store.isOnDemandRevalidate &&
11
- !globalThis.__als.getStore().isISRRevalidation;
11
+ !globalThis.__openNextAls.getStore().isISRRevalidation;
12
12
  }
13
13
  return store;
14
14
  },
@@ -1,12 +1,13 @@
1
1
  import os from "node:os";
2
2
  import logger from "../logger.js";
3
3
  export function printHeader(header) {
4
+ // biome-ignore lint/style/noParameterAssign:
4
5
  header = `OpenNext — ${header}`;
5
6
  logger.info([
6
7
  "",
7
- "┌" + "─".repeat(header.length + 2) + "┐",
8
+ `┌${"─".repeat(header.length + 2)}┐`,
8
9
  `│ ${header} │`,
9
- "└" + "─".repeat(header.length + 2) + "┘",
10
+ `└${"─".repeat(header.length + 2)}┘`,
10
11
  "",
11
12
  ].join("\n"));
12
13
  }
@@ -9,6 +9,7 @@ const compatibilityMatrix = {
9
9
  "aws-lambda-streaming": ["aws-apigw-v2"],
10
10
  cloudflare: ["edge"],
11
11
  node: ["node"],
12
+ dummy: [],
12
13
  };
13
14
  function validateFunctionOptions(fnOptions) {
14
15
  if (fnOptions.runtime === "edge" && fnOptions.experimentalBundledNextServer) {
@@ -1,7 +1,5 @@
1
- import type { BaseEventOrResult, InternalEvent, InternalResult, OpenNextConfig, OpenNextHandler } from "../types/open-next";
2
- declare global {
3
- var openNextConfig: Partial<OpenNextConfig>;
4
- }
1
+ import type { BaseEventOrResult, InternalEvent, InternalResult } from "../types/open-next";
2
+ import type { OpenNextHandler } from "../types/overrides";
5
3
  type HandlerType = "imageOptimization" | "revalidate" | "warmer" | "middleware" | "initializationFunction";
6
4
  type GenericHandler<Type extends HandlerType, E extends BaseEventOrResult = InternalEvent, R extends BaseEventOrResult = InternalResult> = {
7
5
  handler: OpenNextHandler<E, R>;
@@ -1,16 +1,15 @@
1
1
  import { debug } from "../adapters/logger";
2
2
  import { resolveConverter, resolveWrapper } from "./resolve";
3
3
  export async function createGenericHandler(handler) {
4
- //First we load the config
5
- // @ts-expect-error
4
+ // @ts-expect-error `./open-next.config.mjs` exists only in the build output
6
5
  const config = await import("./open-next.config.mjs").then((m) => m.default);
7
6
  globalThis.openNextConfig = config;
8
7
  const override = config[handler.type]
9
8
  ?.override;
10
- // From the config, we create the adapter
11
- const adapter = await resolveConverter(override?.converter);
9
+ // From the config, we create the converter
10
+ const converter = await resolveConverter(override?.converter);
12
11
  // Then we create the handler
13
- const wrapper = await resolveWrapper(override?.wrapper);
14
- debug("Using wrapper", wrapper.name);
15
- return wrapper.wrapper(handler.handler, adapter);
12
+ const { name, wrapper } = await resolveWrapper(override?.wrapper);
13
+ debug("Using wrapper", name);
14
+ return wrapper(handler.handler, converter);
16
15
  }
@@ -1,18 +1 @@
1
- /// <reference types="node" />
2
- import type { AsyncLocalStorage } from "node:async_hooks";
3
- import type { DetachedPromiseRunner } from "../utils/promise";
4
- import type { IncrementalCache } from "../overrides/incrementalCache/types";
5
- import type { Queue } from "../overrides/queue/types";
6
- declare global {
7
- var queue: Queue;
8
- var incrementalCache: IncrementalCache;
9
- var fnName: string | undefined;
10
- var serverId: string;
11
- var __als: AsyncLocalStorage<{
12
- requestId: string;
13
- pendingPromiseRunner: DetachedPromiseRunner;
14
- isISRRevalidation?: boolean;
15
- mergeHeadersPriority?: "middleware" | "handler";
16
- }>;
17
- }
18
1
  export declare function createMainHandler(): Promise<(...args: any[]) => any>;
@@ -1,10 +1,10 @@
1
1
  import { debug } from "../adapters/logger";
2
2
  import { generateUniqueId } from "../adapters/util";
3
- import { openNextHandler } from "./requestHandler.js";
4
- import { resolveConverter, resolveIncrementalCache, resolveQueue, resolveTagCache, resolveWrapper, } from "./resolve";
3
+ import { openNextHandler } from "./requestHandler";
4
+ import { resolveConverter, resolveIncrementalCache, resolveProxyRequest, resolveQueue, resolveTagCache, resolveWrapper, } from "./resolve";
5
5
  export async function createMainHandler() {
6
- //First we load the config
7
- const config = await import(process.cwd() + "/open-next.config.mjs").then((m) => m.default);
6
+ // @ts-expect-error `./open-next.config.mjs` exists only in the build output
7
+ const config = await import("./open-next.config.mjs").then((m) => m.default);
8
8
  const thisFunction = globalThis.fnName
9
9
  ? config.functions[globalThis.fnName]
10
10
  : config.default;
@@ -14,11 +14,12 @@ export async function createMainHandler() {
14
14
  globalThis.queue = await resolveQueue(thisFunction.override?.queue);
15
15
  globalThis.incrementalCache = await resolveIncrementalCache(thisFunction.override?.incrementalCache);
16
16
  globalThis.tagCache = await resolveTagCache(thisFunction.override?.tagCache);
17
+ globalThis.proxyExternalRequest = await resolveProxyRequest(thisFunction.override?.proxyExternalRequest);
17
18
  globalThis.lastModified = {};
18
- // From the config, we create the adapter
19
- const adapter = await resolveConverter(thisFunction.override?.converter);
19
+ // From the config, we create the converter
20
+ const converter = await resolveConverter(thisFunction.override?.converter);
20
21
  // Then we create the handler
21
- const wrapper = await resolveWrapper(thisFunction.override?.wrapper);
22
- debug("Using wrapper", wrapper.name);
23
- return wrapper.wrapper(openNextHandler, adapter);
22
+ const { wrapper, name } = await resolveWrapper(thisFunction.override?.wrapper);
23
+ debug("Using wrapper", name);
24
+ return wrapper(openNextHandler, converter);
24
25
  }
@@ -1,54 +1,4 @@
1
- /// <reference types="node" />
2
- import type { OutgoingHttpHeaders } from "http";
3
- interface RequestData {
4
- geo?: {
5
- city?: string;
6
- country?: string;
7
- region?: string;
8
- latitude?: string;
9
- longitude?: string;
10
- };
11
- headers: OutgoingHttpHeaders;
12
- ip?: string;
13
- method: string;
14
- nextConfig?: {
15
- basePath?: string;
16
- i18n?: any;
17
- trailingSlash?: boolean;
18
- };
19
- page?: {
20
- name?: string;
21
- params?: {
22
- [key: string]: string | string[];
23
- };
24
- };
25
- url: string;
26
- body?: ReadableStream<Uint8Array>;
27
- signal: AbortSignal;
28
- }
29
- interface Entries {
30
- [k: string]: {
31
- default: (props: {
32
- page: string;
33
- request: RequestData;
34
- }) => Promise<{
35
- response: Response;
36
- waitUntil: Promise<void>;
37
- }>;
38
- };
39
- }
40
- declare global {
41
- var _ENTRIES: Entries;
42
- var _ROUTES: EdgeRoute[];
43
- var __storage__: Map<unknown, unknown>;
44
- var AsyncContext: any;
45
- var AsyncLocalStorage: any;
46
- }
47
- export interface EdgeRoute {
48
- name: string;
49
- page: string;
50
- regex: string[];
51
- }
1
+ import type { RequestData } from "../types/global";
52
2
  type EdgeRequest = Omit<RequestData, "page">;
53
3
  export default function edgeFunctionHandler(request: EdgeRequest): Promise<Response>;
54
4
  export {};
@@ -1,16 +1,15 @@
1
- const mod = require("module");
1
+ const mod = require("node:module");
2
2
  const resolveFilename = mod._resolveFilename;
3
3
  export function patchAsyncStorage() {
4
- mod._resolveFilename = function (originalResolveFilename, request, parent, isMain, options) {
4
+ mod._resolveFilename = ((originalResolveFilename, request, parent, isMain, options) => {
5
5
  if (request.endsWith("static-generation-async-storage.external") ||
6
6
  request.endsWith("static-generation-async-storage.external.js")) {
7
7
  return require.resolve("./patchedAsyncStorage.cjs");
8
8
  }
9
- else if (request.endsWith("static-generation-async-storage.external.original")) {
9
+ if (request.endsWith("static-generation-async-storage.external.original")) {
10
10
  return originalResolveFilename.call(mod, request.replace(".original", ".js"), parent, isMain, options);
11
11
  }
12
- else
13
- return originalResolveFilename.call(mod, request, parent, isMain, options);
12
+ return originalResolveFilename.call(mod, request, parent, isMain, options);
14
13
  // We use `bind` here to avoid referencing outside variables to create potential memory leaks.
15
- }.bind(null, resolveFilename);
14
+ }).bind(null, resolveFilename);
16
15
  }
@@ -1,65 +1,88 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
2
  import { IncomingMessage } from "../http/index.js";
3
- import { DetachedPromiseRunner } from "../utils/promise";
3
+ import { runWithOpenNextRequestContext } from "../utils/promise";
4
4
  import { debug, error, warn } from "../adapters/logger";
5
5
  import { patchAsyncStorage } from "./patchAsyncStorage";
6
- import { convertRes, createServerResponse, proxyRequest } from "./routing/util";
7
- import routingHandler from "./routingHandler";
6
+ import { convertRes, createServerResponse } from "./routing/util";
7
+ import routingHandler, { MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_HEADER_PREFIX_LEN, } from "./routingHandler";
8
8
  import { requestHandler, setNextjsPrebundledReact } from "./util";
9
9
  // This is used to identify requests in the cache
10
- globalThis.__als = new AsyncLocalStorage();
10
+ globalThis.__openNextAls = new AsyncLocalStorage();
11
11
  patchAsyncStorage();
12
12
  export async function openNextHandler(internalEvent, responseStreaming) {
13
- if (internalEvent.headers["x-forwarded-host"]) {
14
- internalEvent.headers.host = internalEvent.headers["x-forwarded-host"];
15
- }
16
- debug("internalEvent", internalEvent);
17
- //#override withRouting
18
- let preprocessResult = {
19
- internalEvent: internalEvent,
20
- isExternalRewrite: false,
21
- origin: false,
22
- isISR: false,
23
- };
24
- try {
25
- preprocessResult = await routingHandler(internalEvent);
26
- }
27
- catch (e) {
28
- warn("Routing failed.", e);
29
- }
30
- //#endOverride
31
- const headers = "type" in preprocessResult
32
- ? preprocessResult.headers
33
- : preprocessResult.internalEvent.headers;
34
- const overwrittenResponseHeaders = Object.entries("type" in preprocessResult
35
- ? preprocessResult.headers
36
- : preprocessResult.internalEvent.headers).reduce((acc, [key, value]) => {
37
- if (!key.startsWith("x-middleware-response-")) {
38
- return acc;
13
+ // We run everything in the async local storage context so that it is available in the middleware as well as in NextServer
14
+ return runWithOpenNextRequestContext({ isISRRevalidation: internalEvent.headers["x-isr"] === "1" }, async () => {
15
+ if (internalEvent.headers["x-forwarded-host"]) {
16
+ internalEvent.headers.host = internalEvent.headers["x-forwarded-host"];
39
17
  }
40
- else {
41
- const newKey = key.replace("x-middleware-response-", "");
42
- delete headers[key];
43
- headers[newKey] = value;
44
- return { ...acc, [newKey]: value };
18
+ debug("internalEvent", internalEvent);
19
+ let preprocessResult = {
20
+ internalEvent: internalEvent,
21
+ isExternalRewrite: false,
22
+ origin: false,
23
+ isISR: false,
24
+ };
25
+ //#override withRouting
26
+ try {
27
+ preprocessResult = await routingHandler(internalEvent);
28
+ }
29
+ catch (e) {
30
+ warn("Routing failed.", e);
45
31
  }
46
- }, {});
47
- if ("type" in preprocessResult) {
48
- // // res is used only in the streaming case
49
- if (responseStreaming) {
50
- const res = createServerResponse(internalEvent, headers, responseStreaming);
51
- res.statusCode = preprocessResult.statusCode;
52
- res.flushHeaders();
53
- const [bodyToConsume, bodyToReturn] = preprocessResult.body.tee();
54
- for await (const chunk of bodyToConsume) {
55
- res.write(chunk);
32
+ //#endOverride
33
+ const headers = "type" in preprocessResult
34
+ ? preprocessResult.headers
35
+ : preprocessResult.internalEvent.headers;
36
+ const overwrittenResponseHeaders = {};
37
+ for (const [rawKey, value] of Object.entries(headers)) {
38
+ if (!rawKey.startsWith(MIDDLEWARE_HEADER_PREFIX)) {
39
+ continue;
56
40
  }
57
- res.end();
58
- preprocessResult.body = bodyToReturn;
41
+ const key = rawKey.slice(MIDDLEWARE_HEADER_PREFIX_LEN);
42
+ overwrittenResponseHeaders[key] = value;
43
+ headers[key] = value;
44
+ delete headers[rawKey];
45
+ }
46
+ if ("isExternalRewrite" in preprocessResult &&
47
+ preprocessResult.isExternalRewrite === true) {
48
+ try {
49
+ preprocessResult = await globalThis.proxyExternalRequest.proxy(preprocessResult.internalEvent);
50
+ }
51
+ catch (e) {
52
+ error("External request failed.", e);
53
+ preprocessResult = {
54
+ internalEvent: {
55
+ type: "core",
56
+ rawPath: "/500",
57
+ method: "GET",
58
+ headers: {},
59
+ url: "/500",
60
+ query: {},
61
+ cookies: {},
62
+ remoteAddress: "",
63
+ },
64
+ // On error we need to rewrite to the 500 page which is an internal rewrite
65
+ isExternalRewrite: false,
66
+ isISR: false,
67
+ origin: false,
68
+ };
69
+ }
70
+ }
71
+ if ("type" in preprocessResult) {
72
+ // response is used only in the streaming case
73
+ if (responseStreaming) {
74
+ const response = createServerResponse(internalEvent, headers, responseStreaming);
75
+ response.statusCode = preprocessResult.statusCode;
76
+ response.flushHeaders();
77
+ const [bodyToConsume, bodyToReturn] = preprocessResult.body.tee();
78
+ for await (const chunk of bodyToConsume) {
79
+ response.write(chunk);
80
+ }
81
+ response.end();
82
+ preprocessResult.body = bodyToReturn;
83
+ }
84
+ return preprocessResult;
59
85
  }
60
- return preprocessResult;
61
- }
62
- else {
63
86
  const preprocessedEvent = preprocessResult.internalEvent;
64
87
  debug("preprocessedEvent", preprocessedEvent);
65
88
  const reqProps = {
@@ -74,58 +97,44 @@ export async function openNextHandler(internalEvent, responseStreaming) {
74
97
  body: preprocessedEvent.body,
75
98
  remoteAddress: preprocessedEvent.remoteAddress,
76
99
  };
77
- const requestId = Math.random().toString(36);
78
- const pendingPromiseRunner = new DetachedPromiseRunner();
79
- const isISRRevalidation = headers["x-isr"] === "1";
80
100
  const mergeHeadersPriority = globalThis.openNextConfig.dangerous
81
101
  ?.headersAndCookiesPriority
82
102
  ? globalThis.openNextConfig.dangerous.headersAndCookiesPriority(preprocessedEvent)
83
103
  : "middleware";
84
- const internalResult = await globalThis.__als.run({
85
- requestId,
86
- pendingPromiseRunner,
87
- isISRRevalidation,
88
- mergeHeadersPriority,
89
- }, async () => {
90
- const preprocessedResult = preprocessResult;
91
- const req = new IncomingMessage(reqProps);
92
- const res = createServerResponse(preprocessedEvent, overwrittenResponseHeaders, responseStreaming);
93
- await processRequest(req, res, preprocessedEvent, preprocessedResult.isExternalRewrite);
94
- const { statusCode, headers, isBase64Encoded, body } = convertRes(res);
95
- const internalResult = {
96
- type: internalEvent.type,
97
- statusCode,
98
- headers,
99
- body,
100
- isBase64Encoded,
101
- };
104
+ const store = globalThis.__openNextAls.getStore();
105
+ if (store) {
106
+ store.mergeHeadersPriority = mergeHeadersPriority;
107
+ }
108
+ const req = new IncomingMessage(reqProps);
109
+ const res = createServerResponse(preprocessedEvent, overwrittenResponseHeaders, responseStreaming);
110
+ await processRequest(req, res, preprocessedEvent);
111
+ const { statusCode, headers: responseHeaders, isBase64Encoded, body, } = convertRes(res);
112
+ const internalResult = {
113
+ type: internalEvent.type,
114
+ statusCode,
115
+ headers: responseHeaders,
116
+ body,
117
+ isBase64Encoded,
118
+ };
119
+ const requestId = store?.requestId;
120
+ if (requestId) {
102
121
  // reset lastModified. We need to do this to avoid memory leaks
103
122
  delete globalThis.lastModified[requestId];
104
- await pendingPromiseRunner.await();
105
- return internalResult;
106
- });
123
+ }
107
124
  return internalResult;
108
- }
125
+ });
109
126
  }
110
- async function processRequest(req, res, internalEvent, isExternalRewrite) {
127
+ async function processRequest(req, res, internalEvent) {
111
128
  // @ts-ignore
112
129
  // Next.js doesn't parse body if the property exists
113
130
  // https://github.com/dougmoscrop/serverless-http/issues/227
114
131
  delete req.body;
115
132
  try {
116
- // `serverHandler` is replaced at build time depending on user's
117
- // nextjs version to patch Nextjs 13.4.x and future breaking changes.
118
- const { rawPath } = internalEvent;
119
- if (isExternalRewrite) {
120
- return proxyRequest(internalEvent, res);
121
- }
122
- else {
123
- //#override applyNextjsPrebundledReact
124
- setNextjsPrebundledReact(rawPath);
125
- //#endOverride
126
- // Next Server
127
- await requestHandler(req, res);
128
- }
133
+ //#override applyNextjsPrebundledReact
134
+ setNextjsPrebundledReact(internalEvent.rawPath);
135
+ //#endOverride
136
+ // Next Server
137
+ await requestHandler(req, res);
129
138
  }
130
139
  catch (e) {
131
140
  // This might fail when using bundled next, importing won't do the trick either