feat: add Ctrl+C interrupt handling

This commit is contained in:
Aman Varshney
2025-02-12 12:49:16 +05:30
parent 78340fca07
commit cc8850d7c2
4 changed files with 101 additions and 58 deletions

View File

@@ -4,6 +4,7 @@ import fs from "fs-extra";
import ora from "ora"; import ora from "ora";
import { setupTurso } from "./helpers/db-setup"; import { setupTurso } from "./helpers/db-setup";
import type { ProjectOptions } from "./types"; import type { ProjectOptions } from "./types";
import { logger } from "./utils/logger";
export async function createProject(options: ProjectOptions) { export async function createProject(options: ProjectOptions) {
const spinner = ora("Creating project directory...").start(); const spinner = ora("Creating project directory...").start();
@@ -41,7 +42,7 @@ export async function createProject(options: ProjectOptions) {
console.log(" bun dev"); console.log(" bun dev");
} catch (error) { } catch (error) {
spinner.fail("Failed to create project"); spinner.fail("Failed to create project");
console.error(error); logger.error("Error during project creation:", error);
process.exit(1); process.exit(1);
} }
} }

View File

@@ -4,6 +4,7 @@ import { confirm, input } from "@inquirer/prompts";
import { execa } from "execa"; import { execa } from "execa";
import fs from "fs-extra"; import fs from "fs-extra";
import ora, { type Ora } from "ora"; import ora, { type Ora } from "ora";
import { logger } from "../utils/logger";
async function isTursoInstalled() { async function isTursoInstalled() {
try { try {
@@ -48,10 +49,18 @@ async function installTursoCLI(isMac: boolean, spinner: Ora) {
await execa("turso", ["auth", "login"]); await execa("turso", ["auth", "login"]);
spinner.succeed("Logged in to Turso!"); spinner.succeed("Logged in to Turso!");
} catch (error) { } catch (error) {
console.error(error); if (error instanceof Error && error.message.includes("User force closed")) {
spinner.stop();
console.log("\n");
logger.warn("Turso CLI installation cancelled by user");
throw error;
}
logger.error("Error during Turso CLI installation:", error);
spinner.fail( spinner.fail(
"Failed to install Turso CLI. Proceeding with manual setup...", "Failed to install Turso CLI. Proceeding with manual setup...",
); );
throw error;
} }
} }
@@ -108,7 +117,7 @@ TURSO_AUTH_TOKEN="${authToken.trim()}"`;
spinner.succeed("Turso database configured successfully!"); spinner.succeed("Turso database configured successfully!");
return; return;
} catch (error) { } catch (error) {
console.error(error); logger.error("Error during Turso database creation:", error);
spinner.fail( spinner.fail(
"Failed to install Turso CLI. Proceeding with manual setup...", "Failed to install Turso CLI. Proceeding with manual setup...",
); );

View File

@@ -4,74 +4,91 @@ import { Command } from "commander";
import { createProject } from "./create-project"; import { createProject } from "./create-project";
import { renderTitle } from "./render-title"; import { renderTitle } from "./render-title";
import type { ProjectDatabase, ProjectFeature } from "./types"; import type { ProjectDatabase, ProjectFeature } from "./types";
import { logger } from "./utils/logger";
const program = new Command(); const program = new Command();
async function main() { async function main() {
renderTitle(); try {
renderTitle();
console.log(chalk.bold("\n🚀 Creating a new Better-T Stack project...\n")); console.log(chalk.bold("\n🚀 Creating a new Better-T Stack project...\n"));
const projectName = await input({ const projectName = await input({
message: "Project name:", message: "Project name:",
default: "my-better-t-app", default: "my-better-t-app",
}); });
const database = await select<ProjectDatabase>({ const database = await select<ProjectDatabase>({
message: chalk.cyan("Select database:"), message: chalk.cyan("Select database:"),
choices: [ choices: [
{ {
value: "libsql", value: "libsql",
name: "libSQL", name: "libSQL",
description: chalk.dim( description: chalk.dim(
"(Recommended) - Turso's embedded SQLite database", "(Recommended) - Turso's embedded SQLite database",
), ),
}, },
{ {
value: "postgres", value: "postgres",
name: "PostgreSQL", name: "PostgreSQL",
description: chalk.dim("Traditional relational database"), description: chalk.dim("Traditional relational database"),
}, },
], ],
}); });
const auth = await confirm({ const auth = await confirm({
message: "Add authentication with Better-Auth?", message: "Add authentication with Better-Auth?",
default: true, default: true,
}); });
const features = await checkbox<ProjectFeature>({ const features = await checkbox<ProjectFeature>({
message: chalk.cyan("Select additional features:"), message: chalk.cyan("Select additional features:"),
choices: [ choices: [
{ {
value: "docker", value: "docker",
name: "Docker setup", name: "Docker setup",
description: chalk.dim("Containerize your application"), description: chalk.dim("Containerize your application"),
}, },
{ {
value: "github-actions", value: "github-actions",
name: "GitHub Actions", name: "GitHub Actions",
description: chalk.dim("CI/CD workflows"), description: chalk.dim("CI/CD workflows"),
}, },
{ {
value: "SEO", value: "SEO",
name: "Basic SEO setup", name: "Basic SEO setup",
description: chalk.dim("Search engine optimization configuration"), description: chalk.dim("Search engine optimization configuration"),
}, },
], ],
}); });
const projectOptions = { const projectOptions = {
projectName, projectName,
git: true, git: true,
database, database,
auth, auth,
features, features,
}; };
await createProject(projectOptions); await createProject(projectOptions);
} catch (error) {
if (error instanceof Error && error.message.includes("User force closed")) {
console.log("\n");
logger.warn("Operation cancelled by user");
process.exit(0);
}
logger.error("An unexpected error occurred:", error);
process.exit(1);
}
} }
process.on("SIGINT", () => {
console.log("\n");
logger.warn("Operation cancelled by user");
process.exit(0);
});
program program
.name("create-better-t-stack") .name("create-better-t-stack")
.description("Create a new Better-T Stack project") .description("Create a new Better-T Stack project")

View File

@@ -0,0 +1,16 @@
import chalk from "chalk";
export const logger = {
error(...args: unknown[]) {
console.log(chalk.red(...args));
},
warn(...args: unknown[]) {
console.log(chalk.yellow(...args));
},
info(...args: unknown[]) {
console.log(chalk.cyan(...args));
},
success(...args: unknown[]) {
console.log(chalk.green(...args));
},
};