import * as fs from "node:fs"; import * as path from "node:path"; export type ProjectType = "nextjs" | "vite" | "hono" | "sveltekit" | "worker" | "unknown"; export interface WranglerConfig { name: string; main?: string; compatibility_date: string; assets?: { directory: string; binding?: string; }; } const COMPATIBILITY_DATE = "2024-12-01"; export function generateWranglerConfig( projectType: ProjectType, projectName: string, entryPoint?: string, ): WranglerConfig { switch (projectType) { case "nextjs": return { name: projectName, main: ".open-next/worker.js", compatibility_date: COMPATIBILITY_DATE, assets: { directory: ".open-next/assets", binding: "ASSETS", }, }; case "vite": // Check if this is a Vite + Worker hybrid (has entryPoint) if (entryPoint) { // Hybrid mode: Vite frontend + custom Worker backend return { name: projectName, main: entryPoint, compatibility_date: COMPATIBILITY_DATE, assets: { directory: "./dist", binding: "ASSETS", }, }; } // Pure Vite SPAs use assets-only mode (no worker entry) // Cloudflare auto-generates a worker that serves static files return { name: projectName, compatibility_date: COMPATIBILITY_DATE, assets: { directory: "./dist", }, }; case "hono": return { name: projectName, main: entryPoint || "src/index.ts", compatibility_date: COMPATIBILITY_DATE, }; case "sveltekit": return { name: projectName, compatibility_date: COMPATIBILITY_DATE, assets: { directory: "./.svelte-kit/cloudflare", }, }; default: return { name: projectName, main: entryPoint || "src/index.ts", compatibility_date: COMPATIBILITY_DATE, }; } } export function writeWranglerConfig(projectPath: string, config: WranglerConfig): void { const header = "// wrangler.jsonc (auto-generated by jack)\n"; const json = JSON.stringify(config, null, 2); const content = `${header}${json}\n`; const filePath = path.join(projectPath, "wrangler.jsonc"); fs.writeFileSync(filePath, content, "utf-8"); } export function getDefaultProjectName(projectPath: string): string { const packageJsonPath = path.join(projectPath, "package.json"); if (fs.existsSync(packageJsonPath)) { try { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")); if (packageJson.name && typeof packageJson.name === "string") { const slugified = slugify(packageJson.name); if (slugified) { return slugified; } } } catch { // Fall through to folder name } } const folderName = path.basename(path.resolve(projectPath)); return slugify(folderName) || "my-project"; } export function slugify(name: string): string { return name .toLowerCase() .replace(/[\s_]+/g, "-") .replace(/[^a-z0-9-]/g, "") .replace(/-+/g, "-") .replace(/^-+|-+$/g, ""); }