From 32919df73c30bf39383e2c8b0b84bdb721ba97da Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Thu, 21 Aug 2025 18:30:59 +0530 Subject: [PATCH] fix(cli): only prompt server deploy for hono+workers and restrict to wrangler/alchemy --- apps/cli/src/prompts/server-deploy.ts | 27 ++++++++----------- apps/cli/src/utils/config-validation.ts | 6 +++++ .../app/(home)/_components/stack-builder.tsx | 25 +++++++++++++++-- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/apps/cli/src/prompts/server-deploy.ts b/apps/cli/src/prompts/server-deploy.ts index cf6dd27..8e08457 100644 --- a/apps/cli/src/prompts/server-deploy.ts +++ b/apps/cli/src/prompts/server-deploy.ts @@ -49,19 +49,19 @@ export async function getServerDeploymentChoice( const options: DeploymentOption[] = []; - if (runtime === "workers") { - ["alchemy", "wrangler"].forEach((deploy) => { - const { label, hint } = getDeploymentDisplay(deploy as ServerDeploy); - options.unshift({ - value: deploy as ServerDeploy, - label, - hint, - }); - }); - } else { - options.push({ value: "none", label: "None", hint: "Manual setup" }); + if (runtime !== "workers") { + return "none"; } + ["alchemy", "wrangler"].forEach((deploy) => { + const { label, hint } = getDeploymentDisplay(deploy as ServerDeploy); + options.unshift({ + value: deploy as ServerDeploy, + label, + hint, + }); + }); + const response = await select({ message: "Select server deployment", options, @@ -114,11 +114,6 @@ export async function getServerDeploymentToAdd( } if (options.length > 0) { - options.push({ - value: "none", - label: "None", - hint: "Skip deployment setup", - }); } if (options.length === 0) { diff --git a/apps/cli/src/utils/config-validation.ts b/apps/cli/src/utils/config-validation.ts index 7440fce..e1e4d52 100644 --- a/apps/cli/src/utils/config-validation.ts +++ b/apps/cli/src/utils/config-validation.ts @@ -283,6 +283,12 @@ export function validateFullConfig( validateWorkersCompatibility(providedFlags, options, config); + if (config.runtime === "workers" && config.serverDeploy === "none") { + exitWithError( + "Cloudflare Workers runtime requires a server deployment. Please choose 'wrangler' or 'alchemy' for --server-deploy.", + ); + } + if (config.addons && config.addons.length > 0) { validateAddonsAgainstFrontends(config.addons, config.frontend); config.addons = [...new Set(config.addons)]; diff --git a/apps/web/src/app/(home)/_components/stack-builder.tsx b/apps/web/src/app/(home)/_components/stack-builder.tsx index b177be6..6ef10bd 100644 --- a/apps/web/src/app/(home)/_components/stack-builder.tsx +++ b/apps/web/src/app/(home)/_components/stack-builder.tsx @@ -164,6 +164,7 @@ function TechIcon({ return ( {`${name} { }); } + // Workers runtime requires a server deployment (wrangler or alchemy) + if (nextStack.serverDeploy === "none") { + notes.serverDeploy.notes.push( + "Cloudflare Workers runtime requires a server deployment. Wrangler will be selected.", + ); + notes.serverDeploy.hasIssue = true; + nextStack.serverDeploy = "wrangler"; + changed = true; + changes.push({ + category: "serverDeploy", + message: + "Server deployment set to 'Wrangler' (required by Cloudflare Workers)", + }); + } + if (nextStack.orm !== "drizzle" && nextStack.orm !== "none") { notes.runtime.notes.push( "Cloudflare Workers runtime requires Drizzle ORM or no ORM. Drizzle will be selected.", @@ -681,7 +697,6 @@ const analyzeStackCompatibility = (stack: StackState): CompatibilityResult => { notes.runtime.hasIssue = true; notes.dbSetup.hasIssue = true; nextStack.dbSetup = "d1"; - changed = true; changes.push({ category: "runtime", message: @@ -1811,7 +1826,13 @@ const StackBuilder = () => { TECH_OPTIONS[categoryKey as keyof typeof TECH_OPTIONS] || []; const categoryDisplayName = getCategoryDisplayName(categoryKey); - const filteredOptions = categoryOptions.filter(() => { + const filteredOptions = categoryOptions.filter((opt) => { + if ( + categoryKey === "serverDeploy" && + stack.runtime === "workers" + ) { + return opt.id === "wrangler" || opt.id === "alchemy"; + } return true; });