|
1 |
| -import { cpSync, existsSync } from "node:fs"; |
| 1 | +import { cpSync, existsSync, readFileSync, writeFileSync } from "node:fs"; |
2 | 2 | import { createRequire } from "node:module";
|
3 | 3 | import { dirname, join } from "node:path";
|
4 | 4 |
|
@@ -101,6 +101,10 @@ export async function build(projectOpts: ProjectOptions): Promise<void> {
|
101 | 101 | // TODO: rely on options only.
|
102 | 102 | await bundleServer(projConfig, options);
|
103 | 103 |
|
| 104 | + if (!projectOpts.skipWranglerConfigCheck) { |
| 105 | + await createWranglerConfigIfNotExistent(projectOpts); |
| 106 | + } |
| 107 | + |
104 | 108 | logger.info("OpenNext build complete.");
|
105 | 109 | }
|
106 | 110 |
|
@@ -178,3 +182,94 @@ function ensureCloudflareConfig(config: OpenNextConfig) {
|
178 | 182 | );
|
179 | 183 | }
|
180 | 184 | }
|
| 185 | + |
| 186 | +/** |
| 187 | + * Creates a `wrangler.jsonc` file for the user if a wrangler config file doesn't already exist, |
| 188 | + * but only after asking for the user's confirmation. |
| 189 | + * |
| 190 | + * If the user refuses a warning is shown (which offers ways to opt out of this check to the user). |
| 191 | + * |
| 192 | + * @param projectOpts The options for the project |
| 193 | + */ |
| 194 | +async function createWranglerConfigIfNotExistent(projectOpts: ProjectOptions): Promise<void> { |
| 195 | + const possibleExts = ["toml", "json", "jsonc"]; |
| 196 | + |
| 197 | + const wranglerConfigFileExists = possibleExts.some((ext) => |
| 198 | + existsSync(join(projectOpts.sourceDir, `wrangler.${ext}`)) |
| 199 | + ); |
| 200 | + if (wranglerConfigFileExists) { |
| 201 | + return; |
| 202 | + } |
| 203 | + |
| 204 | + const wranglerConfigPath = join(projectOpts.sourceDir, "wrangler.jsonc"); |
| 205 | + |
| 206 | + const answer = await askConfirmation( |
| 207 | + "No `wrangler.(toml|json|jsonc)` config file found, do you want to create one?" |
| 208 | + ); |
| 209 | + |
| 210 | + if (!answer) { |
| 211 | + console.warn( |
| 212 | + "No Wrangler config file created" + |
| 213 | + "\n" + |
| 214 | + "(to avoid this check use the `--skipWranglerConfigCheck` flag or set a `SKIP_WRANGLER_CONFIG_CHECK` environment variable to `yes`)" |
| 215 | + ); |
| 216 | + return; |
| 217 | + } |
| 218 | + |
| 219 | + const wranglerConfigTemplate = readFileSync( |
| 220 | + join(getPackageTemplatesDirPath(), "defaults", "wrangler.jsonc"), |
| 221 | + "utf8" |
| 222 | + ); |
| 223 | + let wranglerConfigContent = wranglerConfigTemplate; |
| 224 | + |
| 225 | + const appName = getAppNameFromPackageJson(projectOpts.sourceDir) ?? "app-name"; |
| 226 | + if (appName) { |
| 227 | + wranglerConfigContent = wranglerConfigContent.replace( |
| 228 | + '"app-name"', |
| 229 | + JSON.stringify(appName.replaceAll("_", "-")) |
| 230 | + ); |
| 231 | + } |
| 232 | + |
| 233 | + const compatDate = await getLatestCompatDate(); |
| 234 | + if (compatDate) { |
| 235 | + wranglerConfigContent = wranglerConfigContent.replace( |
| 236 | + /"compatibility_date": "\d{4}-\d{2}-\d{2}"/, |
| 237 | + `"compatibility_date": ${JSON.stringify(compatDate)}` |
| 238 | + ); |
| 239 | + } |
| 240 | + |
| 241 | + writeFileSync(wranglerConfigPath, wranglerConfigContent); |
| 242 | +} |
| 243 | + |
| 244 | +function getAppNameFromPackageJson(sourceDir: string): string | undefined { |
| 245 | + try { |
| 246 | + const packageJsonStr = readFileSync(join(sourceDir, "package.json"), "utf8"); |
| 247 | + const packageJson: Record<string, string> = JSON.parse(packageJsonStr); |
| 248 | + if (typeof packageJson.name === "string") return packageJson.name; |
| 249 | + } catch { |
| 250 | + /* empty */ |
| 251 | + } |
| 252 | +} |
| 253 | + |
| 254 | +export async function getLatestCompatDate(): Promise<string | undefined> { |
| 255 | + try { |
| 256 | + const resp = await fetch(`https://registry.npmjs.org/workerd`); |
| 257 | + const latestWorkerdVersion = ( |
| 258 | + (await resp.json()) as { |
| 259 | + "dist-tags": { latest: string }; |
| 260 | + } |
| 261 | + )["dist-tags"].latest; |
| 262 | + |
| 263 | + // The format of the workerd version is `major.yyyymmdd.patch`. |
| 264 | + const match = latestWorkerdVersion.match(/\d+\.(\d{4})(\d{2})(\d{2})\.\d+/); |
| 265 | + |
| 266 | + if (match) { |
| 267 | + const [, year, month, date] = match; |
| 268 | + const compatDate = `${year}-${month}-${date}`; |
| 269 | + |
| 270 | + return compatDate; |
| 271 | + } |
| 272 | + } catch { |
| 273 | + /* empty */ |
| 274 | + } |
| 275 | +} |
0 commit comments