1
- import { cpSync } from "node:fs" ;
1
+ import { cpSync , existsSync } from "node:fs" ;
2
2
import { createRequire } from "node:module" ;
3
3
import { dirname , join } from "node:path" ;
4
4
@@ -12,8 +12,10 @@ import { printHeader, showWarningOnWindows } from "@opennextjs/aws/build/utils.j
12
12
import logger from "@opennextjs/aws/logger.js" ;
13
13
import type { OpenNextConfig } from "@opennextjs/aws/types/open-next.js" ;
14
14
15
+ import { getPackageTemplatesDirPath } from "../../utils/get-package-templates-dir-path.js" ;
15
16
import type { ProjectOptions } from "../config.js" ;
16
17
import { containsDotNextDir , getConfig } from "../config.js" ;
18
+ import { askConfirmation } from "../utils/ask-confirmation.js" ;
17
19
import { bundleServer } from "./bundle-server.js" ;
18
20
import { compileEnvFiles } from "./open-next/compile-env-files.js" ;
19
21
import { copyCacheAssets } from "./open-next/copyCacheAssets.js" ;
@@ -35,6 +37,8 @@ export async function build(projectOpts: ProjectOptions): Promise<void> {
35
37
const require = createRequire ( import . meta. url ) ;
36
38
const openNextDistDir = dirname ( require . resolve ( "@opennextjs/aws/index.js" ) ) ;
37
39
40
+ await createOpenNextConfigIfNotExistent ( projectOpts ) ;
41
+
38
42
const { config, buildDir } = await compileOpenNextConfig ( baseDir ) ;
39
43
40
44
ensureCloudflareConfig ( config ) ;
@@ -100,6 +104,29 @@ export async function build(projectOpts: ProjectOptions): Promise<void> {
100
104
logger . info ( "OpenNext build complete." ) ;
101
105
}
102
106
107
+ /**
108
+ * Creates a `open-next.config.ts` file for the user if it doesn't exist, but only after asking for the user's confirmation.
109
+ *
110
+ * If the user refuses an error is thrown (since the file is mandatory).
111
+ *
112
+ * @param projectOpts The options for the project
113
+ */
114
+ async function createOpenNextConfigIfNotExistent ( projectOpts : ProjectOptions ) : Promise < void > {
115
+ const openNextConfigPath = join ( projectOpts . sourceDir , "open-next.config.ts" ) ;
116
+
117
+ if ( ! existsSync ( openNextConfigPath ) ) {
118
+ const answer = await askConfirmation (
119
+ "Missing required `open-next.config.ts` file, do you want to create one?"
120
+ ) ;
121
+
122
+ if ( ! answer ) {
123
+ throw new Error ( "The `open-next.config.ts` file is required, aborting!" ) ;
124
+ }
125
+
126
+ cpSync ( join ( getPackageTemplatesDirPath ( ) , "defaults" , "open-next.config.ts" ) , openNextConfigPath ) ;
127
+ }
128
+ }
129
+
103
130
/**
104
131
* Ensures open next is configured for cloudflare.
105
132
*
@@ -122,30 +149,32 @@ function ensureCloudflareConfig(config: OpenNextConfig) {
122
149
} ;
123
150
124
151
if ( Object . values ( requirements ) . some ( ( satisfied ) => ! satisfied ) ) {
125
- throw new Error ( `open-next.config.ts should contain:
126
- {
127
- default: {
128
- override: {
129
- wrapper: "cloudflare-node",
130
- converter: "edge",
131
- incrementalCache: "dummy" | function,
132
- tagCache: "dummy",
133
- queue: "dummy",
134
- },
135
- },
136
-
137
- middleware: {
138
- external: true,
139
- override: {
140
- wrapper: "cloudflare-edge",
141
- converter: "edge",
142
- proxyExternalRequest: "fetch",
143
- },
144
- },
145
-
146
- "dangerous": {
147
- "enableCacheInterception": false
148
- }
149
- }` ) ;
152
+ throw new Error (
153
+ "The `open-next.config.ts` should have a default export like this:\n\n" +
154
+ `{
155
+ default: {
156
+ override: {
157
+ wrapper: "cloudflare-node",
158
+ converter: "edge",
159
+ incrementalCache: "dummy" | function,
160
+ tagCache: "dummy",
161
+ queue: "dummy",
162
+ },
163
+ },
164
+
165
+ middleware: {
166
+ external: true,
167
+ override: {
168
+ wrapper: "cloudflare-edge",
169
+ converter: "edge",
170
+ proxyExternalRequest: "fetch",
171
+ },
172
+ },
173
+
174
+ "dangerous": {
175
+ "enableCacheInterception": false
176
+ },
177
+ }\n\n` . replace ( / ^ { 8 } / gm, "" )
178
+ ) ;
150
179
}
151
180
}
0 commit comments