Prevent web-deploy when no web frontend is selected

This commit is contained in:
Aman Varshney
2025-07-07 18:07:36 +05:30
parent dd31abd190
commit d344b85922
6 changed files with 64 additions and 15 deletions

View File

@@ -0,0 +1,5 @@
---
"create-better-t-stack": patch
---
Prevent web-deploy when no web frontend is selected

View File

@@ -1,6 +1,6 @@
import path from "node:path"; import path from "node:path";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import type { ProjectConfig } from "./types"; import type { ProjectConfig, Frontend } from "./types";
import { getUserPkgManager } from "./utils/get-package-manager"; import { getUserPkgManager } from "./utils/get-package-manager";
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
@@ -126,3 +126,14 @@ export const ADDON_COMPATIBILITY = {
starlight: [], starlight: [],
none: [], none: [],
} as const; } as const;
// TODO: need to refactor this
export const WEB_FRAMEWORKS: readonly Frontend[] = [
"tanstack-router",
"react-router",
"tanstack-start",
"next",
"nuxt",
"svelte",
"solid",
];

View File

@@ -1,8 +1,12 @@
import { cancel, isCancel, select } from "@clack/prompts"; import { cancel, isCancel, select } from "@clack/prompts";
import pc from "picocolors"; import pc from "picocolors";
import { DEFAULT_CONFIG } from "../constants"; import { DEFAULT_CONFIG, WEB_FRAMEWORKS } from "../constants";
import type { Backend, Frontend, Runtime, WebDeploy } from "../types"; import type { Backend, Frontend, Runtime, WebDeploy } from "../types";
function hasWebFrontend(frontends: Frontend[]): boolean {
return frontends.some((f) => WEB_FRAMEWORKS.includes(f));
}
type DeploymentOption = { type DeploymentOption = {
value: WebDeploy; value: WebDeploy;
label: string; label: string;
@@ -29,9 +33,12 @@ export async function getDeploymentChoice(
deployment?: WebDeploy, deployment?: WebDeploy,
_runtime?: Runtime, _runtime?: Runtime,
_backend?: Backend, _backend?: Backend,
_frontend: Frontend[] = [], frontend: Frontend[] = [],
): Promise<WebDeploy> { ): Promise<WebDeploy> {
if (deployment !== undefined) return deployment; if (deployment !== undefined) return deployment;
if (!hasWebFrontend(frontend)) {
return "none";
}
const options: DeploymentOption[] = [ const options: DeploymentOption[] = [
{ {
@@ -57,9 +64,13 @@ export async function getDeploymentChoice(
} }
export async function getDeploymentToAdd( export async function getDeploymentToAdd(
_frontend: Frontend[], frontend: Frontend[],
existingDeployment?: WebDeploy, existingDeployment?: WebDeploy,
): Promise<WebDeploy> { ): Promise<WebDeploy> {
if (!hasWebFrontend(frontend)) {
return "none";
}
const options: DeploymentOption[] = []; const options: DeploymentOption[] = [];
if (existingDeployment !== "workers") { if (existingDeployment !== "workers") {

View File

@@ -16,6 +16,7 @@ import {
type Runtime, type Runtime,
type WebDeploy, type WebDeploy,
} from "./types"; } from "./types";
import { WEB_FRAMEWORKS } from "./constants";
export function processAndValidateFlags( export function processAndValidateFlags(
options: CLIInput, options: CLIInput,
@@ -125,15 +126,8 @@ export function processAndValidateFlags(
const validOptions = options.frontend.filter( const validOptions = options.frontend.filter(
(f): f is Frontend => f !== "none", (f): f is Frontend => f !== "none",
); );
const webFrontends = validOptions.filter( const webFrontends = validOptions.filter((f) =>
(f) => WEB_FRAMEWORKS.includes(f),
f === "tanstack-router" ||
f === "react-router" ||
f === "tanstack-start" ||
f === "next" ||
f === "nuxt" ||
f === "svelte" ||
f === "solid",
); );
const nativeFrontends = validOptions.filter( const nativeFrontends = validOptions.filter(
(f) => f === "native-nativewind" || f === "native-unistyles", (f) => f === "native-nativewind" || f === "native-unistyles",
@@ -451,6 +445,16 @@ export function processAndValidateFlags(
process.exit(1); process.exit(1);
} }
const hasWebFrontendFlag = (config.frontend ?? []).some((f) =>
WEB_FRAMEWORKS.includes(f),
);
if (config.webDeploy && config.webDeploy !== "none" && !hasWebFrontendFlag) {
consola.fatal(
"'--web-deploy' requires a web frontend. Please select a web frontend or set '--web-deploy none'.",
);
process.exit(1);
}
return config; return config;
} }

View File

@@ -68,7 +68,7 @@ import { drizzleAdapter } from "better-auth/adapters/drizzle";
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}} {{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
import { expo } from "@better-auth/expo"; import { expo } from "@better-auth/expo";
{{/if}} {{/if}}
import { db } from "@/db"; import { db } from "../db";
import * as schema from "../db/schema/auth"; import * as schema from "../db/schema/auth";
import { env } from "cloudflare:workers"; import { env } from "cloudflare:workers";

View File

@@ -805,6 +805,24 @@ const analyzeStackCompatibility = (stack: StackState): CompatibilityResult => {
} }
} }
const webFrontendsSelected = nextStack.webFrontend.some((f) => f !== "none");
if (!webFrontendsSelected && nextStack.webDeploy !== "none") {
notes.webDeploy.notes.push(
"Web deployment requires a web frontend. It will be disabled.",
);
notes.webFrontend.notes.push(
"No web frontend selected: Deployment has been disabled.",
);
notes.webDeploy.hasIssue = true;
notes.webFrontend.hasIssue = true;
nextStack.webDeploy = "none";
changed = true;
changes.push({
category: "webDeploy",
message: "Web deployment set to 'none' (requires web frontend)",
});
}
return { return {
adjustedStack: changed ? nextStack : null, adjustedStack: changed ? nextStack : null,
notes, notes,