@opennextjs/aws 3.9.8 → 3.9.9

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.
@@ -127,7 +127,6 @@ async function generateBundle(name, options, fnOptions, codeCustomization) {
127
127
  patches.patchBackgroundRevalidation,
128
128
  patches.patchUseCacheForISR,
129
129
  patches.patchNodeEnvironment,
130
- patches.patchNextConfig,
131
130
  ...additionalCodePatches,
132
131
  ]);
133
132
  // Build Lambda code
@@ -4,4 +4,4 @@ export { patchFetchCacheForISR, patchUnstableCacheForISR, patchUseCacheForISR, }
4
4
  export { patchFetchCacheSetMissingWaitUntil } from "./patchFetchCacheWaitUntil.js";
5
5
  export { patchBackgroundRevalidation } from "./patchBackgroundRevalidation.js";
6
6
  export { patchNodeEnvironment } from "./patchNodeEnvironment.js";
7
- export { patchNextConfig } from "./patchNextConfig.js";
7
+ export { patchOriginalNextConfig } from "./patchOriginalNextConfig.js";
@@ -4,4 +4,4 @@ export { patchFetchCacheForISR, patchUnstableCacheForISR, patchUseCacheForISR, }
4
4
  export { patchFetchCacheSetMissingWaitUntil } from "./patchFetchCacheWaitUntil.js";
5
5
  export { patchBackgroundRevalidation } from "./patchBackgroundRevalidation.js";
6
6
  export { patchNodeEnvironment } from "./patchNodeEnvironment.js";
7
- export { patchNextConfig } from "./patchNextConfig.js";
7
+ export { patchOriginalNextConfig } from "./patchOriginalNextConfig.js";
@@ -0,0 +1,10 @@
1
+ import * as buildHelper from "../../helper.js";
2
+ /**
3
+ * Next 16.1+ removes `skipTrailingSlashRedirect` from the config in `required-server-files.json`.
4
+ *
5
+ * This patch adds it back in by compiling and importing the user's `next.config.js` file.
6
+ *
7
+ * It is a regression in https://github.com/vercel/next.js/pull/86830
8
+ * TODO(#1082): revisit when Next is fixed
9
+ */
10
+ export declare function patchOriginalNextConfig(options: buildHelper.BuildOptions): Promise<void>;
@@ -0,0 +1,78 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { build } from "esbuild";
4
+ import { inlineRequireResolvePlugin } from "../../../plugins/inline-require-resolve.js";
5
+ import * as buildHelper from "../../helper.js";
6
+ /**
7
+ * Next 16.1+ removes `skipTrailingSlashRedirect` from the config in `required-server-files.json`.
8
+ *
9
+ * This patch adds it back in by compiling and importing the user's `next.config.js` file.
10
+ *
11
+ * It is a regression in https://github.com/vercel/next.js/pull/86830
12
+ * TODO(#1082): revisit when Next is fixed
13
+ */
14
+ export async function patchOriginalNextConfig(options) {
15
+ if (buildHelper.compareSemver(options.nextVersion, "<", "16.1.0")) {
16
+ return;
17
+ }
18
+ // The manifests in both `.next` and `.next/standalone` folders
19
+ // are patched as Open Next uses either of them.
20
+ const manifestPath = path.join(options.appBuildOutputPath, ".next/required-server-files.json");
21
+ const manifestStandalonePath = path.join(options.appBuildOutputPath, ".next/standalone", buildHelper.getPackagePath(options), ".next/required-server-files.json");
22
+ if (fs.existsSync(manifestPath)) {
23
+ const manifest = JSON.parse(await fs.promises.readFile(manifestPath, "utf-8"));
24
+ if (manifest.config.skipTrailingSlashRedirect === undefined) {
25
+ const { skipTrailingSlashRedirect } = await importNextConfigFromSource(options);
26
+ manifest.config.skipTrailingSlashRedirect =
27
+ skipTrailingSlashRedirect ?? false;
28
+ await fs.promises.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
29
+ if (fs.existsSync(manifestStandalonePath)) {
30
+ await fs.promises.writeFile(manifestStandalonePath, JSON.stringify(manifest, null, 2), "utf-8");
31
+ }
32
+ }
33
+ }
34
+ else {
35
+ throw new Error(`Could not find required-server-files.json at path: ${manifestPath}`);
36
+ }
37
+ }
38
+ /**
39
+ * Compile and import the user's `next.config` file
40
+ *
41
+ * @returns
42
+ */
43
+ async function importNextConfigFromSource(buildOptions) {
44
+ // Find the `next.config file with any supported extension
45
+ const tsExtensions = [".ts", ".mts", ".cts"];
46
+ const possibleExtensions = [...tsExtensions, ".mjs", ".js", ".cjs"];
47
+ let configPath;
48
+ let configExtension;
49
+ for (const ext of possibleExtensions) {
50
+ const testPath = path.join(buildOptions.appPath, `next.config${ext}`);
51
+ if (fs.existsSync(testPath)) {
52
+ configPath = testPath;
53
+ configExtension = ext;
54
+ break;
55
+ }
56
+ }
57
+ if (!configPath || !configExtension) {
58
+ throw new Error("Could not find next.config file");
59
+ }
60
+ let configToImport;
61
+ // Only compile if the extension is a TypeScript extension
62
+ if (tsExtensions.includes(configExtension)) {
63
+ await build({
64
+ entryPoints: [configPath],
65
+ outfile: path.join(buildOptions.tempBuildDir, "next.config.mjs"),
66
+ bundle: true,
67
+ format: "esm",
68
+ platform: "node",
69
+ plugins: [inlineRequireResolvePlugin],
70
+ });
71
+ configToImport = path.join(buildOptions.tempBuildDir, "next.config.mjs");
72
+ }
73
+ else {
74
+ // For .js, .mjs, .cjs, use the file directly
75
+ configToImport = configPath;
76
+ }
77
+ return (await import(configToImport)).default;
78
+ }
package/dist/build.js CHANGED
@@ -12,6 +12,7 @@ import { createServerBundle } from "./build/createServerBundle.js";
12
12
  import { createWarmerBundle } from "./build/createWarmerBundle.js";
13
13
  import { generateOutput } from "./build/generateOutput.js";
14
14
  import * as buildHelper from "./build/helper.js";
15
+ import { patchOriginalNextConfig } from "./build/patch/patches/index.js";
15
16
  import { printHeader, showWarningOnWindows } from "./build/utils.js";
16
17
  import logger from "./logger.js";
17
18
  export async function build(openNextConfigPath, nodeExternals) {
@@ -33,6 +34,8 @@ export async function build(openNextConfigPath, nodeExternals) {
33
34
  buildNextjsApp(options);
34
35
  // Generate deployable bundle
35
36
  printHeader("Generating bundle");
37
+ // Patch the original Next.js config
38
+ await patchOriginalNextConfig(options);
36
39
  // Compile cache.ts
37
40
  compileCache(options);
38
41
  // Compile middleware
@@ -0,0 +1,10 @@
1
+ import type { Plugin } from "esbuild";
2
+ /**
3
+ * Inlines calls to `require.resolve` in JavaScript files.
4
+ *
5
+ * esbuild does not statically analyse `require.resolve` calls, and the polyfill
6
+ * does not include an implementation to handle them. This can be problematic
7
+ * if you attempt to dynamically import a file built by esbuild that unknowingly
8
+ * contains `require.resolve` calls, as they will throw an error during import.
9
+ */
10
+ export declare const inlineRequireResolvePlugin: Plugin;
@@ -0,0 +1,27 @@
1
+ import fs from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ /**
4
+ * Inlines calls to `require.resolve` in JavaScript files.
5
+ *
6
+ * esbuild does not statically analyse `require.resolve` calls, and the polyfill
7
+ * does not include an implementation to handle them. This can be problematic
8
+ * if you attempt to dynamically import a file built by esbuild that unknowingly
9
+ * contains `require.resolve` calls, as they will throw an error during import.
10
+ */
11
+ export const inlineRequireResolvePlugin = {
12
+ name: "inline-require-resolve",
13
+ setup: (build) => {
14
+ build.onLoad({ filter: /\.(js|ts|mjs|cjs)$/ }, async (args) => {
15
+ const source = await fs.promises.readFile(args.path, "utf-8");
16
+ const transformed = source.replace(/require\.resolve\((?<quote>['"])((?:\\.|.)*?)\k<quote>\)/g, (_, quote, modulePath) => {
17
+ try {
18
+ return JSON.stringify(createRequire(args.path).resolve(modulePath));
19
+ }
20
+ catch {
21
+ return `require.resolve(${quote}${modulePath}${quote})`;
22
+ }
23
+ });
24
+ return { contents: transformed, loader: "default" };
25
+ });
26
+ },
27
+ };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "access": "public"
4
4
  },
5
5
  "name": "@opennextjs/aws",
6
- "version": "3.9.8",
6
+ "version": "3.9.9",
7
7
  "bin": {
8
8
  "open-next": "./dist/index.js"
9
9
  },
@@ -1,2 +0,0 @@
1
- import type { CodePatcher } from "../codePatcher";
2
- export declare const patchNextConfig: CodePatcher;
@@ -1,54 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { buildSync } from "esbuild";
4
- export const patchNextConfig = {
5
- name: "patch-next-config",
6
- patches: [
7
- {
8
- pathFilter: /required\-server\-files\.json$/,
9
- versions: ">=16.1.0",
10
- patchCode: async ({ code, buildOptions }) => {
11
- // Find the next.config file with any supported extension
12
- const tsExtensions = [".ts", ".mts", ".cts"];
13
- const possibleExtensions = [...tsExtensions, ".mjs", ".js", ".cjs"];
14
- let configPath;
15
- let configExtension;
16
- for (const ext of possibleExtensions) {
17
- const testPath = path.join(buildOptions.appPath, `next.config${ext}`);
18
- if (fs.existsSync(testPath)) {
19
- configPath = testPath;
20
- configExtension = ext;
21
- break;
22
- }
23
- }
24
- if (!configPath || !configExtension) {
25
- throw new Error("Could not find next.config file");
26
- }
27
- let configToImport;
28
- // Only compile if the extension is a TypeScript extension
29
- if (tsExtensions.includes(configExtension)) {
30
- buildSync({
31
- entryPoints: [configPath],
32
- outfile: path.join(buildOptions.tempBuildDir, "next.config.mjs"),
33
- bundle: true,
34
- format: "esm",
35
- platform: "node",
36
- });
37
- configToImport = path.join(buildOptions.tempBuildDir, "next.config.mjs");
38
- }
39
- else {
40
- // For .js, .mjs, .cjs, use the file directly
41
- configToImport = configPath;
42
- }
43
- // In next 16.1+ we need to add `skipTrailingSlashRedirect` manually because next removes it from the config
44
- const originalConfig = (await import(configToImport)).default;
45
- const config = JSON.parse(code);
46
- if (config.config.skipTrailingSlashRedirect === undefined) {
47
- config.config.skipTrailingSlashRedirect =
48
- originalConfig.skipTrailingSlashRedirect ?? false;
49
- }
50
- return JSON.stringify(config, null, 2);
51
- },
52
- },
53
- ],
54
- };