From 5b13b04a20f369e611067807e76156fc3df029a6 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Thu, 6 Mar 2025 14:35:01 +0530 Subject: [PATCH] rename features to addons --- .changeset/early-falcons-itch.md | 5 +++ apps/cli/src/constants.ts | 2 +- .../{feature-setup.ts => addons-setup.ts} | 13 +++---- apps/cli/src/helpers/create-project.ts | 6 ++-- apps/cli/src/helpers/create-readme.ts | 4 +-- apps/cli/src/helpers/db-setup.ts | 1 - apps/cli/src/helpers/install-dependencies.ts | 3 +- apps/cli/src/index.ts | 18 +++++----- .../src/prompts/{features.ts => addons.ts} | 14 ++++---- apps/cli/src/prompts/config-prompts.ts | 10 +++--- apps/cli/src/prompts/install.ts | 2 +- apps/cli/src/types.ts | 4 +-- apps/cli/src/utils/display-config.ts | 4 +-- .../utils/generate-reproducible-command.ts | 8 ++--- .../app/(home)/_components/CodeContainer.tsx | 2 +- .../(home)/_components/CustomizableStack.tsx | 34 ++++++++----------- .../app/(home)/_components/TechSelector.tsx | 26 +++++++------- 17 files changed, 75 insertions(+), 81 deletions(-) create mode 100644 .changeset/early-falcons-itch.md rename apps/cli/src/helpers/{feature-setup.ts => addons-setup.ts} (93%) rename apps/cli/src/prompts/{features.ts => addons.ts} (65%) diff --git a/.changeset/early-falcons-itch.md b/.changeset/early-falcons-itch.md new file mode 100644 index 0000000..61f4b37 --- /dev/null +++ b/.changeset/early-falcons-itch.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": patch +--- + +rename features to addons diff --git a/apps/cli/src/constants.ts b/apps/cli/src/constants.ts index 61f5b2b..419447d 100644 --- a/apps/cli/src/constants.ts +++ b/apps/cli/src/constants.ts @@ -11,7 +11,7 @@ export const DEFAULT_CONFIG: ProjectConfig = { database: "sqlite", orm: "drizzle", auth: true, - features: [], + addons: [], git: true, packageManager: "npm", noInstall: false, diff --git a/apps/cli/src/helpers/feature-setup.ts b/apps/cli/src/helpers/addons-setup.ts similarity index 93% rename from apps/cli/src/helpers/feature-setup.ts rename to apps/cli/src/helpers/addons-setup.ts index 35ccc0c..39eadac 100644 --- a/apps/cli/src/helpers/feature-setup.ts +++ b/apps/cli/src/helpers/addons-setup.ts @@ -2,21 +2,18 @@ import path from "node:path"; import { log } from "@clack/prompts"; import fs from "fs-extra"; import pc from "picocolors"; -import type { ProjectFeature } from "../types"; +import type { ProjectAddons } from "../types"; -export async function setupFeatures( - projectDir: string, - features: ProjectFeature[], -) { - if (features.includes("docker")) { +export async function setupAddons(projectDir: string, addons: ProjectAddons[]) { + if (addons.includes("docker")) { await setupDocker(projectDir); } - if (features.includes("github-actions")) { + if (addons.includes("github-actions")) { await setupGithubActions(projectDir); } - if (features.includes("SEO")) { + if (addons.includes("SEO")) { log.info( pc.yellow( "SEO feature is still a work-in-progress and will be available in a future update.", diff --git a/apps/cli/src/helpers/create-project.ts b/apps/cli/src/helpers/create-project.ts index 32799cb..f270ef0 100644 --- a/apps/cli/src/helpers/create-project.ts +++ b/apps/cli/src/helpers/create-project.ts @@ -5,10 +5,10 @@ import fs from "fs-extra"; import pc from "picocolors"; import { PKG_ROOT } from "../constants"; import type { ProjectConfig } from "../types"; +import { setupAddons } from "./addons-setup"; import { configureAuth } from "./auth-setup"; import { createReadme } from "./create-readme"; import { setupDatabase } from "./db-setup"; -import { setupFeatures } from "./feature-setup"; import { displayPostInstallInstructions } from "./post-installation"; export async function createProject(options: ProjectConfig): Promise { @@ -92,8 +92,8 @@ export async function createProject(options: ProjectConfig): Promise { await $({ cwd: projectDir })`git init`; } - if (options.features.length > 0) { - await setupFeatures(projectDir, options.features); + if (options.addons.length > 0) { + await setupAddons(projectDir, options.addons); } const packageJsonPath = path.join(projectDir, "package.json"); diff --git a/apps/cli/src/helpers/create-readme.ts b/apps/cli/src/helpers/create-readme.ts index ee8d77d..857de25 100644 --- a/apps/cli/src/helpers/create-readme.ts +++ b/apps/cli/src/helpers/create-readme.ts @@ -19,7 +19,7 @@ function generateReadmeContent(options: ProjectConfig): string { packageManager, database, auth, - features = [], + addons = [], orm = "drizzle", } = options; @@ -32,7 +32,7 @@ This project was created with [Better-T-Stack](https://github.com/better-t-stack ## Features -${generateFeaturesList(database, auth, features, orm)} +${generateFeaturesList(database, auth, addons, orm)} ## Getting Started diff --git a/apps/cli/src/helpers/db-setup.ts b/apps/cli/src/helpers/db-setup.ts index 59fedf0..e3e27a8 100644 --- a/apps/cli/src/helpers/db-setup.ts +++ b/apps/cli/src/helpers/db-setup.ts @@ -15,7 +15,6 @@ export async function setupDatabase( if (databaseType === "none") { await fs.remove(path.join(serverDir, "src/db")); - log.info(pc.yellow("Database configuration removed")); return; } diff --git a/apps/cli/src/helpers/install-dependencies.ts b/apps/cli/src/helpers/install-dependencies.ts index 8e7d08c..256f29d 100644 --- a/apps/cli/src/helpers/install-dependencies.ts +++ b/apps/cli/src/helpers/install-dependencies.ts @@ -13,7 +13,6 @@ export async function installDependencies({ packageManager, }: InstallDependenciesOptions) { const s = spinner(); - log.info(pc.blue(`Installing dependencies using ${packageManager}...`)); try { s.start(`Running ${packageManager} install...`); @@ -34,7 +33,7 @@ export async function installDependencies({ break; } - s.stop(pc.green("Dependencies installed successfully")); + s.stop("Dependencies installed successfully"); } catch (error) { s.stop(pc.red("Failed to install dependencies")); if (error instanceof Error) { diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index 2c4cb76..4cae1bd 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -5,7 +5,7 @@ import { DEFAULT_CONFIG } from "./constants"; import { createProject } from "./helpers/create-project"; import { installDependencies } from "./helpers/install-dependencies"; import { gatherConfig } from "./prompts/config-prompts"; -import type { ProjectConfig, ProjectFeature } from "./types"; +import type { ProjectAddons, ProjectConfig } from "./types"; import { displayConfig } from "./utils/display-config"; import { generateReproducibleCommand } from "./utils/generate-reproducible-command"; import { getVersion } from "./utils/get-version"; @@ -33,7 +33,7 @@ async function main() { .option("--docker", "Include Docker setup") .option("--github-actions", "Include GitHub Actions") .option("--seo", "Include SEO setup") - .option("--no-features", "Skip all additional features") + .option("--no-addons", "Skip all additional addons") .option("--git", "Include git setup") .option("--no-git", "Skip git initialization") .option("--npm", "Use npm package manager") @@ -75,15 +75,15 @@ async function main() { ...((options.docker || options.githubActions || options.seo || - options.features === false) && { - features: - options.features === false + options.addons === false) && { + addons: + options.addons === false ? [] : ([ ...(options.docker ? ["docker"] : []), ...(options.githubActions ? ["github-actions"] : []), ...(options.seo ? ["SEO"] : []), - ] as ProjectFeature[]), + ] as ProjectAddons[]), }), }; @@ -117,9 +117,9 @@ async function main() { : DEFAULT_CONFIG.noInstall, packageManager: flagConfig.packageManager ?? DEFAULT_CONFIG.packageManager, - features: flagConfig.features?.length - ? flagConfig.features - : DEFAULT_CONFIG.features, + addons: flagConfig.addons?.length + ? flagConfig.addons + : DEFAULT_CONFIG.addons, turso: "turso" in options ? options.turso diff --git a/apps/cli/src/prompts/features.ts b/apps/cli/src/prompts/addons.ts similarity index 65% rename from apps/cli/src/prompts/features.ts rename to apps/cli/src/prompts/addons.ts index 8560c6e..ad46f6c 100644 --- a/apps/cli/src/prompts/features.ts +++ b/apps/cli/src/prompts/addons.ts @@ -1,14 +1,14 @@ import { cancel, isCancel, multiselect } from "@clack/prompts"; import pc from "picocolors"; -import type { ProjectFeature } from "../types"; +import type { ProjectAddons } from "../types"; -export async function getFeaturesChoice( - features?: ProjectFeature[], -): Promise { - if (features !== undefined) return features; +export async function getAddonsChoice( + Addons?: ProjectAddons[], +): Promise { + if (Addons !== undefined) return Addons; - const response = await multiselect({ - message: "Which features would you like to add?", + const response = await multiselect({ + message: "Which Addons would you like to add?", options: [ { value: "docker", diff --git a/apps/cli/src/prompts/config-prompts.ts b/apps/cli/src/prompts/config-prompts.ts index 8db4de3..eb0b31a 100644 --- a/apps/cli/src/prompts/config-prompts.ts +++ b/apps/cli/src/prompts/config-prompts.ts @@ -2,14 +2,14 @@ import { cancel, group } from "@clack/prompts"; import pc from "picocolors"; import type { PackageManager, + ProjectAddons, ProjectConfig, ProjectDatabase, - ProjectFeature, ProjectOrm, } from "../types"; +import { getAddonsChoice } from "./addons"; import { getAuthChoice } from "./auth"; import { getDatabaseChoice } from "./database"; -import { getFeaturesChoice } from "./features"; import { getGitChoice } from "./git"; import { getNoInstallChoice } from "./install"; import { getORMChoice } from "./orm"; @@ -22,7 +22,7 @@ interface PromptGroupResults { database: ProjectDatabase; orm: ProjectOrm; auth: boolean; - features: ProjectFeature[]; + addons: ProjectAddons[]; git: boolean; packageManager: PackageManager; noInstall: boolean; @@ -46,7 +46,7 @@ export async function gatherConfig( results.database === "sqlite" ? getTursoSetupChoice(flags.turso) : Promise.resolve(false), - features: () => getFeaturesChoice(flags.features), + addons: () => getAddonsChoice(flags.addons), git: () => getGitChoice(flags.git), packageManager: () => getPackageManagerChoice(flags.packageManager), noInstall: () => getNoInstallChoice(flags.noInstall), @@ -64,7 +64,7 @@ export async function gatherConfig( database: result.database, orm: result.orm, auth: result.auth, - features: result.features, + addons: result.addons, git: result.git, packageManager: result.packageManager, noInstall: result.noInstall, diff --git a/apps/cli/src/prompts/install.ts b/apps/cli/src/prompts/install.ts index 117c1dc..ec62f27 100644 --- a/apps/cli/src/prompts/install.ts +++ b/apps/cli/src/prompts/install.ts @@ -8,7 +8,7 @@ export async function getNoInstallChoice( if (noInstall !== undefined) return noInstall; const response = await confirm({ - message: "Install dependencies after creating project?", + message: "Install dependencies?", initialValue: !DEFAULT_CONFIG.noInstall, }); diff --git a/apps/cli/src/types.ts b/apps/cli/src/types.ts index cf4a527..f7b8bd0 100644 --- a/apps/cli/src/types.ts +++ b/apps/cli/src/types.ts @@ -1,14 +1,14 @@ export type ProjectDatabase = "sqlite" | "postgres" | "none"; export type ProjectOrm = "drizzle" | "prisma" | "none"; export type PackageManager = "npm" | "pnpm" | "yarn" | "bun"; -export type ProjectFeature = "docker" | "github-actions" | "SEO"; +export type ProjectAddons = "docker" | "github-actions" | "SEO"; export interface ProjectConfig { projectName: string; database: ProjectDatabase; orm: ProjectOrm; auth: boolean; - features: ProjectFeature[]; + addons: ProjectAddons[]; git: boolean; packageManager: PackageManager; noInstall?: boolean; diff --git a/apps/cli/src/utils/display-config.ts b/apps/cli/src/utils/display-config.ts index e497f3e..1f295a1 100644 --- a/apps/cli/src/utils/display-config.ts +++ b/apps/cli/src/utils/display-config.ts @@ -16,8 +16,8 @@ export function displayConfig(config: Partial) { if (config.auth !== undefined) { configDisplay.push(`${pc.blue("Authentication:")} ${config.auth}`); } - if (config.features?.length) { - configDisplay.push(`${pc.blue("Features:")} ${config.features.join(", ")}`); + if (config.addons?.length) { + configDisplay.push(`${pc.blue("Addons:")} ${config.addons.join(", ")}`); } if (config.git !== undefined) { configDisplay.push(`${pc.blue("Git Init:")} ${config.git}`); diff --git a/apps/cli/src/utils/generate-reproducible-command.ts b/apps/cli/src/utils/generate-reproducible-command.ts index ec9d91a..7a9a18d 100644 --- a/apps/cli/src/utils/generate-reproducible-command.ts +++ b/apps/cli/src/utils/generate-reproducible-command.ts @@ -41,12 +41,12 @@ export function generateReproducibleCommand(config: ProjectConfig): string { flags.push(`--${config.packageManager}`); } - if (config.features.length > 0) { - for (const feature of config.features) { - flags.push(`--${feature}`); + if (config.addons.length > 0) { + for (const addon of config.addons) { + flags.push(`--${addon}`); } } else { - flags.push("--no-features"); + flags.push("--no-addons"); } const baseCommand = "npx create-better-t-stack"; diff --git a/apps/web/src/app/(home)/_components/CodeContainer.tsx b/apps/web/src/app/(home)/_components/CodeContainer.tsx index 0817bb7..922b439 100644 --- a/apps/web/src/app/(home)/_components/CodeContainer.tsx +++ b/apps/web/src/app/(home)/_components/CodeContainer.tsx @@ -175,7 +175,7 @@ const CodeContainer = () => { yes

- Features:{" "} + Addons:{" "} docker, github-actions, SEO diff --git a/apps/web/src/app/(home)/_components/CustomizableStack.tsx b/apps/web/src/app/(home)/_components/CustomizableStack.tsx index 6eb9178..195e968 100644 --- a/apps/web/src/app/(home)/_components/CustomizableStack.tsx +++ b/apps/web/src/app/(home)/_components/CustomizableStack.tsx @@ -45,7 +45,7 @@ interface ActiveNodes { orm: string; auth: string; packageManager: string; - features: { + addons: { docker: boolean; githubActions: boolean; seo: boolean; @@ -62,7 +62,7 @@ const CustomizableStack = () => { orm: "drizzle", auth: "better-auth", packageManager: "npm", - features: { + addons: { docker: false, githubActions: false, seo: false, @@ -128,10 +128,10 @@ const CustomizableStack = () => { setActiveNodes((prev) => ({ ...prev, [category]: techId, - ...(category === "features" && { - features: { - ...prev.features, - [techId]: !prev.features[techId as keyof typeof prev.features], + ...(category === "addons" && { + addons: { + ...prev.addons, + [techId]: !prev.addons[techId as keyof typeof prev.addons], }, }), })); @@ -342,16 +342,15 @@ const CustomizableStack = () => { const command = "npx create-better-t-stack my-app"; const flags: string[] = []; - // Check if all defaults are being used const isAllDefaults = activeNodes.database === "sqlite" && activeNodes.auth === "better-auth" && activeNodes.orm === "drizzle" && activeNodes.packageManager === "npm" && - activeNodes.features.git === true && - !activeNodes.features.docker && - !activeNodes.features.githubActions && - !activeNodes.features.seo; + activeNodes.addons.git === true && + !activeNodes.addons.docker && + !activeNodes.addons.githubActions && + !activeNodes.addons.seo; // If using all defaults, just use -y flag if (isAllDefaults) { @@ -387,19 +386,19 @@ const CustomizableStack = () => { } // Feature flags - if (activeNodes.features.docker) { + if (activeNodes.addons.docker) { flags.push("--docker"); } - if (activeNodes.features.githubActions) { + if (activeNodes.addons.githubActions) { flags.push("--github-actions"); } - if (activeNodes.features.seo) { + if (activeNodes.addons.seo) { flags.push("--seo"); } - if (!activeNodes.features.git) { + if (!activeNodes.addons.git) { flags.push("--no-git"); } @@ -408,21 +407,17 @@ const CustomizableStack = () => { return (

- {/* Command Display - Fixed at top with proper centering */}
- {/* Main container with proper layout */}
- {/* Tech selector fixed to the left side */}
- {/* Help text */}
Select technologies from the left panel to customize your stack. The @@ -430,7 +425,6 @@ const CustomizableStack = () => {
- {/* Flow container with proper spacing from the selector */}
= { { id: "yarn", label: "Yarn", category: "packageManager" }, { id: "bun", label: "Bun", category: "packageManager" }, ], - features: [ - { id: "docker", label: "Docker", category: "features" }, - { id: "githubActions", label: "GitHub Actions", category: "features" }, - { id: "seo", label: "SEO", category: "features" }, - { id: "git", label: "Git", category: "features" }, + addons: [ + { id: "docker", label: "Docker", category: "addons" }, + { id: "githubActions", label: "GitHub Actions", category: "addons" }, + { id: "seo", label: "SEO", category: "addons" }, + { id: "git", label: "Git", category: "addons" }, ], }; @@ -60,7 +60,7 @@ export function TechSelector({ onSelect, activeNodes }: TechSelectorProps) { {/* Regular tech options */} {Object.entries(techOptions) - .filter(([category]) => category !== "features") + .filter(([category]) => category !== "addons") .map(([category, options]) => (
{category}
@@ -71,7 +71,7 @@ export function TechSelector({ onSelect, activeNodes }: TechSelectorProps) { variant="secondary" className={`cursor-pointer hover:bg-gray-700 ${ activeNodes[ - category as keyof Omit + category as keyof Omit ] === option.id && "bg-blue-600 text-white" }`} onClick={() => onSelect(category, option.id)} @@ -85,18 +85,18 @@ export function TechSelector({ onSelect, activeNodes }: TechSelectorProps) { {/* Feature toggles */}
-
Features
+
Addons
- {techOptions.features.map((option) => ( + {techOptions.addons.map((option) => ( onSelect("features", option.id)} + onClick={() => onSelect("addons", option.id)} > {option.label}