|
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 |
|
@@ -37,6 +37,8 @@ export async function build(projectOpts: ProjectOptions): Promise<void> {
|
37 | 37 | const require = createRequire(import.meta.url);
|
38 | 38 | const openNextDistDir = dirname(require.resolve("@opennextjs/aws/index.js"));
|
39 | 39 |
|
| 40 | + await createWranglerTomlIfNotExistent(projectOpts); |
| 41 | + |
40 | 42 | await createOpenNextConfigIfNotExistent(projectOpts);
|
41 | 43 |
|
42 | 44 | const { config, buildDir } = await compileOpenNextConfig(baseDir);
|
@@ -178,3 +180,79 @@ function ensureCloudflareConfig(config: OpenNextConfig) {
|
178 | 180 | );
|
179 | 181 | }
|
180 | 182 | }
|
| 183 | + |
| 184 | +/** |
| 185 | + * Creates a `wrangler.toml` file for the user if it doesn't exist, but only after asking for the user's confirmation. |
| 186 | + * |
| 187 | + * If the user refuses an error is thrown (since the file is mandatory). |
| 188 | + * |
| 189 | + * @param projectOpts The options for the project |
| 190 | + */ |
| 191 | +async function createWranglerTomlIfNotExistent(projectOpts: ProjectOptions): Promise<void> { |
| 192 | + const wranglerTomlPath = join(projectOpts.sourceDir, "wrangler.toml"); |
| 193 | + |
| 194 | + if (!existsSync(wranglerTomlPath)) { |
| 195 | + const answer = await askConfirmation("Missing required `wrangler.toml` file, do you want to create one?"); |
| 196 | + |
| 197 | + if (!answer) { |
| 198 | + throw new Error("The `wrangler.toml` file is required, aborting!"); |
| 199 | + } |
| 200 | + |
| 201 | + const wranglerTomlTemplate = readFileSync( |
| 202 | + join(getPackageTemplatesDirPath(), "defaults", "wrangler.toml"), |
| 203 | + "utf8" |
| 204 | + ); |
| 205 | + let wranglerTomlContent = wranglerTomlTemplate; |
| 206 | + |
| 207 | + const appName = getAppNameFromPackageJson(projectOpts.sourceDir) ?? "app-name"; |
| 208 | + if (appName) { |
| 209 | + wranglerTomlContent = wranglerTomlContent.replace( |
| 210 | + '"app-name"', |
| 211 | + JSON.stringify(appName.replaceAll("_", "-")) |
| 212 | + ); |
| 213 | + } |
| 214 | + |
| 215 | + const compatDate = await getLatestCompatDate(); |
| 216 | + if (compatDate) { |
| 217 | + wranglerTomlContent = wranglerTomlContent.replace( |
| 218 | + /compatibility_date = "\d{4}-\d{2}-\d{2}"/, |
| 219 | + `compatibility_date = ${JSON.stringify(compatDate)}` |
| 220 | + ); |
| 221 | + } |
| 222 | + |
| 223 | + writeFileSync(wranglerTomlPath, wranglerTomlContent); |
| 224 | + } |
| 225 | +} |
| 226 | + |
| 227 | +function getAppNameFromPackageJson(sourceDir: string): string | undefined { |
| 228 | + try { |
| 229 | + const packageJsonStr = readFileSync(join(sourceDir, "package.json"), "utf8"); |
| 230 | + const packageJson: Record<string, string> = JSON.parse(packageJsonStr); |
| 231 | + if (typeof packageJson.name === "string") return packageJson.name; |
| 232 | + } catch { |
| 233 | + /* empty */ |
| 234 | + } |
| 235 | +} |
| 236 | + |
| 237 | +export async function getLatestCompatDate(): Promise<string | undefined> { |
| 238 | + try { |
| 239 | + const resp = await fetch(`https://registry.npmjs.org/workerd`); |
| 240 | + const latestWorkerdVersion = ( |
| 241 | + (await resp.json()) as { |
| 242 | + "dist-tags": { latest: string }; |
| 243 | + } |
| 244 | + )["dist-tags"].latest; |
| 245 | + |
| 246 | + // The format of the workerd version is `major.yyyymmdd.patch`. |
| 247 | + const match = latestWorkerdVersion.match(/\d+\.(\d{4})(\d{2})(\d{2})\.\d+/); |
| 248 | + |
| 249 | + if (match) { |
| 250 | + const [, year, month, date] = match ?? []; |
| 251 | + const compatDate = `${year}-${month}-${date}`; |
| 252 | + |
| 253 | + return compatDate; |
| 254 | + } |
| 255 | + } catch { |
| 256 | + /* empty */ |
| 257 | + } |
| 258 | +} |
0 commit comments