@opennextjs/aws 3.2.1 → 3.3.0

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 (155) hide show
  1. package/README.md +21 -2
  2. package/dist/adapters/cache.d.ts +0 -23
  3. package/dist/adapters/cache.js +10 -12
  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.d.ts +1 -2
  10. package/dist/adapters/image-optimization-adapter.js +4 -4
  11. package/dist/adapters/logger.d.ts +0 -3
  12. package/dist/adapters/logger.js +32 -13
  13. package/dist/adapters/middleware.js +42 -18
  14. package/dist/adapters/plugins/image-optimization/image-optimization.d.ts +1 -3
  15. package/dist/adapters/plugins/image-optimization/image-optimization.js +0 -1
  16. package/dist/adapters/plugins/image-optimization/image-optimization.replacement.d.ts +1 -3
  17. package/dist/adapters/revalidate.js +2 -2
  18. package/dist/adapters/server-adapter.d.ts +0 -3
  19. package/dist/adapters/server-adapter.js +3 -1
  20. package/dist/adapters/util.js +2 -2
  21. package/dist/build/bundleNextServer.d.ts +3 -1
  22. package/dist/build/bundleNextServer.js +3 -3
  23. package/dist/build/compileConfig.js +1 -1
  24. package/dist/build/copyTracedFiles.js +15 -26
  25. package/dist/build/createAssets.js +36 -27
  26. package/dist/build/createImageOptimizationBundle.js +1 -1
  27. package/dist/build/createMiddleware.js +8 -3
  28. package/dist/build/createRevalidationBundle.js +1 -1
  29. package/dist/build/createServerBundle.js +25 -31
  30. package/dist/build/createWarmerBundle.js +1 -1
  31. package/dist/build/edge/createEdgeBundle.d.ts +8 -4
  32. package/dist/build/edge/createEdgeBundle.js +34 -16
  33. package/dist/build/generateOutput.js +7 -13
  34. package/dist/build/helper.d.ts +28 -5
  35. package/dist/build/helper.js +44 -15
  36. package/dist/build/installDeps.js +1 -1
  37. package/dist/build/patch/patchedAsyncStorage.js +1 -1
  38. package/dist/build/utils.js +3 -2
  39. package/dist/build/validateConfig.js +4 -1
  40. package/dist/core/createGenericHandler.d.ts +2 -4
  41. package/dist/core/createGenericHandler.js +1 -2
  42. package/dist/core/createMainHandler.d.ts +0 -17
  43. package/dist/core/createMainHandler.js +5 -4
  44. package/dist/core/edgeFunctionHandler.d.ts +1 -51
  45. package/dist/core/patchAsyncStorage.js +5 -6
  46. package/dist/core/requestHandler.d.ts +1 -2
  47. package/dist/core/requestHandler.js +99 -90
  48. package/dist/core/require-hooks.js +8 -7
  49. package/dist/core/resolve.d.ts +13 -7
  50. package/dist/core/resolve.js +29 -35
  51. package/dist/core/routing/cacheInterceptor.js +12 -13
  52. package/dist/core/routing/i18n/accept-header.js +3 -2
  53. package/dist/core/routing/matcher.d.ts +2 -4
  54. package/dist/core/routing/matcher.js +18 -27
  55. package/dist/core/routing/middleware.d.ts +3 -3
  56. package/dist/core/routing/middleware.js +20 -20
  57. package/dist/core/routing/util.d.ts +2 -15
  58. package/dist/core/routing/util.js +26 -88
  59. package/dist/core/routingHandler.d.ts +4 -8
  60. package/dist/core/routingHandler.js +36 -18
  61. package/dist/core/util.js +5 -3
  62. package/dist/helpers/withCloudflare.d.ts +1 -1
  63. package/dist/helpers/withCloudflare.js +2 -2
  64. package/dist/helpers/withSST.d.ts +1 -1
  65. package/dist/http/openNextResponse.d.ts +6 -18
  66. package/dist/http/openNextResponse.js +32 -32
  67. package/dist/http/request.d.ts +0 -3
  68. package/dist/http/request.js +4 -2
  69. package/dist/http/util.d.ts +1 -1
  70. package/dist/http/util.js +8 -12
  71. package/dist/minimize-js.js +19 -19
  72. package/dist/overrides/converters/aws-apigw-v1.d.ts +2 -2
  73. package/dist/overrides/converters/aws-apigw-v1.js +2 -1
  74. package/dist/overrides/converters/aws-apigw-v2.d.ts +2 -2
  75. package/dist/overrides/converters/aws-apigw-v2.js +8 -8
  76. package/dist/overrides/converters/aws-cloudfront.d.ts +2 -2
  77. package/dist/overrides/converters/aws-cloudfront.js +11 -30
  78. package/dist/overrides/converters/dummy.d.ts +1 -1
  79. package/dist/overrides/converters/edge.d.ts +3 -5
  80. package/dist/overrides/converters/edge.js +15 -18
  81. package/dist/overrides/converters/node.d.ts +1 -1
  82. package/dist/overrides/converters/node.js +1 -1
  83. package/dist/overrides/converters/sqs-revalidate.d.ts +1 -1
  84. package/dist/overrides/imageLoader/dummy.d.ts +1 -1
  85. package/dist/overrides/imageLoader/host.d.ts +1 -1
  86. package/dist/overrides/imageLoader/s3.d.ts +1 -1
  87. package/dist/overrides/imageLoader/s3.js +1 -1
  88. package/dist/overrides/incrementalCache/dummy.d.ts +1 -1
  89. package/dist/overrides/incrementalCache/dummy.js +4 -3
  90. package/dist/overrides/incrementalCache/s3-lite.d.ts +1 -1
  91. package/dist/overrides/incrementalCache/s3-lite.js +15 -19
  92. package/dist/overrides/incrementalCache/s3.d.ts +1 -1
  93. package/dist/overrides/incrementalCache/s3.js +1 -1
  94. package/dist/overrides/originResolver/dummy.d.ts +1 -1
  95. package/dist/overrides/originResolver/pattern-env.d.ts +1 -1
  96. package/dist/overrides/originResolver/pattern-env.js +10 -11
  97. package/dist/overrides/proxyExternalRequest/dummy.d.ts +3 -0
  98. package/dist/overrides/proxyExternalRequest/dummy.js +8 -0
  99. package/dist/overrides/proxyExternalRequest/fetch.d.ts +3 -0
  100. package/dist/overrides/proxyExternalRequest/fetch.js +25 -0
  101. package/dist/overrides/proxyExternalRequest/node.d.ts +3 -0
  102. package/dist/overrides/proxyExternalRequest/node.js +67 -0
  103. package/dist/overrides/queue/dummy.d.ts +1 -1
  104. package/dist/overrides/queue/dummy.js +2 -1
  105. package/dist/overrides/queue/sqs-lite.d.ts +1 -1
  106. package/dist/overrides/queue/sqs-lite.js +7 -9
  107. package/dist/overrides/queue/sqs.d.ts +1 -1
  108. package/dist/overrides/queue/sqs.js +1 -1
  109. package/dist/overrides/tagCache/constants.js +2 -2
  110. package/dist/overrides/tagCache/dummy.d.ts +1 -1
  111. package/dist/overrides/tagCache/dynamodb-lite.d.ts +1 -1
  112. package/dist/overrides/tagCache/dynamodb-lite.js +10 -12
  113. package/dist/overrides/tagCache/dynamodb.d.ts +1 -1
  114. package/dist/overrides/tagCache/dynamodb.js +2 -2
  115. package/dist/overrides/warmer/aws-lambda.d.ts +1 -1
  116. package/dist/overrides/warmer/dummy.d.ts +1 -1
  117. package/dist/overrides/warmer/dummy.js +2 -1
  118. package/dist/overrides/wrappers/aws-lambda-streaming.d.ts +3 -3
  119. package/dist/overrides/wrappers/aws-lambda-streaming.js +0 -4
  120. package/dist/overrides/wrappers/aws-lambda.d.ts +2 -2
  121. package/dist/overrides/wrappers/aws-lambda.js +0 -3
  122. package/dist/overrides/wrappers/cloudflare-edge.d.ts +9 -0
  123. package/dist/overrides/wrappers/cloudflare-edge.js +38 -0
  124. package/dist/overrides/wrappers/cloudflare-node.d.ts +8 -0
  125. package/dist/overrides/wrappers/cloudflare-node.js +47 -0
  126. package/dist/overrides/wrappers/dummy.d.ts +3 -3
  127. package/dist/overrides/wrappers/dummy.js +1 -1
  128. package/dist/overrides/wrappers/node.d.ts +3 -3
  129. package/dist/overrides/wrappers/node.js +3 -6
  130. package/dist/plugins/edge.js +6 -5
  131. package/dist/plugins/replacement.js +2 -2
  132. package/dist/plugins/resolve.d.ts +3 -1
  133. package/dist/plugins/resolve.js +9 -2
  134. package/dist/types/aws-lambda.d.ts +2 -5
  135. package/dist/types/cache.d.ts +0 -2
  136. package/dist/types/global.d.ts +188 -0
  137. package/dist/types/next-types.d.ts +1 -3
  138. package/dist/types/open-next.d.ts +33 -41
  139. package/dist/types/overrides.d.ts +86 -0
  140. package/dist/{adapters → utils}/binary.js +1 -0
  141. package/dist/utils/error.d.ts +1 -0
  142. package/dist/utils/error.js +8 -0
  143. package/dist/utils/promise.d.ts +3 -0
  144. package/dist/utils/promise.js +44 -0
  145. package/dist/utils/stream.d.ts +0 -1
  146. package/package.json +3 -3
  147. package/dist/overrides/incrementalCache/types.d.ts +0 -34
  148. package/dist/overrides/queue/types.d.ts +0 -12
  149. package/dist/overrides/tagCache/types.d.ts +0 -11
  150. package/dist/overrides/tagCache/types.js +0 -1
  151. package/dist/overrides/wrappers/cloudflare.d.ts +0 -11
  152. package/dist/overrides/wrappers/cloudflare.js +0 -20
  153. /package/dist/{overrides/incrementalCache/types.js → types/global.js} +0 -0
  154. /package/dist/{overrides/queue/types.js → types/overrides.js} +0 -0
  155. /package/dist/{adapters → utils}/binary.d.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  import url from "node:url";
2
- import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, readlinkSync, statSync, symlinkSync, writeFileSync, } from "fs";
3
- import path from "path";
2
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, statSync, symlinkSync, writeFileSync, } from "node:fs";
3
+ import path from "node:path";
4
4
  import logger from "../logger.js";
5
5
  const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
6
6
  function copyPatchFile(outputDir) {
@@ -15,9 +15,7 @@ export async function copyTracedFiles(buildOutputPath, packagePath, outputDir, r
15
15
  const standaloneDir = path.join(dotNextDir, "standalone");
16
16
  const standaloneNextDir = path.join(standaloneDir, packagePath, ".next");
17
17
  const outputNextDir = path.join(outputDir, packagePath, ".next");
18
- const extractFiles = (files, from = standaloneNextDir) => {
19
- return files.map((f) => path.resolve(from, f));
20
- };
18
+ const extractFiles = (files, from = standaloneNextDir) => files.map((f) => path.resolve(from, f));
21
19
  // On next 14+, we might not have to include those files
22
20
  // For next 13, we need to include them otherwise we get runtime error
23
21
  const requiredServerFiles = JSON.parse(readFileSync(path.join(dotNextDir, bundledNextServer
@@ -59,13 +57,11 @@ See the docs for more information on how to bundle edge runtime functions.
59
57
  --------------------------------------------------------------------------------
60
58
  `);
61
59
  }
62
- else {
63
- throw new Error(`
60
+ throw new Error(`
64
61
  --------------------------------------------------------------------------------
65
62
  We cannot find the route for ${pagePath}.
66
63
  File ${fullFilePath} does not exist
67
64
  --------------------------------------------------------------------------------`);
68
- }
69
65
  }
70
66
  const dir = path.dirname(fullFilePath);
71
67
  extractFiles(requiredFiles.files, path.join(standaloneNextDir, dir)).forEach((f) => {
@@ -83,7 +79,7 @@ File ${fullFilePath} does not exist
83
79
  }
84
80
  catch (e) {
85
81
  if (alternativePath) {
86
- computeCopyFilesForPage(alternativePath);
82
+ safeComputeCopyFilesForPage(alternativePath);
87
83
  }
88
84
  }
89
85
  };
@@ -144,20 +140,15 @@ File ${fullFilePath} does not exist
144
140
  copyFileSync(from, to);
145
141
  }
146
142
  });
147
- readdirSync(standaloneNextDir).forEach((f) => {
148
- if (statSync(path.join(standaloneNextDir, f)).isDirectory())
149
- return;
150
- copyFileSync(path.join(standaloneNextDir, f), path.join(outputNextDir, f));
151
- });
143
+ readdirSync(standaloneNextDir)
144
+ .filter((fileOrDir) => !statSync(path.join(standaloneNextDir, fileOrDir)).isDirectory())
145
+ .forEach((file) => copyFileSync(path.join(standaloneNextDir, file), path.join(outputNextDir, file)));
152
146
  // We then need to copy all the files at the root of server
153
147
  mkdirSync(path.join(outputNextDir, "server"), { recursive: true });
154
- readdirSync(path.join(standaloneNextDir, "server")).forEach((f) => {
155
- if (statSync(path.join(standaloneNextDir, "server", f)).isDirectory())
156
- return;
157
- if (f !== "server.js") {
158
- copyFileSync(path.join(standaloneNextDir, "server", f), path.join(path.join(outputNextDir, "server"), f));
159
- }
160
- });
148
+ readdirSync(path.join(standaloneNextDir, "server"))
149
+ .filter((fileOrDir) => !statSync(path.join(standaloneNextDir, "server", fileOrDir)).isDirectory())
150
+ .filter((file) => file !== "server.js")
151
+ .forEach((file) => copyFileSync(path.join(standaloneNextDir, "server", file), path.join(path.join(outputNextDir, "server"), file)));
161
152
  // Copy patch file
162
153
  copyPatchFile(path.join(outputDir, packagePath));
163
154
  // TODO: Recompute all the files.
@@ -198,11 +189,9 @@ File ${fullFilePath} does not exist
198
189
  }
199
190
  }
200
191
  });
201
- staticFiles.forEach((f) => {
202
- if (f.endsWith(".html")) {
203
- copyStaticFile(`server/${f}`);
204
- }
205
- });
192
+ staticFiles
193
+ .filter((file) => file.endsWith(".html"))
194
+ .forEach((file) => copyStaticFile(`server/${file}`));
206
195
  }
207
196
  logger.debug("copyTracedFiles:", Date.now() - tsStart, "ms");
208
197
  }
@@ -1,20 +1,25 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { isBinaryContentType } from "../adapters/binary.js";
4
3
  import logger from "../logger.js";
4
+ import { isBinaryContentType } from "../utils/binary.js";
5
5
  import * as buildHelper from "./helper.js";
6
6
  export function createStaticAssets(options) {
7
- logger.info(`Bundling static assets...`);
7
+ logger.info("Bundling static assets...");
8
8
  const { appBuildOutputPath, appPublicPath, outputDir, appPath } = options;
9
9
  // Create output folder
10
10
  const outputPath = path.join(outputDir, "assets");
11
11
  fs.mkdirSync(outputPath, { recursive: true });
12
- // Next.js outputs assets into multiple files. Copy into the same directory.
13
- // Copy over:
14
- // - .next/BUILD_ID => _next/BUILD_ID
15
- // - .next/static => _next/static
16
- // - public/* => *
17
- // - app/favicon.ico or src/app/favicon.ico => favicon.ico
12
+ /**
13
+ * Next.js outputs assets into multiple files. Copy into the same directory.
14
+ *
15
+ * Copy over:
16
+ * - .next/BUILD_ID => BUILD_ID
17
+ * - .next/static => _next/static
18
+ * - public/* => *
19
+ * - app/favicon.ico or src/app/favicon.ico => favicon.ico
20
+ *
21
+ * Note: BUILD_ID is used by the SST infra.
22
+ */
18
23
  fs.copyFileSync(path.join(appBuildOutputPath, ".next/BUILD_ID"), path.join(outputPath, "BUILD_ID"));
19
24
  fs.cpSync(path.join(appBuildOutputPath, ".next/static"), path.join(outputPath, "_next", "static"), { recursive: true });
20
25
  if (fs.existsSync(appPublicPath)) {
@@ -24,7 +29,9 @@ export function createStaticAssets(options) {
24
29
  ? "src/app"
25
30
  : "app";
26
31
  const faviconPath = path.join(appPath, appSrcPath, "favicon.ico");
27
- if (fs.existsSync(faviconPath)) {
32
+ // We need to check if the favicon is either a file or directory.
33
+ // If it's a directory, we assume it's a route handler and ignore it.
34
+ if (fs.existsSync(faviconPath) && fs.lstatSync(faviconPath).isFile()) {
28
35
  fs.copyFileSync(faviconPath, path.join(outputPath, "favicon.ico"));
29
36
  }
30
37
  }
@@ -35,7 +42,7 @@ export function createStaticAssets(options) {
35
42
  * @returns Whether tag cache is used.
36
43
  */
37
44
  export function createCacheAssets(options) {
38
- logger.info(`Bundling cache assets...`);
45
+ logger.info("Bundling cache assets...");
39
46
  const { appBuildOutputPath, outputDir } = options;
40
47
  const packagePath = path.relative(options.monorepoRoot, appBuildOutputPath);
41
48
  const buildId = buildHelper.getBuildId(appBuildOutputPath);
@@ -49,27 +56,29 @@ export function createCacheAssets(options) {
49
56
  .forEach((dir) => fs.cpSync(dir, outputPath, { recursive: true }));
50
57
  // Remove non-cache files
51
58
  const htmlPages = buildHelper.getHtmlPages(dotNextPath);
52
- buildHelper.removeFiles(outputPath, (file) => file.endsWith(".js") ||
53
- file.endsWith(".js.nft.json") ||
54
- (file.endsWith(".html") && htmlPages.has(file)));
59
+ buildHelper.removeFiles(outputPath, ({ relativePath }) => relativePath.endsWith(".js") ||
60
+ relativePath.endsWith(".js.nft.json") ||
61
+ (relativePath.endsWith(".html") && htmlPages.has(relativePath)));
55
62
  // Merge cache files into a single file
56
63
  const cacheFilesPath = {};
57
- buildHelper.traverseFiles(outputPath, () => true, (filepath) => {
58
- const ext = path.extname(filepath);
64
+ buildHelper.traverseFiles(outputPath, () => true, ({ absolutePath }) => {
65
+ const ext = path.extname(absolutePath);
59
66
  switch (ext) {
60
67
  case ".meta":
61
68
  case ".html":
62
69
  case ".json":
63
70
  case ".body":
64
- case ".rsc":
65
- const newFilePath = filepath
66
- .substring(0, filepath.length - ext.length)
67
- .replace(/\.prefetch$/, "") + ".cache";
71
+ case ".rsc": {
72
+ const newFilePath = absolutePath
73
+ .substring(0, absolutePath.length - ext.length)
74
+ .replace(/\.prefetch$/, "")
75
+ .concat(".cache");
68
76
  cacheFilesPath[newFilePath] = {
69
- [ext.slice(1)]: filepath,
77
+ [ext.slice(1)]: absolutePath,
70
78
  ...cacheFilesPath[newFilePath],
71
79
  };
72
80
  break;
81
+ }
73
82
  case ".map":
74
83
  break;
75
84
  default:
@@ -106,8 +115,8 @@ export function createCacheAssets(options) {
106
115
  const metaFiles = [];
107
116
  // Compute dynamodb cache data
108
117
  // Traverse files inside cache to find all meta files and cache tags associated with them
109
- buildHelper.traverseFiles(outputPath, (file) => file.endsWith(".meta"), (filePath) => {
110
- const fileContent = fs.readFileSync(filePath, "utf8");
118
+ buildHelper.traverseFiles(outputPath, ({ absolutePath }) => absolutePath.endsWith(".meta"), ({ absolutePath, relativePath }) => {
119
+ const fileContent = fs.readFileSync(absolutePath, "utf8");
111
120
  const fileData = JSON.parse(fileContent);
112
121
  if (fileData.headers?.["x-next-cache-tags"]) {
113
122
  fileData.headers["x-next-cache-tags"]
@@ -117,7 +126,7 @@ export function createCacheAssets(options) {
117
126
  metaFiles.push({
118
127
  tag: { S: path.posix.join(buildId, tag.trim()) },
119
128
  path: {
120
- S: path.posix.join(buildId, path.relative(outputPath, filePath).replace(".meta", "")),
129
+ S: path.posix.join(buildId, relativePath.replace(".meta", "")),
121
130
  },
122
131
  // We don't care about the revalidation time here, we just need to make sure it's there
123
132
  revalidatedAt: { N: "1" },
@@ -131,14 +140,14 @@ export function createCacheAssets(options) {
131
140
  const fetchOutputPath = path.join(outputDir, "cache", "__fetch", buildId);
132
141
  fs.mkdirSync(fetchOutputPath, { recursive: true });
133
142
  fs.cpSync(fetchCachePath, fetchOutputPath, { recursive: true });
134
- buildHelper.traverseFiles(fetchCachePath, () => true, (filepath) => {
135
- const fileContent = fs.readFileSync(filepath, "utf8");
143
+ buildHelper.traverseFiles(fetchCachePath, () => true, ({ absolutePath, relativePath }) => {
144
+ const fileContent = fs.readFileSync(absolutePath, "utf8");
136
145
  const fileData = JSON.parse(fileContent);
137
146
  fileData?.tags?.forEach((tag) => {
138
147
  metaFiles.push({
139
148
  tag: { S: path.posix.join(buildId, tag) },
140
149
  path: {
141
- S: path.posix.join(buildId, path.relative(fetchCachePath, filepath)),
150
+ S: path.posix.join(buildId, relativePath),
142
151
  },
143
152
  revalidatedAt: { N: "1" },
144
153
  });
@@ -156,6 +165,6 @@ export function createCacheAssets(options) {
156
165
  }
157
166
  }
158
167
  // We need to remove files later because we need the metafiles for dynamodb tags cache
159
- buildHelper.removeFiles(outputPath, (file) => !file.endsWith(".cache"));
168
+ buildHelper.removeFiles(outputPath, ({ relativePath }) => !relativePath.endsWith(".cache"));
160
169
  return { useTagCache };
161
170
  }
@@ -8,7 +8,7 @@ import * as buildHelper from "./helper.js";
8
8
  import { installDependencies } from "./installDeps.js";
9
9
  const require = createRequire(import.meta.url);
10
10
  export async function createImageOptimizationBundle(options) {
11
- logger.info(`Bundling image optimization function...`);
11
+ logger.info("Bundling image optimization function...");
12
12
  const { appBuildOutputPath, config, outputDir } = options;
13
13
  // Create output folder
14
14
  const outputPath = path.join(outputDir, "image-optimization-function");
@@ -11,7 +11,7 @@ import { installDependencies } from "./installDeps.js";
11
11
  * @param forceOnlyBuildOnce force to build only once.
12
12
  */
13
13
  export async function createMiddleware(options, { forceOnlyBuildOnce = false } = {}) {
14
- logger.info(`Bundling middleware function...`);
14
+ logger.info("Bundling middleware function...");
15
15
  const { appBuildOutputPath, config, outputDir } = options;
16
16
  // Get middleware manifest
17
17
  const middlewareManifest = JSON.parse(fs.readFileSync(path.join(appBuildOutputPath, ".next/server/middleware-manifest.json"), "utf8"));
@@ -20,18 +20,22 @@ export async function createMiddleware(options, { forceOnlyBuildOnce = false } =
20
20
  const outputPath = path.join(outputDir, "middleware");
21
21
  fs.mkdirSync(outputPath, { recursive: true });
22
22
  // Copy open-next.config.mjs
23
- buildHelper.copyOpenNextConfig(options.buildDir, outputPath, config.middleware.override?.wrapper === "cloudflare");
23
+ buildHelper.copyOpenNextConfig(options.buildDir, outputPath, await buildHelper.isEdgeRuntime(config.middleware.override));
24
24
  // Bundle middleware
25
25
  await buildEdgeBundle({
26
26
  entrypoint: path.join(options.openNextDistDir, "adapters", "middleware.js"),
27
27
  outfile: path.join(outputPath, "handler.mjs"),
28
28
  middlewareInfo,
29
29
  options,
30
- overrides: config.middleware?.override,
30
+ overrides: {
31
+ ...config.middleware.override,
32
+ originResolver: config.middleware.originResolver,
33
+ },
31
34
  defaultConverter: "aws-cloudfront",
32
35
  includeCache: config.dangerous?.enableCacheInterception,
33
36
  additionalExternals: config.edgeExternals,
34
37
  onlyBuildOnce: forceOnlyBuildOnce === true,
38
+ name: "middleware",
35
39
  });
36
40
  installDependencies(outputPath, config.middleware?.install);
37
41
  }
@@ -42,6 +46,7 @@ export async function createMiddleware(options, { forceOnlyBuildOnce = false } =
42
46
  middlewareInfo,
43
47
  options,
44
48
  onlyBuildOnce: true,
49
+ name: "middleware",
45
50
  });
46
51
  }
47
52
  }
@@ -5,7 +5,7 @@ import { openNextResolvePlugin } from "../plugins/resolve.js";
5
5
  import * as buildHelper from "./helper.js";
6
6
  import { installDependencies } from "./installDeps.js";
7
7
  export async function createRevalidationBundle(options) {
8
- logger.info(`Bundling revalidation function...`);
8
+ logger.info("Bundling revalidation function...");
9
9
  const { appBuildOutputPath, config, outputDir } = options;
10
10
  // Create output folder
11
11
  const outputPath = path.join(outputDir, "revalidation-function");
@@ -42,28 +42,22 @@ export async function createServerBundle(options) {
42
42
  // Find app dir routes
43
43
  if (fs.existsSync(path.join(serverPath, "app"))) {
44
44
  const appPath = path.join(serverPath, "app");
45
- buildHelper.traverseFiles(appPath, (file) => {
46
- if (file.endsWith("page.js") || file.endsWith("route.js")) {
47
- const route = `app/${file.replace(/\.js$/, "")}`;
48
- if (!foundRoutes.has(route)) {
49
- remainingRoutes.add(route);
50
- }
45
+ buildHelper.traverseFiles(appPath, ({ relativePath }) => relativePath.endsWith("page.js") || relativePath.endsWith("route.js"), ({ relativePath }) => {
46
+ const route = `app/${relativePath.replace(/\.js$/, "")}`;
47
+ if (!foundRoutes.has(route)) {
48
+ remainingRoutes.add(route);
51
49
  }
52
- return false;
53
- }, () => { });
50
+ });
54
51
  }
55
52
  // Find pages dir routes
56
53
  if (fs.existsSync(path.join(serverPath, "pages"))) {
57
54
  const pagePath = path.join(serverPath, "pages");
58
- buildHelper.traverseFiles(pagePath, (file) => {
59
- if (file.endsWith(".js")) {
60
- const route = `pages/${file.replace(/\.js$/, "")}`;
61
- if (!foundRoutes.has(route)) {
62
- remainingRoutes.add(route);
63
- }
55
+ buildHelper.traverseFiles(pagePath, ({ relativePath }) => relativePath.endsWith(".js"), ({ relativePath }) => {
56
+ const route = `pages/${relativePath.replace(/\.js$/, "")}`;
57
+ if (!foundRoutes.has(route)) {
58
+ remainingRoutes.add(route);
64
59
  }
65
- return false;
66
- }, () => { });
60
+ });
67
61
  }
68
62
  // Generate default function
69
63
  await generateBundle("default", options, {
@@ -83,7 +77,6 @@ async function generateBundle(name, options, fnOptions) {
83
77
  // `node_modules` inside `.next/standalone`, and others inside
84
78
  // `.next/standalone/package/path` (ie. `.next`, `server.js`).
85
79
  // We need to output the handler file inside the package path.
86
- const isMonorepo = monorepoRoot !== appPath;
87
80
  const packagePath = path.relative(monorepoRoot, appBuildOutputPath);
88
81
  fs.mkdirSync(path.join(outputPath, packagePath), { recursive: true });
89
82
  const ext = fnOptions.runtime === "deno" ? "mjs" : "cjs";
@@ -94,7 +87,9 @@ async function generateBundle(name, options, fnOptions) {
94
87
  // Bundle next server if necessary
95
88
  const isBundled = fnOptions.experimentalBundledNextServer ?? false;
96
89
  if (isBundled) {
97
- await bundleNextServer(path.join(outputPath, packagePath), appPath);
90
+ await bundleNextServer(path.join(outputPath, packagePath), appPath, {
91
+ minify: options.minify,
92
+ });
98
93
  }
99
94
  // Copy middleware
100
95
  if (!config.middleware?.external) {
@@ -132,20 +127,16 @@ async function generateBundle(name, options, fnOptions) {
132
127
  ...(disableNextPrebundledReact ? ["requireHooks"] : []),
133
128
  ...(disableRouting ? ["trustHostHeader"] : []),
134
129
  ...(!isBefore13413 ? ["requestHandlerHost"] : []),
135
- ...(!isAfter141 ? ["stableIncrementalCache"] : []),
136
- ...(isAfter141 ? ["experimentalIncrementalCacheHandler"] : []),
130
+ ...(isAfter141
131
+ ? ["experimentalIncrementalCacheHandler"]
132
+ : ["stableIncrementalCache"]),
137
133
  ],
138
134
  }),
139
135
  openNextResolvePlugin({
140
136
  fnName: name,
141
- overrides: overrides,
137
+ overrides,
142
138
  }),
143
139
  ];
144
- if (plugins && plugins.length > 0) {
145
- logger.debug(`Applying plugins:: [${plugins
146
- .map(({ name }) => name)
147
- .join(",")}] for Next version: ${options.nextVersion}`);
148
- }
149
140
  const outfileExt = fnOptions.runtime === "deno" ? "ts" : "mjs";
150
141
  await buildHelper.esbuildAsync({
151
142
  entryPoints: [
@@ -167,11 +158,14 @@ async function generateBundle(name, options, fnOptions) {
167
158
  },
168
159
  plugins,
169
160
  alias: {
170
- "next/dist/server/next-server.js": isBundled
171
- ? "./next-server.runtime.prod.js"
172
- : "next/dist/server/next-server.js",
161
+ ...(isBundled
162
+ ? {
163
+ "next/dist/server/next-server.js": "./next-server.runtime.prod.js",
164
+ }
165
+ : {}),
173
166
  },
174
167
  }, options);
168
+ const isMonorepo = monorepoRoot !== appPath;
175
169
  if (isMonorepo) {
176
170
  addMonorepoEntrypoint(outputPath, packagePath);
177
171
  }
@@ -214,10 +208,10 @@ function addMonorepoEntrypoint(outputPath, packagePath) {
214
208
  // that re-exports the real handler.
215
209
  // Always use posix path for import path
216
210
  const packagePosixPath = packagePath.split(path.sep).join(path.posix.sep);
217
- fs.writeFileSync(path.join(outputPath, "index.mjs"), [`export * from "./${packagePosixPath}/index.mjs";`].join(""));
211
+ fs.writeFileSync(path.join(outputPath, "index.mjs"), `export * from "./${packagePosixPath}/index.mjs";`);
218
212
  }
219
213
  async function minifyServerBundle(outputDir) {
220
- logger.info(`Minimizing server function...`);
214
+ logger.info("Minimizing server function...");
221
215
  await minifyAll(outputDir, {
222
216
  compress_json: true,
223
217
  mangle: true,
@@ -5,7 +5,7 @@ import { openNextResolvePlugin } from "../plugins/resolve.js";
5
5
  import * as buildHelper from "./helper.js";
6
6
  import { installDependencies } from "./installDeps.js";
7
7
  export async function createWarmerBundle(options) {
8
- logger.info(`Bundling warmer function...`);
8
+ logger.info("Bundling warmer function...");
9
9
  const { config, outputDir } = options;
10
10
  // Create output folder
11
11
  const outputPath = path.join(outputDir, "warmer-function");
@@ -1,18 +1,22 @@
1
1
  import type { MiddlewareInfo } from "../../types/next-types";
2
- import type { IncludedConverter, OverrideOptions, SplittedFunctionOptions } from "../../types/open-next";
3
- import type { BuildOptions } from "../helper.js";
2
+ import type { IncludedConverter, IncludedOriginResolver, LazyLoadedOverride, OverrideOptions, SplittedFunctionOptions } from "../../types/open-next";
3
+ import type { OriginResolver } from "../../types/overrides.js";
4
+ import { type BuildOptions } from "../helper.js";
4
5
  interface BuildEdgeBundleOptions {
5
6
  middlewareInfo?: MiddlewareInfo;
6
7
  entrypoint: string;
7
8
  outfile: string;
8
9
  options: BuildOptions;
9
- overrides?: OverrideOptions;
10
+ overrides?: OverrideOptions & {
11
+ originResolver?: LazyLoadedOverride<OriginResolver> | IncludedOriginResolver;
12
+ };
10
13
  defaultConverter?: IncludedConverter;
11
14
  additionalInject?: string;
12
15
  includeCache?: boolean;
13
16
  additionalExternals?: string[];
14
17
  onlyBuildOnce?: boolean;
18
+ name: string;
15
19
  }
16
- export declare function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, }: BuildEdgeBundleOptions): Promise<void>;
20
+ export declare function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, name, }: BuildEdgeBundleOptions): Promise<void>;
17
21
  export declare function generateEdgeBundle(name: string, options: BuildOptions, fnOptions: SplittedFunctionOptions): Promise<void>;
18
22
  export {};
@@ -1,19 +1,17 @@
1
1
  import { mkdirSync } from "node:fs";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
2
4
  import { build } from "esbuild";
3
- import fs from "fs";
4
- import path from "path";
5
5
  import logger from "../../logger.js";
6
6
  import { openNextEdgePlugins } from "../../plugins/edge.js";
7
7
  import { openNextReplacementPlugin } from "../../plugins/replacement.js";
8
8
  import { openNextResolvePlugin } from "../../plugins/resolve.js";
9
+ import { isEdgeRuntime } from "../helper.js";
9
10
  import { copyOpenNextConfig, esbuildAsync } from "../helper.js";
10
- export async function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, }) {
11
- const isInCloudfare = typeof overrides?.wrapper === "string"
12
- ? overrides.wrapper === "cloudflare"
13
- : (await overrides?.wrapper?.())?.edgeRuntime;
11
+ export async function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, name, }) {
12
+ const isInCloudfare = await isEdgeRuntime(overrides);
14
13
  await esbuildAsync({
15
14
  entryPoints: [entrypoint],
16
- // inject: ,
17
15
  bundle: true,
18
16
  outfile,
19
17
  external: ["node:*", "next", "@aws-sdk/*"],
@@ -41,7 +39,14 @@ export async function buildEdgeBundle({ middlewareInfo, entrypoint, outfile, opt
41
39
  : "sqs-lite",
42
40
  }
43
41
  : {}),
42
+ originResolver: typeof overrides?.originResolver === "string"
43
+ ? overrides.originResolver
44
+ : "pattern-env",
45
+ proxyExternalRequest: typeof overrides?.proxyExternalRequest === "string"
46
+ ? overrides.proxyExternalRequest
47
+ : "node",
44
48
  },
49
+ fnName: name,
45
50
  }),
46
51
  openNextReplacementPlugin({
47
52
  name: "externalMiddlewareOverrides",
@@ -70,20 +75,32 @@ globalThis.Buffer = Buffer;
70
75
 
71
76
  import {AsyncLocalStorage} from "node:async_hooks";
72
77
  globalThis.AsyncLocalStorage = AsyncLocalStorage;
78
+
79
+ ${""
80
+ /**
81
+ * Next.js sets this `__import_unsupported` on `globalThis` (with `configurable: false`):
82
+ * https://github.com/vercel/next.js/blob/5b7833e3/packages/next/src/server/web/globals.ts#L94-L98
83
+ *
84
+ * It does so in both the middleware and the main server, so if the middleware runs in the same place
85
+ * as the main handler this code gets run twice triggering a runtime error.
86
+ *
87
+ * For this reason we need to patch `Object.defineProperty` to avoid this issue.
88
+ */
89
+ }
90
+ const defaultDefineProperty = Object.defineProperty;
91
+ Object.defineProperty = function(o, p, a) {
92
+ if(p=== '__import_unsupported' && Boolean(globalThis.__import_unsupported)) {
93
+ return;
94
+ }
95
+ return defaultDefineProperty(o, p, a);
96
+ };
97
+
73
98
  ${isInCloudfare
74
99
  ? ""
75
100
  : `
76
101
  const require = (await import("node:module")).createRequire(import.meta.url);
77
102
  const __filename = (await import("node:url")).fileURLToPath(import.meta.url);
78
103
  const __dirname = (await import("node:path")).dirname(__filename);
79
-
80
- const defaultDefineProperty = Object.defineProperty;
81
- Object.defineProperty = function(o, p, a) {
82
- if(p=== '__import_unsupported' && Boolean(globalThis.__import_unsupported)) {
83
- return;
84
- }
85
- return defaultDefineProperty(o, p, a);
86
- };
87
104
  `}
88
105
  ${additionalInject ?? ""}
89
106
  `,
@@ -95,7 +112,7 @@ globalThis.AsyncLocalStorage = AsyncLocalStorage;
95
112
  outfile,
96
113
  allowOverwrite: true,
97
114
  bundle: true,
98
- minify: true,
115
+ minify: options.minify,
99
116
  platform: "node",
100
117
  format: "esm",
101
118
  conditions: ["workerd", "worker", "browser"],
@@ -141,5 +158,6 @@ export async function generateEdgeBundle(name, options, fnOptions) {
141
158
  options,
142
159
  overrides: fnOptions.override,
143
160
  additionalExternals: options.config.edgeExternals,
161
+ name,
144
162
  });
145
163
  }
@@ -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
  });
@@ -1,5 +1,5 @@
1
1
  import type { BuildOptions as ESBuildOptions } from "esbuild";
2
- import type { OpenNextConfig } from "../types/open-next.js";
2
+ import type { DefaultOverrideOptions, OpenNextConfig } from "../types/open-next.js";
3
3
  export type BuildOptions = ReturnType<typeof normalizeOptions>;
4
4
  export declare function normalizeOptions(config: OpenNextConfig, distDir: string, tempBuildDir: string): {
5
5
  appBuildOutputPath: string;
@@ -9,6 +9,7 @@ export declare function normalizeOptions(config: OpenNextConfig, distDir: string
9
9
  buildDir: string;
10
10
  config: OpenNextConfig;
11
11
  debug: boolean;
12
+ minify: boolean;
12
13
  monorepoRoot: string;
13
14
  nextVersion: string;
14
15
  openNextVersion: string;
@@ -19,15 +20,33 @@ export declare function normalizeOptions(config: OpenNextConfig, distDir: string
19
20
  };
20
21
  export declare function esbuildSync(esbuildOptions: ESBuildOptions, options: BuildOptions): void;
21
22
  export declare function esbuildAsync(esbuildOptions: ESBuildOptions, options: BuildOptions): Promise<void>;
22
- export declare function removeFiles(root: string, conditionFn: (file: string) => boolean, searchingDir?: string): void;
23
+ /**
24
+ * Type of the parameter of `traverseFiles` callbacks
25
+ */
26
+ export type TraversePath = {
27
+ absolutePath: string;
28
+ relativePath: string;
29
+ };
23
30
  /**
24
31
  * Recursively traverse files in a directory and call `callbackFn` when `conditionFn` returns true
32
+ *
33
+ * The callbacks are passed both the absolute and relative (to root) path to files.
34
+ *
25
35
  * @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
36
+ * @param conditionFn - Called to determine if `callbackFn` should be called.
37
+ * @param callbackFn - Called when `conditionFn` returns true.
28
38
  * @param searchingDir - Directory to search (used for recursion)
29
39
  */
30
- export declare function traverseFiles(root: string, conditionFn: (file: string) => boolean, callbackFn: (filePath: string) => void, searchingDir?: string): void;
40
+ export declare function traverseFiles(root: string, conditionFn: (paths: TraversePath) => boolean, callbackFn: (paths: TraversePath) => void, searchingDir?: string): void;
41
+ /**
42
+ * Recursively delete files.
43
+ *
44
+ * @see `traverseFiles`.
45
+ *
46
+ * @param root Root directory to search.
47
+ * @param conditionFn Predicate used to delete the files.
48
+ */
49
+ export declare function removeFiles(root: string, conditionFn: (paths: TraversePath) => boolean): void;
31
50
  export declare function getHtmlPages(dotNextPath: string): Set<string>;
32
51
  export declare function getBuildId(dotNextPath: string): string;
33
52
  export declare function getOpenNextVersion(): string;
@@ -50,3 +69,7 @@ export declare function printOpenNextVersion(options: BuildOptions): void;
50
69
  * the app directory, but the compiled config is in the root of the monorepo.
51
70
  */
52
71
  export declare function initOutputDir(options: BuildOptions): void;
72
+ /**
73
+ * @returns Whether the edge runtime is used
74
+ */
75
+ export declare function isEdgeRuntime(overrides: DefaultOverrideOptions | undefined): Promise<boolean | undefined>;