From 31f12717ee2652b33e386882365dd76526f4f923 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Fri, 14 Feb 2025 00:14:04 +0530 Subject: [PATCH] improve prompts --- .changeset/beige-mugs-wash.md | 5 ++ apps/cli/src/consts.ts | 22 ------- apps/cli/src/helpers/create-project.ts | 25 +++----- apps/cli/src/helpers/db-setup.ts | 26 ++++----- apps/cli/src/index.ts | 57 ++++++++++--------- apps/cli/src/render-title.ts | 23 +++++++- .../utils/generate-reproducible-command.ts | 10 ++++ 7 files changed, 88 insertions(+), 80 deletions(-) create mode 100644 .changeset/beige-mugs-wash.md diff --git a/.changeset/beige-mugs-wash.md b/.changeset/beige-mugs-wash.md new file mode 100644 index 0000000..73ddda5 --- /dev/null +++ b/.changeset/beige-mugs-wash.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": patch +--- + +Improve prompts diff --git a/apps/cli/src/consts.ts b/apps/cli/src/consts.ts index 05f1b5a..4232374 100644 --- a/apps/cli/src/consts.ts +++ b/apps/cli/src/consts.ts @@ -2,28 +2,6 @@ import path from "node:path"; import { fileURLToPath } from "node:url"; import type { ProjectConfig } from "./types"; -export const TITLE_TEXT = ` - ╔════════════════════════════════════════════════════════════╗ - ║ ║ - ║ ██████╗ ███████╗████████╗████████╗███████╗██████╗ ║ - ║ ██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗ ║ - ║ ██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝ ║ - ║ ██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗ ║ - ║ ██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║ ║ - ║ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ║ - ║ ║ - ║ ████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗ ║ - ║ ╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝ ║ - ║ ██║ ███████╗ ██║ ███████║██║ █████╔╝ ║ - ║ ██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗ ║ - ║ ██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗ ║ - ║ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ║ - ║ ║ - ║ The Modern Full-Stack Framework ║ - ║ ║ - ╚════════════════════════════════════════════════════════════╝ - `; - const __filename = fileURLToPath(import.meta.url); const distPath = path.dirname(__filename); export const PKG_ROOT = path.join(distPath, "../"); diff --git a/apps/cli/src/helpers/create-project.ts b/apps/cli/src/helpers/create-project.ts index 065098d..e874241 100644 --- a/apps/cli/src/helpers/create-project.ts +++ b/apps/cli/src/helpers/create-project.ts @@ -14,13 +14,13 @@ export async function createProject(options: ProjectConfig) { try { const tasksList = [ { - title: "Creating project directory", + title: "📁 Creating project directory", task: async () => { await fs.ensureDir(projectDir); }, }, { - title: "Cloning template repository", + title: "📥 Cloning template repository", task: async () => { try { await $`npx degit AmanVarshney01/Better-T-Stack ${projectDir}`; @@ -37,7 +37,7 @@ export async function createProject(options: ProjectConfig) { if (options.git) { tasksList.push({ - title: "Initializing git repository", + title: "🗃️ Initializing git repository", task: async () => { await $`git init ${projectDir}`; }, @@ -51,7 +51,7 @@ export async function createProject(options: ProjectConfig) { } const installDepsResponse = await confirm({ - message: `📦 Install dependencies using ${options.packageManager}?`, + message: `📦 Install dependencies with ${options.packageManager}?`, }); if (isCancel(installDepsResponse)) { @@ -62,13 +62,13 @@ export async function createProject(options: ProjectConfig) { shouldInstallDeps = installDepsResponse; if (shouldInstallDeps) { - s.start(`Installing dependencies using ${options.packageManager}...`); + s.start(`📦 Installing dependencies using ${options.packageManager}...`); try { await $({ cwd: projectDir, stdio: "inherit", })`${options.packageManager} install`; - s.stop("Dependencies installed successfully"); + s.stop("✅ Dependencies installed successfully"); } catch (error) { s.stop("Failed to install dependencies"); if (error instanceof Error) { @@ -79,16 +79,9 @@ export async function createProject(options: ProjectConfig) { } log.success("✨ Project created successfully!\n"); - log.info(chalk.dim("Next steps:")); - log.info(` cd ${options.projectName}`); - if (!shouldInstallDeps) { - log.info(` ${options.packageManager} install`); - } - log.info( - ` ${ - options.packageManager === "npm" ? "npm run" : options.packageManager - } dev`, - ); + log.info(`${chalk.dim("Next steps:")} +cd ${options.projectName}${!shouldInstallDeps ? `\n${options.packageManager} install` : ""} +${options.packageManager === "npm" ? "npm run" : options.packageManager} dev`); } catch (error) { s.stop("Failed"); if (error instanceof Error) { diff --git a/apps/cli/src/helpers/db-setup.ts b/apps/cli/src/helpers/db-setup.ts index 77b672a..08d259f 100644 --- a/apps/cli/src/helpers/db-setup.ts +++ b/apps/cli/src/helpers/db-setup.ts @@ -26,9 +26,9 @@ interface TursoConfig { async function loginToTurso() { const s = spinner(); try { - s.start("Logging in to Turso..."); + s.start("🔄 Logging in to Turso..."); await $`turso auth login`; - s.stop("Logged in to Turso successfully!"); + s.stop("✅ Logged in to Turso successfully!"); } catch (error) { s.stop("Failed to log in to Turso"); throw error; @@ -38,7 +38,7 @@ async function loginToTurso() { async function installTursoCLI(isMac: boolean) { const s = spinner(); try { - s.start("Installing Turso CLI..."); + s.start("🔄 Installing Turso CLI..."); if (isMac) { await $`brew install tursodatabase/tap/turso`; @@ -48,7 +48,7 @@ async function installTursoCLI(isMac: boolean) { await $`bash -c '${installScript}'`; } - s.stop("Turso CLI installed successfully!"); + s.stop("✅ Turso CLI installed successfully!"); } catch (error) { if (error instanceof Error && error.message.includes("User force closed")) { s.stop(); @@ -91,7 +91,7 @@ TURSO_AUTH_TOKEN=`; } function displayManualSetupInstructions() { - log.info("📝 Manual Turso Setup Instructions:"); + log.info("🔧 Manual Turso Setup Instructions:"); log.info("1. Visit https://turso.tech and create an account"); log.info("2. Create a new database from the dashboard"); log.info("3. Get your database URL and authentication token"); @@ -118,7 +118,7 @@ export async function setupTurso(projectDir: string) { if (!isCliInstalled) { const shouldInstall = await confirm({ - message: "Would you like to install Turso CLI?", + message: "🔧 Would you like to install Turso CLI?", }); if (isCancel(shouldInstall)) { @@ -133,7 +133,7 @@ export async function setupTurso(projectDir: string) { } const s = spinner(); - s.start("Installing Turso CLI..."); + s.start("🔄 Installing Turso CLI..."); try { if (isMac) { await $`brew install tursodatabase/tap/turso`; @@ -142,7 +142,7 @@ export async function setupTurso(projectDir: string) { await $`curl -sSfL https://get.tur.so/install.sh`; await $`bash -c '${installScript}'`; } - s.stop("Turso CLI installed successfully!"); + s.stop("✅ Turso CLI installed successfully!"); } catch (error) { s.stop("Failed to install Turso CLI"); throw error; @@ -152,10 +152,10 @@ export async function setupTurso(projectDir: string) { const isLoggedIn = await isTursoLoggedIn(); if (!isLoggedIn) { const s = spinner(); - s.start("Logging in to Turso..."); + s.start("🔄 Logging in to Turso..."); try { await $`turso auth login`; - s.stop("Logged in to Turso successfully!"); + s.stop("✅ Logged in to Turso successfully!"); } catch (error) { s.stop("Failed to log in to Turso"); throw error; @@ -168,7 +168,7 @@ export async function setupTurso(projectDir: string) { while (!success) { const dbNameResponse = await text({ - message: "Enter database name:", + message: "📝 Enter a name for your database:", defaultValue: suggestedName, initialValue: suggestedName, placeholder: suggestedName, @@ -183,10 +183,10 @@ export async function setupTurso(projectDir: string) { const s = spinner(); try { - s.start(`Creating Turso database "${dbName}"...`); + s.start(`🔄 Creating Turso database "${dbName}"...`); const config = await createTursoDatabase(dbName); await writeEnvFile(projectDir, config); - s.stop("Turso database configured successfully!"); + s.stop("✅ Turso database configured successfully!"); success = true; } catch (error) { if (error instanceof Error && error.message === "DATABASE_EXISTS") { diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index 9411e54..2aa4f89 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -52,7 +52,7 @@ async function gatherConfig( while (!isValid) { const response = await text({ - message: "📝 Project name", + message: "📝 What is your project named? (directory name or path)", placeholder: defaultName, initialValue: flags.projectName, defaultValue: defaultName, @@ -85,17 +85,17 @@ async function gatherConfig( database: () => !flags.database ? select({ - message: "💾 Select database", + message: "💾 Which database would you like to use?", options: [ { value: "libsql", label: "libSQL", - hint: "✨ (Recommended) - Turso's embedded SQLite database", + hint: "Turso's embedded SQLite database (recommended)", }, { value: "postgres", label: "PostgreSQL", - hint: "🐘 Traditional relational database", + hint: "Traditional relational database", }, ], }) @@ -103,28 +103,29 @@ async function gatherConfig( auth: () => flags.auth === undefined ? confirm({ - message: "🔐 Add authentication with Better-Auth?", + message: + "🔐 Would you like to add authentication with Better-Auth?", }) : Promise.resolve(flags.auth), features: () => !flags.features ? multiselect({ - message: "🎯 Select additional features", + message: "✨ Which features would you like to add?", options: [ { value: "docker", label: "Docker setup", - hint: "🐳 Containerize your application", + hint: "Containerize your application", }, { value: "github-actions", label: "GitHub Actions", - hint: "⚡ CI/CD workflows", + hint: "CI/CD workflows", }, { value: "SEO", label: "Basic SEO setup", - hint: "🔍 Search engine optimization configuration", + hint: "Search engine optimization configuration", }, ], }) @@ -132,7 +133,7 @@ async function gatherConfig( git: () => flags.git !== false ? confirm({ - message: "🗃️ Initialize Git repository?", + message: "🗃️ Initialize a new git repository?", initialValue: true, }) : Promise.resolve(false), @@ -140,20 +141,15 @@ async function gatherConfig( const detectedPackageManager = getUserPkgManager(); const useDetected = await confirm({ - message: `📦 Use detected package manager (${detectedPackageManager})?`, + message: `📦 Use ${detectedPackageManager} as your package manager?`, }); if (useDetected) return detectedPackageManager; return select({ - message: "📦 Select package manager", + message: "📦 Which package manager would you like to use?", options: [ { value: "npm", label: "npm", hint: "Node Package Manager" }, - { - value: "bun", - label: "bun", - hint: "All-in-one JavaScript runtime & toolkit (recommended)", - }, { value: "pnpm", label: "pnpm", @@ -164,7 +160,13 @@ async function gatherConfig( label: "yarn", hint: "Fast, reliable, and secure dependency management", }, + { + value: "bun", + label: "bun", + hint: "All-in-one JavaScript runtime & toolkit (recommended)", + }, ], + initialValue: "bun", }); }, }, @@ -191,7 +193,7 @@ async function main() { try { process.stdout.write("\x1Bc"); renderTitle(); - intro(chalk.bold("Creating a new Better-T Stack project")); + intro(chalk.bold("✨ Creating a new Better-T-Stack project")); program .name("create-better-t-stack") .description("Create a new Better-T Stack project") @@ -256,15 +258,15 @@ async function main() { }; log.message( - `${chalk.blue("Project Name: ")}${ + `${chalk.blue("📝 Project Name: ")}${ colorizedConfig.projectName - }\n${chalk.blue("Database: ")}${colorizedConfig.database}\n${chalk.blue( - "Authentication: ", - )}${colorizedConfig.auth}\n${chalk.blue("Features: ")}${ + }\n${chalk.blue("💾 Database: ")}${colorizedConfig.database}\n${chalk.blue( + "🔐 Authentication: ", + )}${colorizedConfig.auth}\n${chalk.blue("✨ Features: ")}${ colorizedConfig.features.length ? colorizedConfig.features.join(", ") : chalk.gray("none") - }\n${chalk.blue("Git Init: ")}${colorizedConfig.git}\n`, + }\n${chalk.blue("🗃️ Git Init: ")}${colorizedConfig.git}\n`, ); s.stop("Configuration loaded"); @@ -272,12 +274,11 @@ async function main() { await createProject(config); - log.message("You can reproduce this setup with the following command:", { - symbol: chalk.cyan("🔄"), - }); - log.info(generateReproducibleCommand(config)); + log.info( + `You can reproduce this setup with the following command:\n${generateReproducibleCommand(config)}`, + ); - outro("Project created successfully! 🎉"); + outro("🎉 Project created successfully!"); } catch (error) { s.stop("Failed"); if (error instanceof Error) { diff --git a/apps/cli/src/render-title.ts b/apps/cli/src/render-title.ts index 0c7b1fb..ab5bdaf 100644 --- a/apps/cli/src/render-title.ts +++ b/apps/cli/src/render-title.ts @@ -1,5 +1,26 @@ import gradient from "gradient-string"; -import { TITLE_TEXT } from "./consts"; + +export const TITLE_TEXT = ` + ╔════════════════════════════════════════════════════════════╗ + ║ ║ + ║ ██████╗ ███████╗████████╗████████╗███████╗██████╗ ║ + ║ ██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗ ║ + ║ ██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝ ║ + ║ ██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗ ║ + ║ ██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║ ║ + ║ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ║ + ║ ║ + ║ ████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗ ║ + ║ ╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝ ║ + ║ ██║ ███████╗ ██║ ███████║██║ █████╔╝ ║ + ║ ██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗ ║ + ║ ██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗ ║ + ║ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ║ + ║ ║ + ║ The Modern Full-Stack Framework ║ + ║ ║ + ╚════════════════════════════════════════════════════════════╝ + `; const catppuccinTheme = { rosewater: "#F5E0DC", diff --git a/apps/cli/src/utils/generate-reproducible-command.ts b/apps/cli/src/utils/generate-reproducible-command.ts index af725e3..4ea5bfe 100644 --- a/apps/cli/src/utils/generate-reproducible-command.ts +++ b/apps/cli/src/utils/generate-reproducible-command.ts @@ -5,6 +5,16 @@ import type { ProjectConfig } from "../types"; export function generateReproducibleCommand(config: ProjectConfig): string { const flags: string[] = []; + const isMainlyDefault = Object.entries(config).every(([key, value]) => { + if (key === "projectName") return true; + if (key === "features" && Array.isArray(value)) return value.length === 0; + return value === DEFAULT_CONFIG[key as keyof ProjectConfig]; + }); + + if (isMainlyDefault) { + flags.push(chalk.gray("-y")); + } + if (config.database !== DEFAULT_CONFIG.database) { flags.push(chalk.cyan(`--database ${config.database}`)); }