From 4ecff6e9bc150bd15e6a0d60d29489022e316561 Mon Sep 17 00:00:00 2001 From: tianma Date: Fri, 26 Jun 2026 18:28:52 +0800 Subject: [PATCH] fix: prepare wrangler config for cloudflare builds --- .env.local.example | 4 +- .gitignore | 1 + README.md | 8 +++- package.json | 6 +-- scripts/run-wrangler.mjs | 88 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 scripts/run-wrangler.mjs diff --git a/.env.local.example b/.env.local.example index b022ac26..012b0940 100644 --- a/.env.local.example +++ b/.env.local.example @@ -19,7 +19,9 @@ EDGE_EVER_WORKER_NAME=edgeever EDGE_EVER_D1_DATABASE_NAME=edgeever # D1 数据库 ID。 -# 创建 D1 后,把 wrangler 返回的 database_id 填到这里,并同步替换 wrangler.toml 里的占位值。 +# 创建 D1 后,把 wrangler 返回的 database_id 填到这里。 +# Cloudflare Git 自动部署时,也需要在 Build Variables 里设置同名变量。 +# 脚本会生成临时 .wrangler.generated.toml,不需要把个人 D1 ID 提交到公开仓库。 EDGE_EVER_D1_DATABASE_ID=00000000-0000-0000-0000-000000000000 # R2 生产资源桶名称。 diff --git a/.gitignore b/.gitignore index a36dcef3..3e02f5c8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ build/ coverage/ .wrangler/ +.wrangler.generated.toml .dev.vars wrangler.local.toml diff --git a/README.md b/README.md index e6d7d8f8..20d5193b 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,13 @@ bunx wrangler d1 create edgeever bunx wrangler r2 bucket create edgeever-resources ``` -把 D1 创建命令返回的 `database_id` 填入本机 `.env.local` 的 `EDGE_EVER_D1_DATABASE_ID`,并同步替换 `wrangler.toml` 里的 `database_id` 占位值。 +把 D1 创建命令返回的 `database_id` 填入本机 `.env.local` 的 `EDGE_EVER_D1_DATABASE_ID`。部署脚本会在运行时生成临时 `.wrangler.generated.toml`,不需要把个人 D1 ID 提交到公开仓库。 + +如果你把 Worker 连接到 GitHub 并开启 Cloudflare 自动构建,需要在 Cloudflare 的 Build Variables 里设置: + +```text +EDGE_EVER_D1_DATABASE_ID=<你的 D1 database_id> +``` 应用本地迁移: diff --git a/package.json b/package.json index d4af1e16..c4d8db9a 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ "build:web": "vite build --config apps/web/vite.config.ts", "preview:web": "vite preview --config apps/web/vite.config.ts --host 127.0.0.1 --port 4173", "typecheck": "tsc -p tsconfig.json --noEmit", - "db:migrate:local": "wrangler d1 migrations apply DB --local", - "db:migrate:remote": "wrangler d1 migrations apply DB --remote", - "deploy": "bun run build && bun run db:migrate:remote && wrangler deploy" + "db:migrate:local": "bun scripts/run-wrangler.mjs d1 migrations apply DB --local", + "db:migrate:remote": "bun scripts/run-wrangler.mjs d1 migrations apply DB --remote", + "deploy": "bun run build && bun run db:migrate:remote && bun scripts/run-wrangler.mjs deploy" }, "cloudflare": { "bindings": { diff --git a/scripts/run-wrangler.mjs b/scripts/run-wrangler.mjs new file mode 100644 index 00000000..7eebfb21 --- /dev/null +++ b/scripts/run-wrangler.mjs @@ -0,0 +1,88 @@ +import { spawnSync } from "node:child_process"; +import { readFileSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const PLACEHOLDER_D1_ID = "00000000-0000-0000-0000-000000000000"; +const UUID_PATTERN = + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; + +const wranglerArgs = process.argv.slice(2); +if (wranglerArgs.length === 0) { + console.error("Usage: bun scripts/run-wrangler.mjs "); + process.exit(1); +} + +const baseConfigPath = resolve(process.env.WRANGLER_CONFIG ?? "wrangler.toml"); +const generatedConfigPath = resolve(".wrangler.generated.toml"); +let config = readFileSync(baseConfigPath, "utf8"); +let changed = false; + +const replaceTomlValue = (source, key, value) => { + if (!value) { + return source; + } + + const pattern = new RegExp(`(^${key}\\s*=\\s*")[^"]*(")`, "m"); + if (!pattern.test(source)) { + throw new Error(`Cannot find ${key} in ${baseConfigPath}`); + } + + changed = true; + return source.replace(pattern, `$1${value}$2`); +}; + +const d1DatabaseId = process.env.EDGE_EVER_D1_DATABASE_ID?.trim(); +if (d1DatabaseId) { + if (!UUID_PATTERN.test(d1DatabaseId)) { + throw new Error("EDGE_EVER_D1_DATABASE_ID must be a Cloudflare D1 UUID."); + } + + config = replaceTomlValue(config, "database_id", d1DatabaseId); +} + +config = replaceTomlValue( + config, + "database_name", + process.env.EDGE_EVER_D1_DATABASE_NAME?.trim(), +); +config = replaceTomlValue( + config, + "bucket_name", + process.env.EDGE_EVER_R2_BUCKET_NAME?.trim(), +); +config = replaceTomlValue( + config, + "preview_bucket_name", + process.env.EDGE_EVER_R2_PREVIEW_BUCKET_NAME?.trim(), +); + +const isRemoteCommand = + wranglerArgs.includes("deploy") || wranglerArgs.includes("--remote"); +if (isRemoteCommand && config.includes(`database_id = "${PLACEHOLDER_D1_ID}"`)) { + console.error( + [ + "Missing Cloudflare D1 database id.", + "Set EDGE_EVER_D1_DATABASE_ID as a Cloudflare Build Variable,", + "or replace the database_id placeholder in wrangler.toml / WRANGLER_CONFIG.", + ].join(" "), + ); + process.exit(1); +} + +const configPath = changed ? generatedConfigPath : baseConfigPath; +if (changed) { + writeFileSync(generatedConfigPath, config); +} + +const executable = process.platform === "win32" ? "wrangler.cmd" : "wrangler"; +const result = spawnSync(executable, ["--config", configPath, ...wranglerArgs], { + stdio: "inherit", + shell: process.platform === "win32", +}); + +if (result.error) { + console.error(result.error.message); + process.exit(1); +} + +process.exit(result.status ?? 1);