diff --git a/.changeset/purple-candles-brake.md b/.changeset/purple-candles-brake.md new file mode 100644 index 0000000..6475b33 --- /dev/null +++ b/.changeset/purple-candles-brake.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": minor +--- + +replace chalk with picocolors diff --git a/apps/cli/package.json b/apps/cli/package.json index 721212f..7e56c33 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -19,12 +19,12 @@ "files": ["dist", "templates"], "dependencies": { "@clack/prompts": "^0.10.0", - "chalk": "^5.3.0", "commander": "^13.1.0", "degit": "^2.8.4", "execa": "^8.0.1", "fs-extra": "^11.2.0", - "gradient-string": "^3.0.0" + "gradient-string": "^3.0.0", + "picocolors": "^1.1.1" }, "devDependencies": { "@types/degit": "^2.8.6", diff --git a/apps/cli/src/helpers/create-project.ts b/apps/cli/src/helpers/create-project.ts index d3a98ca..05da9f9 100644 --- a/apps/cli/src/helpers/create-project.ts +++ b/apps/cli/src/helpers/create-project.ts @@ -1,9 +1,9 @@ import path from "node:path"; import { cancel, confirm, isCancel, log, spinner, tasks } from "@clack/prompts"; -import chalk from "chalk"; import degit from "degit"; import { $ } from "execa"; import fs from "fs-extra"; +import pc from "picocolors"; import type { ProjectConfig } from "../types"; import { setupTurso } from "./db-setup"; @@ -29,9 +29,9 @@ export async function createProject(options: ProjectConfig) { }); await emitter.clone(projectDir); } catch (error) { - log.error("Failed to clone template repository"); + log.error(pc.red("Failed to clone template repository")); if (error instanceof Error) { - log.error(error.message); + log.error(pc.red(error.message)); } throw error; } @@ -57,39 +57,41 @@ export async function createProject(options: ProjectConfig) { } const installDepsResponse = await confirm({ - message: `šŸ“¦ Install dependencies with ${options.packageManager}?`, + message: `šŸ“¦ Install dependencies with ${pc.magenta(options.packageManager)}?`, }); if (isCancel(installDepsResponse)) { - cancel("Operation cancelled"); + cancel(pc.red("Operation cancelled")); process.exit(0); } shouldInstallDeps = installDepsResponse; if (shouldInstallDeps) { - s.start(`šŸ“¦ Installing dependencies using ${options.packageManager}...`); + s.start( + `šŸ“¦ Installing dependencies using ${pc.magenta(options.packageManager)}...`, + ); try { await $({ cwd: projectDir, })`${options.packageManager} install`; s.stop("āœ… Dependencies installed successfully"); } catch (error) { - s.stop("Failed to install dependencies"); + s.stop(pc.red("Failed to install dependencies")); if (error instanceof Error) { - log.error(`Installation error: ${error.message}`); + log.error(pc.red(`Installation error: ${error.message}`)); } throw error; } } - log.info(`${chalk.dim("Next steps:")} -cd ${options.projectName}${!shouldInstallDeps ? `\n${options.packageManager} install` : ""} -${options.packageManager === "npm" ? "npm run" : options.packageManager} dev`); + log.info(`${pc.dim("Next steps:")} +${pc.cyan("cd")} ${options.projectName}${!shouldInstallDeps ? `\n${pc.cyan(options.packageManager)} install` : ""} +${pc.cyan(options.packageManager === "npm" ? "npm run" : options.packageManager)} ${"dev"}`); } catch (error) { - s.stop("Failed"); + s.stop(pc.red("Failed")); if (error instanceof Error) { - log.error(`Error during project creation: ${error.message}`); + log.error(pc.red(`Error during project creation: ${error.message}`)); process.exit(1); } } diff --git a/apps/cli/src/helpers/db-setup.ts b/apps/cli/src/helpers/db-setup.ts index 08d259f..ba69396 100644 --- a/apps/cli/src/helpers/db-setup.ts +++ b/apps/cli/src/helpers/db-setup.ts @@ -3,19 +3,15 @@ import path from "node:path"; import { cancel, confirm, - group, - intro, isCancel, log, - multiselect, outro, - select, spinner, - tasks, text, } from "@clack/prompts"; import { $ } from "execa"; import fs from "fs-extra"; +import pc from "picocolors"; import { isTursoInstalled, isTursoLoggedIn } from "../utils/turso-cli"; interface TursoConfig { @@ -30,7 +26,7 @@ async function loginToTurso() { await $`turso auth login`; s.stop("āœ… Logged in to Turso successfully!"); } catch (error) { - s.stop("Failed to log in to Turso"); + s.stop(pc.red("Failed to log in to Turso")); throw error; } } @@ -52,10 +48,10 @@ async function installTursoCLI(isMac: boolean) { } catch (error) { if (error instanceof Error && error.message.includes("User force closed")) { s.stop(); - log.warn("Turso CLI installation cancelled by user"); + log.warn(pc.yellow("Turso CLI installation cancelled by user")); throw new Error("Installation cancelled"); } - s.stop("Failed to install Turso CLI"); + s.stop(pc.red("Failed to install Turso CLI")); throw error; } } @@ -91,14 +87,15 @@ TURSO_AUTH_TOKEN=`; } function displayManualSetupInstructions() { - 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"); - log.info("4. Add these credentials to the .env file in packages/server/.env"); - log.info("\nThe .env file has been created with placeholder variables:"); - log.info("TURSO_DATABASE_URL=your_database_url"); - log.info("TURSO_AUTH_TOKEN=your_auth_token"); + log.info(`šŸ”§ Manual Turso Setup Instructions: + +1. Visit https://turso.tech and create an account +2. Create a new database from the dashboard +3. Get your database URL and authentication token +4. Add these credentials to the .env file in packages/server/.env + +TURSO_DATABASE_URL=your_database_url +TURSO_AUTH_TOKEN=your_auth_token`); } export async function setupTurso(projectDir: string) { @@ -107,7 +104,7 @@ export async function setupTurso(projectDir: string) { const canInstallCLI = platform !== "win32"; if (!canInstallCLI) { - log.warn("Automatic Turso setup is not supported on Windows."); + log.warn(pc.yellow("Automatic Turso setup is not supported on Windows.")); await writeEnvFile(projectDir); displayManualSetupInstructions(); return; @@ -122,7 +119,7 @@ export async function setupTurso(projectDir: string) { }); if (isCancel(shouldInstall)) { - cancel("Operation cancelled"); + cancel(pc.red("Operation cancelled")); process.exit(0); } @@ -144,7 +141,7 @@ export async function setupTurso(projectDir: string) { } s.stop("āœ… Turso CLI installed successfully!"); } catch (error) { - s.stop("Failed to install Turso CLI"); + s.stop(pc.red("Failed to install Turso CLI")); throw error; } } @@ -157,7 +154,7 @@ export async function setupTurso(projectDir: string) { await $`turso auth login`; s.stop("āœ… Logged in to Turso successfully!"); } catch (error) { - s.stop("Failed to log in to Turso"); + s.stop(pc.red("Failed to log in to Turso")); throw error; } } @@ -175,7 +172,7 @@ export async function setupTurso(projectDir: string) { }); if (isCancel(dbNameResponse)) { - cancel("Operation cancelled"); + cancel(pc.red("Operation cancelled")); process.exit(0); } @@ -190,7 +187,7 @@ export async function setupTurso(projectDir: string) { success = true; } catch (error) { if (error instanceof Error && error.message === "DATABASE_EXISTS") { - s.stop(`Database "${dbName}" already exists`); + s.stop(pc.yellow(`Database "${pc.red(dbName)}" already exists`)); suggestedName = `${dbName}-${Math.floor(Math.random() * 1000)}`; } else { throw error; @@ -198,9 +195,9 @@ export async function setupTurso(projectDir: string) { } } } catch (error) { - log.error(`Error during Turso setup: ${error}`); + log.error(pc.red(`Error during Turso setup: ${error}`)); await writeEnvFile(projectDir); displayManualSetupInstructions(); - outro("Setup completed with manual configuration required."); + log.success("Setup completed with manual configuration required."); } } diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index 169603d..a7be429 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -11,12 +11,11 @@ import { spinner, text, } from "@clack/prompts"; -import chalk from "chalk"; import { Command } from "commander"; import fs from "fs-extra"; +import pc from "picocolors"; import { DEFAULT_CONFIG } from "./consts"; import { createProject } from "./helpers/create-project"; -import { renderTitle } from "./render-title"; import type { PackageManager, ProjectConfig, @@ -26,9 +25,10 @@ import type { import { generateReproducibleCommand } from "./utils/generate-reproducible-command"; import { getUserPkgManager } from "./utils/get-package-manager"; import { getVersion } from "./utils/get-version"; +import { renderTitle } from "./utils/render-title"; process.on("SIGINT", () => { - log.error("Operation cancelled"); + log.error(pc.red("Operation cancelled")); process.exit(0); }); @@ -74,7 +74,7 @@ async function gatherConfig( }); if (typeof response === "symbol") { - cancel("Operation cancelled."); + cancel(pc.red("Operation cancelled.")); process.exit(0); } @@ -178,7 +178,7 @@ async function gatherConfig( }, { onCancel: () => { - cancel("Operation cancelled."); + cancel(pc.red("Operation cancelled.")); process.exit(0); }, }, @@ -198,33 +198,25 @@ function displayConfig(config: Partial) { const configDisplay = []; if (config.projectName) { - configDisplay.push( - `${chalk.blue("šŸ“ Project Name: ")}${chalk.green(config.projectName)}`, - ); + configDisplay.push(`${pc.blue("šŸ“ Project Name:")} ${config.projectName}`); } if (config.database) { - configDisplay.push( - `${chalk.blue("šŸ’¾ Database: ")}${chalk.yellow(config.database)}`, - ); + configDisplay.push(`${pc.blue("šŸ’¾ Database:")} ${config.database}`); } if (config.auth !== undefined) { - configDisplay.push( - `${chalk.blue("šŸ” Authentication: ")}${chalk.cyan(config.auth)}`, - ); + configDisplay.push(`${pc.blue("šŸ” Authentication:")} ${config.auth}`); } if (config.features?.length) { configDisplay.push( - `${chalk.blue("✨ Features: ")}${config.features.map((f) => chalk.magenta(f)).join(", ")}`, + `${pc.blue("✨ Features:")} ${config.features.join(", ")}`, ); } if (config.git !== undefined) { - configDisplay.push( - `${chalk.blue("šŸ—ƒļø Git Init: ")}${chalk.cyan(config.git)}`, - ); + configDisplay.push(`${pc.blue("šŸ—ƒļø Git Init:")} ${config.git}`); } if (config.packageManager) { configDisplay.push( - `${chalk.blue("šŸ“¦ Package Manager: ")}${chalk.yellow(config.packageManager)}`, + `${pc.blue("šŸ“¦ Package Manager:")} ${config.packageManager}`, ); } @@ -236,7 +228,7 @@ async function main() { try { process.stdout.write("\x1Bc"); renderTitle(); - intro(chalk.bold("✨ Creating a new Better-T-Stack project")); + intro(pc.magenta("✨ Creating a new Better-T-Stack project")); program .name("create-better-t-stack") .description("Create a new Better-T Stack project") @@ -288,7 +280,7 @@ async function main() { !options.yes && Object.values(flagConfig).some((v) => v !== undefined) ) { - log.message(chalk.bold("\nšŸŽÆ Using these pre-selected options:")); + log.info(pc.yellow("šŸŽÆ Using these pre-selected options:")); log.message(displayConfig(flagConfig)); log.message(""); } @@ -312,22 +304,26 @@ async function main() { : await gatherConfig(flagConfig); if (options.yes) { - log.message(chalk.bold("\nšŸŽÆ Using these default options:")); + log.info(pc.yellow("šŸŽÆ Using these default options:")); log.message(displayConfig(config)); log.message(""); } await createProject(config); - log.info( - `You can reproduce this setup with the following command:\n${generateReproducibleCommand(config)}`, + log.success( + pc.blue( + `You can reproduce this setup with the following command:\n${pc.white( + generateReproducibleCommand(config), + )}`, + ), ); - outro("šŸŽ‰ Project created successfully!"); + outro(pc.magenta("šŸŽ‰ Project created successfully!")); } catch (error) { - s.stop("Failed"); + s.stop(pc.red("Failed")); if (error instanceof Error) { - cancel("An unexpected error occurred"); + cancel(pc.red("An unexpected error occurred")); process.exit(1); } } diff --git a/apps/cli/src/utils/generate-reproducible-command.ts b/apps/cli/src/utils/generate-reproducible-command.ts index df5fb66..8d22300 100644 --- a/apps/cli/src/utils/generate-reproducible-command.ts +++ b/apps/cli/src/utils/generate-reproducible-command.ts @@ -1,4 +1,3 @@ -import chalk from "chalk"; import { DEFAULT_CONFIG } from "../consts"; import type { ProjectConfig } from "../types"; @@ -12,37 +11,34 @@ export function generateReproducibleCommand(config: ProjectConfig): string { }); if (isMainlyDefault) { - flags.push(chalk.gray("-y")); + flags.push("-y"); } if (config.database !== DEFAULT_CONFIG.database) { - flags.push(chalk.cyan(`--database ${config.database}`)); + flags.push(`--database ${config.database}`); } if (config.auth !== DEFAULT_CONFIG.auth) { - flags.push(chalk.yellow("--no-auth")); + flags.push("--no-auth"); } if (!config.git) { - flags.push(chalk.red("--no-git")); + flags.push("--no-git"); } - // Updated package manager flag handling if ( config.packageManager && config.packageManager !== DEFAULT_CONFIG.packageManager ) { - flags.push(chalk.magenta(`--${config.packageManager}`)); + flags.push(`--${config.packageManager}`); } for (const feature of config.features) { - flags.push(chalk.green(`--${feature}`)); + flags.push(`--${feature}`); } - const baseCommand = chalk.bold("npx create-better-t-stack"); - const projectName = config.projectName - ? chalk.blue(` ${config.projectName}`) - : ""; + const baseCommand = "npx create-better-t-stack"; + const projectName = config.projectName ? ` ${config.projectName}` : ""; const flagString = flags.length > 0 ? ` ${flags.join(" ")}` : ""; return `${baseCommand}${projectName}${flagString}`; diff --git a/apps/cli/src/render-title.ts b/apps/cli/src/utils/render-title.ts similarity index 100% rename from apps/cli/src/render-title.ts rename to apps/cli/src/utils/render-title.ts diff --git a/bun.lock b/bun.lock index e3b7535..d4da113 100644 --- a/bun.lock +++ b/bun.lock @@ -14,18 +14,18 @@ }, "apps/cli": { "name": "create-better-t-stack", - "version": "0.6.1", + "version": "0.6.2", "bin": { "create-better-t-stack": "dist/index.js" }, "dependencies": { "@clack/prompts": "^0.10.0", - "chalk": "^5.3.0", "commander": "^13.1.0", "degit": "^2.8.4", "execa": "^8.0.1", "fs-extra": "^11.2.0", "gradient-string": "^3.0.0", + "picocolors": "^1.1.1", }, "devDependencies": { "@types/degit": "^2.8.6",