Add R2 MEDIA binding and setup script

This commit is contained in:
2026-09-12 09:54:40 +08:00
parent 47f14b79e3
commit 125030ce2e
5 changed files with 29 additions and 3 deletions
+1
View File
@@ -18,6 +18,7 @@
"db:seed:local": "wrangler d1 execute yingfung-solar-db --local --file=./migrations/seed.sql", "db:seed:local": "wrangler d1 execute yingfung-solar-db --local --file=./migrations/seed.sql",
"db:studio": "drizzle-kit studio", "db:studio": "drizzle-kit studio",
"kv:create": "wrangler kv namespace create CACHE", "kv:create": "wrangler kv namespace create CACHE",
"r2:create": "wrangler r2 bucket create yingfung-solar-media",
"secret": "wrangler secret put ADMIN_PASSWORD", "secret": "wrangler secret put ADMIN_PASSWORD",
"types": "wrangler types", "types": "wrangler types",
"setup": "node scripts/setup.mjs" "setup": "node scripts/setup.mjs"
+16
View File
@@ -11,6 +11,7 @@ const ROOT = dirname(SCRIPT_DIR);
const D1_PLACEHOLDER = "PASTE_D1_DATABASE_ID_HERE"; const D1_PLACEHOLDER = "PASTE_D1_DATABASE_ID_HERE";
const KV_PLACEHOLDER = "PASTE_KV_NAMESPACE_ID_HERE"; const KV_PLACEHOLDER = "PASTE_KV_NAMESPACE_ID_HERE";
const R2_BUCKET = "yingfung-solar-media";
const WRANGLER = join(ROOT, "wrangler.jsonc"); const WRANGLER = join(ROOT, "wrangler.jsonc");
const SEED_FILE = join(ROOT, "migrations", "seed.sql"); const SEED_FILE = join(ROOT, "migrations", "seed.sql");
const ASTRO_CONFIG = join(ROOT, "astro.config.mjs"); const ASTRO_CONFIG = join(ROOT, "astro.config.mjs");
@@ -116,6 +117,21 @@ async function main() {
console.log("KV id 已設定,略過。"); console.log("KV id 已設定,略過。");
} }
console.log(`檢查 / 建立 R2 bucket「${R2_BUCKET}」…`);
const r2List = runSoft("npx wrangler r2 bucket list");
const r2Text = `${r2List.out || ""}\n${r2List.err || ""}`;
if (new RegExp(`\\b${R2_BUCKET}\\b`).test(r2Text)) {
console.log(" R2 bucket 已存在,略過。");
} else {
const r2 = runSoft(`npx wrangler r2 bucket create ${R2_BUCKET}`);
if (r2.ok) {
console.log(" R2 bucket 已建立。");
} else {
console.log(" 建立 R2 bucket 失敗(可能未開通 R2),請稍後手動執行: npm run r2:create");
console.log(r2.out || r2.err || "");
}
}
const setPassword = await rl.question("而家設定後台密碼 ADMIN_PASSWORD(y/N)"); const setPassword = await rl.question("而家設定後台密碼 ADMIN_PASSWORD(y/N)");
if (setPassword.trim().toLowerCase() === "y") { if (setPassword.trim().toLowerCase() === "y") {
execSync("npx wrangler secret put ADMIN_PASSWORD", { stdio: "inherit" }); execSync("npx wrangler secret put ADMIN_PASSWORD", { stdio: "inherit" });
+1
View File
@@ -3,6 +3,7 @@ import { env } from "cloudflare:workers";
export type AppEnv = { export type AppEnv = {
DB: D1Database; DB: D1Database;
CACHE: KVNamespace; CACHE: KVNamespace;
MEDIA: R2Bucket;
ADMIN_PASSWORD?: string; ADMIN_PASSWORD?: string;
AI_API_KEY?: string; AI_API_KEY?: string;
TAVILY_API_KEY?: string; TAVILY_API_KEY?: string;
+5 -3
View File
@@ -1,11 +1,13 @@
/* eslint-disable */ /* eslint-disable */
// Generated by Wrangler by running `wrangler types` (hash: bcadd21c7ffb76583873a6eda250f922) // Generated by Wrangler by running `wrangler types` (hash: 03ae7c4bd9c0facc561b340619a53d21)
// Runtime types generated with [email protected] 2026-09-10 nodejs_compat // Runtime types generated with [email protected] 2026-09-10 nodejs_compat
interface __BaseEnv_Env { interface __BaseEnv_Env {
CACHE: KVNamespace; CACHE: KVNamespace;
MEDIA: R2Bucket;
DB: D1Database; DB: D1Database;
ASSETS: Fetcher; ASSETS: Fetcher;
SITE_NAME: "你的公司名"; SITE_NAME: "盈豐太陽能";
ADMIN_PASSWORD: string;
} }
declare namespace Cloudflare { declare namespace Cloudflare {
interface Env extends __BaseEnv_Env {} interface Env extends __BaseEnv_Env {}
@@ -15,7 +17,7 @@ type StringifyValues<EnvType extends Record<string, unknown>> = {
[Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string; [Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string;
}; };
declare namespace NodeJS { declare namespace NodeJS {
interface ProcessEnv extends StringifyValues<Pick<Cloudflare.Env, "SITE_NAME">> {} interface ProcessEnv extends StringifyValues<Pick<Cloudflare.Env, "SITE_NAME" | "ADMIN_PASSWORD">> {}
} }
// Begin runtime types // Begin runtime types
+6
View File
@@ -33,5 +33,11 @@
"binding": "CACHE", "binding": "CACHE",
"id": "PASTE_KV_NAMESPACE_ID_HERE" "id": "PASTE_KV_NAMESPACE_ID_HERE"
} }
],
"r2_buckets": [
{
"binding": "MEDIA",
"bucket_name": "yingfung-solar-media"
}
] ]
} }