mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
Add consola errors, update to better-auth v1.2.6
This commit is contained in:
5
.changeset/hot-waves-hope.md
Normal file
5
.changeset/hot-waves-hope.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"create-better-t-stack": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
add consola errors, update to better-auth v1.2.6
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"author": "Aman Varshney",
|
||||||
"bin": {
|
"bin": {
|
||||||
"create-better-t-stack": "dist/index.js"
|
"create-better-t-stack": "dist/index.js"
|
||||||
},
|
},
|
||||||
@@ -53,6 +54,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@clack/prompts": "^0.10.1",
|
"@clack/prompts": "^0.10.1",
|
||||||
|
"consola": "^3.4.2",
|
||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
"fs-extra": "^11.3.0",
|
"fs-extra": "^11.3.0",
|
||||||
"gradient-string": "^3.0.0",
|
"gradient-string": "^3.0.0",
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ export const DEFAULT_CONFIG: ProjectConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const dependencyVersionMap = {
|
export const dependencyVersionMap = {
|
||||||
"better-auth": "^1.2.5",
|
"better-auth": "^1.2.6",
|
||||||
"@better-auth/expo": "^1.2.5",
|
"@better-auth/expo": "^1.2.6",
|
||||||
|
|
||||||
"drizzle-orm": "^0.38.4",
|
"drizzle-orm": "^0.38.4",
|
||||||
"drizzle-kit": "^0.30.5",
|
"drizzle-kit": "^0.30.5",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { log } from "@clack/prompts";
|
import consola from "consola";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
import type { ProjectFrontend } from "../types";
|
import type { ProjectFrontend } from "../types";
|
||||||
import { addPackageDependency } from "../utils/add-package-deps";
|
import { addPackageDependency } from "../utils/add-package-deps";
|
||||||
@@ -54,9 +54,9 @@ export async function setupAuth(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(pc.red("Failed to configure authentication"));
|
consola.error(pc.red("Failed to configure authentication"));
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
log.error(pc.red(error.message));
|
consola.error(pc.red(error.message));
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
import consola from "consola";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import type {
|
import type {
|
||||||
ProjectAddons,
|
ProjectAddons,
|
||||||
@@ -16,7 +17,7 @@ export async function createReadme(projectDir: string, options: ProjectConfig) {
|
|||||||
try {
|
try {
|
||||||
await fs.writeFile(readmePath, content);
|
await fs.writeFile(readmePath, content);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to create README.md file:", error);
|
consola.error("Failed to create README.md file:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,24 +31,33 @@ function generateReadmeContent(options: ProjectConfig): string {
|
|||||||
orm = "drizzle",
|
orm = "drizzle",
|
||||||
runtime = "bun",
|
runtime = "bun",
|
||||||
frontend = ["tanstack-router"],
|
frontend = ["tanstack-router"],
|
||||||
|
backend = "hono",
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const hasReactRouter = frontend.includes("react-router");
|
const hasReactRouter = frontend.includes("react-router");
|
||||||
const hasTanstackRouter = frontend.includes("tanstack-router");
|
const hasTanstackRouter = frontend.includes("tanstack-router");
|
||||||
const hasNative = frontend.includes("native");
|
const hasNative = frontend.includes("native");
|
||||||
|
const hasNext = frontend.includes("next");
|
||||||
|
const hasTanstackStart = frontend.includes("tanstack-start");
|
||||||
|
|
||||||
const packageManagerRunCmd =
|
const packageManagerRunCmd =
|
||||||
packageManager === "npm" ? "npm run" : packageManager;
|
packageManager === "npm" ? "npm run" : packageManager;
|
||||||
|
|
||||||
const port = hasReactRouter ? "5173" : "3001";
|
// Determine the web port based on the frontend framework
|
||||||
|
let webPort = "3001"; // Default for TanStack Router and TanStack Start
|
||||||
|
if (hasReactRouter) {
|
||||||
|
webPort = "5173";
|
||||||
|
} else if (hasNext) {
|
||||||
|
webPort = "3000";
|
||||||
|
}
|
||||||
|
|
||||||
return `# ${projectName}
|
return `# ${projectName}
|
||||||
|
|
||||||
This project was created with [Better-T-Stack](https://github.com/AmanVarshney01/create-better-t-stack), a modern TypeScript stack that combines React, ${hasTanstackRouter ? "TanStack Router" : "React Router"}, Hono, tRPC, and more.
|
This project was created with [Better-T-Stack](https://github.com/AmanVarshney01/create-better-t-stack), a modern TypeScript stack that combines React, ${hasTanstackRouter ? "TanStack Router" : hasReactRouter ? "React Router" : hasNext ? "Next.js" : hasTanstackStart ? "TanStack Start" : ""}, ${backend[0].toUpperCase() + backend.slice(1)}, tRPC, and more.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
${generateFeaturesList(database, auth, addons, orm, runtime, frontend)}
|
${generateFeaturesList(database, auth, addons, orm, runtime, frontend, backend)}
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
@@ -66,8 +76,8 @@ ${packageManagerRunCmd} dev
|
|||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
${
|
${
|
||||||
hasTanstackRouter || hasReactRouter
|
hasTanstackRouter || hasReactRouter || hasNext || hasTanstackStart
|
||||||
? `Open [http://localhost:${port}](http://localhost:${port}) in your browser to see the web application.`
|
? `Open [http://localhost:${webPort}](http://localhost:${webPort}) in your browser to see the web application.`
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
${hasNative ? "Use the Expo Go app to run the mobile application.\n" : ""}
|
${hasNative ? "Use the Expo Go app to run the mobile application.\n" : ""}
|
||||||
@@ -84,12 +94,12 @@ ${
|
|||||||
\`\`\`
|
\`\`\`
|
||||||
${projectName}/
|
${projectName}/
|
||||||
├── apps/
|
├── apps/
|
||||||
${hasTanstackRouter || hasReactRouter ? `│ ├── web/ # Frontend application (React, ${hasTanstackRouter ? "TanStack Router" : "React Router"})\n` : ""}${hasNative ? "│ ├── native/ # Mobile application (React Native, Expo)\n" : ""}│ └── server/ # Backend API (Hono, tRPC)
|
${hasTanstackRouter || hasReactRouter || hasNext || hasTanstackStart ? `│ ├── web/ # Frontend application (${hasTanstackRouter ? "React + TanStack Router" : hasReactRouter ? "React + React Router" : hasNext ? "Next.js" : "React + TanStack Start"})\n` : ""}${hasNative ? "│ ├── native/ # Mobile application (React Native, Expo)\n" : ""}${addons.includes("starlight") ? "│ ├── docs/ # Documentation site (Astro Starlight)\n" : ""}│ └── server/ # Backend API (${backend[0].toUpperCase() + backend.slice(1)}, tRPC)
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
## Available Scripts
|
## Available Scripts
|
||||||
|
|
||||||
${generateScriptsList(packageManagerRunCmd, database, orm, auth, hasNative)}
|
${generateScriptsList(packageManagerRunCmd, database, orm, auth, hasNative, addons, backend)}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,10 +110,13 @@ function generateFeaturesList(
|
|||||||
orm: ProjectOrm,
|
orm: ProjectOrm,
|
||||||
runtime: ProjectRuntime,
|
runtime: ProjectRuntime,
|
||||||
frontend: ProjectFrontend[],
|
frontend: ProjectFrontend[],
|
||||||
|
backend: string,
|
||||||
): string {
|
): string {
|
||||||
const hasTanstackRouter = frontend.includes("tanstack-router");
|
const hasTanstackRouter = frontend.includes("tanstack-router");
|
||||||
const hasReactRouter = frontend.includes("react-router");
|
const hasReactRouter = frontend.includes("react-router");
|
||||||
const hasNative = frontend.includes("native");
|
const hasNative = frontend.includes("native");
|
||||||
|
const hasNext = frontend.includes("next");
|
||||||
|
const hasTanstackStart = frontend.includes("tanstack-start");
|
||||||
|
|
||||||
const addonsList = [
|
const addonsList = [
|
||||||
"- **TypeScript** - For type safety and improved developer experience",
|
"- **TypeScript** - For type safety and improved developer experience",
|
||||||
@@ -115,6 +128,12 @@ function generateFeaturesList(
|
|||||||
);
|
);
|
||||||
} else if (hasReactRouter) {
|
} else if (hasReactRouter) {
|
||||||
addonsList.push("- **React Router** - Declarative routing for React");
|
addonsList.push("- **React Router** - Declarative routing for React");
|
||||||
|
} else if (hasNext) {
|
||||||
|
addonsList.push("- **Next.js** - Full-stack React framework");
|
||||||
|
} else if (hasTanstackStart) {
|
||||||
|
addonsList.push(
|
||||||
|
"- **TanStack Start** - SSR framework with TanStack Router",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasNative) {
|
if (hasNative) {
|
||||||
@@ -125,7 +144,19 @@ function generateFeaturesList(
|
|||||||
addonsList.push(
|
addonsList.push(
|
||||||
"- **TailwindCSS** - Utility-first CSS for rapid UI development",
|
"- **TailwindCSS** - Utility-first CSS for rapid UI development",
|
||||||
"- **shadcn/ui** - Reusable UI components",
|
"- **shadcn/ui** - Reusable UI components",
|
||||||
"- **Hono** - Lightweight, performant server framework",
|
);
|
||||||
|
|
||||||
|
if (backend === "hono") {
|
||||||
|
addonsList.push("- **Hono** - Lightweight, performant server framework");
|
||||||
|
} else if (backend === "express") {
|
||||||
|
addonsList.push("- **Express** - Fast, unopinionated web framework");
|
||||||
|
} else if (backend === "elysia") {
|
||||||
|
addonsList.push("- **Elysia** - Type-safe, high-performance framework");
|
||||||
|
} else if (backend === "next") {
|
||||||
|
addonsList.push("- **Next.js** - Full-stack React framework");
|
||||||
|
}
|
||||||
|
|
||||||
|
addonsList.push(
|
||||||
"- **tRPC** - End-to-end type-safe APIs",
|
"- **tRPC** - End-to-end type-safe APIs",
|
||||||
`- **${runtime === "bun" ? "Bun" : "Node.js"}** - Runtime environment`,
|
`- **${runtime === "bun" ? "Bun" : "Node.js"}** - Runtime environment`,
|
||||||
);
|
);
|
||||||
@@ -133,7 +164,7 @@ function generateFeaturesList(
|
|||||||
if (database !== "none") {
|
if (database !== "none") {
|
||||||
addonsList.push(
|
addonsList.push(
|
||||||
`- **${orm === "drizzle" ? "Drizzle" : "Prisma"}** - TypeScript-first ORM`,
|
`- **${orm === "drizzle" ? "Drizzle" : "Prisma"}** - TypeScript-first ORM`,
|
||||||
`- **${database === "sqlite" ? "SQLite/Turso" : "PostgreSQL"}** - Database engine`,
|
`- **${database === "sqlite" ? "SQLite/Turso" : database === "postgres" ? "PostgreSQL" : database === "mysql" ? "MySQL" : "MongoDB"}** - Database engine`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +183,8 @@ function generateFeaturesList(
|
|||||||
addonsList.push("- **Biome** - Linting and formatting");
|
addonsList.push("- **Biome** - Linting and formatting");
|
||||||
} else if (addon === "husky") {
|
} else if (addon === "husky") {
|
||||||
addonsList.push("- **Husky** - Git hooks for code quality");
|
addonsList.push("- **Husky** - Git hooks for code quality");
|
||||||
|
} else if (addon === "starlight") {
|
||||||
|
addonsList.push("- **Starlight** - Documentation site with Astro");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,11 +218,23 @@ cd apps/server && ${packageManagerRunCmd} db:local
|
|||||||
|
|
||||||
1. Make sure you have a PostgreSQL database set up.
|
1. Make sure you have a PostgreSQL database set up.
|
||||||
2. Update your \`apps/server/.env\` file with your PostgreSQL connection details.
|
2. Update your \`apps/server/.env\` file with your PostgreSQL connection details.
|
||||||
|
`;
|
||||||
|
} else if (database === "mysql") {
|
||||||
|
setup += `This project uses MySQL${orm === "drizzle" ? " with Drizzle ORM" : " with Prisma"}.
|
||||||
|
|
||||||
|
1. Make sure you have a MySQL database set up.
|
||||||
|
2. Update your \`apps/server/.env\` file with your MySQL connection details.
|
||||||
|
`;
|
||||||
|
} else if (database === "mongodb") {
|
||||||
|
setup += `This project uses MongoDB with Prisma ORM.
|
||||||
|
|
||||||
|
1. Make sure you have MongoDB set up.
|
||||||
|
2. Update your \`apps/server/.env\` file with your MongoDB connection URI.
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
setup += `
|
setup += `
|
||||||
${auth ? "4" : "3"}. ${
|
${auth ? "3" : "3"}. ${
|
||||||
orm === "prisma"
|
orm === "prisma"
|
||||||
? `Generate the Prisma client and push the schema:
|
? `Generate the Prisma client and push the schema:
|
||||||
\`\`\`bash
|
\`\`\`bash
|
||||||
@@ -211,9 +256,11 @@ function generateScriptsList(
|
|||||||
orm: ProjectOrm,
|
orm: ProjectOrm,
|
||||||
auth: boolean,
|
auth: boolean,
|
||||||
hasNative: boolean,
|
hasNative: boolean,
|
||||||
|
addons: ProjectAddons[],
|
||||||
|
backend: string,
|
||||||
): string {
|
): string {
|
||||||
let scripts = `- \`${packageManagerRunCmd} dev\`: Start both web and server in development mode
|
let scripts = `- \`${packageManagerRunCmd} dev\`: Start all applications in development mode
|
||||||
- \`${packageManagerRunCmd} build\`: Build both web and server
|
- \`${packageManagerRunCmd} build\`: Build all applications
|
||||||
- \`${packageManagerRunCmd} dev:web\`: Start only the web application
|
- \`${packageManagerRunCmd} dev:web\`: Start only the web application
|
||||||
- \`${packageManagerRunCmd} dev:server\`: Start only the server
|
- \`${packageManagerRunCmd} dev:server\`: Start only the server
|
||||||
- \`${packageManagerRunCmd} check-types\`: Check TypeScript types across all apps`;
|
- \`${packageManagerRunCmd} check-types\`: Check TypeScript types across all apps`;
|
||||||
@@ -229,9 +276,32 @@ function generateScriptsList(
|
|||||||
- \`${packageManagerRunCmd} db:studio\`: Open database studio UI`;
|
- \`${packageManagerRunCmd} db:studio\`: Open database studio UI`;
|
||||||
|
|
||||||
if (database === "sqlite" && orm === "drizzle") {
|
if (database === "sqlite" && orm === "drizzle") {
|
||||||
scripts += `\n- \`cd apps/server && ${packageManagerRunCmd} db:local\`: Start the local SQLite database`;
|
scripts += `
|
||||||
|
- \`cd apps/server && ${packageManagerRunCmd} db:local\`: Start the local SQLite database`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addons.includes("biome")) {
|
||||||
|
scripts += `
|
||||||
|
- \`${packageManagerRunCmd} check\`: Run Biome formatting and linting`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addons.includes("pwa")) {
|
||||||
|
scripts += `
|
||||||
|
- \`cd apps/web && ${packageManagerRunCmd} generate-pwa-assets\`: Generate PWA assets`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addons.includes("tauri")) {
|
||||||
|
scripts += `
|
||||||
|
- \`cd apps/web && ${packageManagerRunCmd} desktop:dev\`: Start Tauri desktop app in development
|
||||||
|
- \`cd apps/web && ${packageManagerRunCmd} desktop:build\`: Build Tauri desktop app`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addons.includes("starlight")) {
|
||||||
|
scripts += `
|
||||||
|
- \`cd apps/docs && ${packageManagerRunCmd} dev\`: Start documentation site
|
||||||
|
- \`cd apps/docs && ${packageManagerRunCmd} build\`: Build documentation site`;
|
||||||
|
}
|
||||||
|
|
||||||
return scripts;
|
return scripts;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { log, spinner } from "@clack/prompts";
|
import { log, spinner } from "@clack/prompts";
|
||||||
|
import consola from "consola";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
import type {
|
import type {
|
||||||
@@ -74,7 +75,7 @@ export async function setupDatabase(
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
s.stop(pc.red("Failed to set up database"));
|
s.stop(pc.red("Failed to set up database"));
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
log.error(pc.red(error.message));
|
consola.error(pc.red(error.message));
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { log, spinner } from "@clack/prompts";
|
import { log, spinner } from "@clack/prompts";
|
||||||
|
import consola from "consola";
|
||||||
import { $ } from "execa";
|
import { $ } from "execa";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
import type { ProjectAddons, ProjectPackageManager } from "../types";
|
import type { ProjectAddons, ProjectPackageManager } from "../types";
|
||||||
@@ -30,7 +31,7 @@ export async function installDependencies({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
s.stop(pc.red("Failed to install dependencies"));
|
s.stop(pc.red("Failed to install dependencies"));
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
log.error(pc.red(`Installation error: ${error.message}`));
|
consola.error(pc.red(`Installation error: ${error.message}`));
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { cancel, isCancel, log, spinner, text } from "@clack/prompts";
|
import { cancel, isCancel, log, spinner, text } from "@clack/prompts";
|
||||||
|
import consola from "consola";
|
||||||
import { execa } from "execa";
|
import { execa } from "execa";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
@@ -34,7 +35,7 @@ async function initMongoDBAtlas(
|
|||||||
const hasAtlas = await checkAtlasCLI();
|
const hasAtlas = await checkAtlasCLI();
|
||||||
|
|
||||||
if (!hasAtlas) {
|
if (!hasAtlas) {
|
||||||
log.error(pc.red("MongoDB Atlas CLI not found."));
|
consola.error(pc.red("MongoDB Atlas CLI not found."));
|
||||||
log.info(
|
log.info(
|
||||||
pc.yellow(
|
pc.yellow(
|
||||||
"Please install it from: https://www.mongodb.com/docs/atlas/cli/current/install-atlas-cli/",
|
"Please install it from: https://www.mongodb.com/docs/atlas/cli/current/install-atlas-cli/",
|
||||||
@@ -74,7 +75,7 @@ async function initMongoDBAtlas(
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
log.error(pc.red(error.message));
|
consola.error(pc.red(error.message));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -105,7 +106,7 @@ async function writeEnvFile(projectDir: string, config?: MongoDBConfig) {
|
|||||||
|
|
||||||
await fs.writeFile(envPath, envContent.trim());
|
await fs.writeFile(envPath, envContent.trim());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error("Failed to update environment configuration");
|
consola.error("Failed to update environment configuration");
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +155,7 @@ export async function setupMongoDBAtlas(projectDir: string) {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
mainSpinner.stop(pc.red("MongoDB Atlas setup failed"));
|
mainSpinner.stop(pc.red("MongoDB Atlas setup failed"));
|
||||||
log.error(
|
consola.error(
|
||||||
pc.red(
|
pc.red(
|
||||||
`Error during MongoDB Atlas setup: ${error instanceof Error ? error.message : String(error)}`,
|
`Error during MongoDB Atlas setup: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { cancel, isCancel, log, spinner, text } from "@clack/prompts";
|
import { cancel, isCancel, log, spinner, text } from "@clack/prompts";
|
||||||
|
import { consola } from "consola";
|
||||||
import { execa } from "execa";
|
import { execa } from "execa";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
@@ -82,7 +83,7 @@ async function authenticateWithNeon(packageManager: string) {
|
|||||||
log.success("Authenticated with Neon successfully!");
|
log.success("Authenticated with Neon successfully!");
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(pc.red("Failed to authenticate with Neon"));
|
consola.error(pc.red("Failed to authenticate with Neon"));
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,10 +117,12 @@ async function createNeonProject(
|
|||||||
roleName: params.role,
|
roleName: params.role,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
log.error(pc.red("Failed to extract connection information from response"));
|
consola.error(
|
||||||
|
pc.red("Failed to extract connection information from response"),
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(pc.red("Failed to create Neon project"));
|
consola.error(pc.red("Failed to create Neon project"));
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +201,7 @@ export async function setupNeonPostgres(
|
|||||||
setupSpinner.stop(pc.red("Neon PostgreSQL setup failed"));
|
setupSpinner.stop(pc.red("Neon PostgreSQL setup failed"));
|
||||||
|
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
log.error(pc.red(error.message));
|
consola.error(pc.red(error.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
await writeEnvFile(projectDir);
|
await writeEnvFile(projectDir);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { note } from "@clack/prompts";
|
import { consola } from "consola";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
import type {
|
import type {
|
||||||
ProjectAddons,
|
ProjectAddons,
|
||||||
@@ -57,8 +57,8 @@ export function displayPostInstallInstructions(
|
|||||||
|
|
||||||
const webPort = hasReactRouter ? "5173" : "3001";
|
const webPort = hasReactRouter ? "5173" : "3001";
|
||||||
|
|
||||||
note(
|
consola.box(
|
||||||
`${pc.cyan("1.")} ${cdCmd}
|
`${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}
|
||||||
${!depsInstalled ? `${pc.cyan("2.")} ${packageManager} install\n` : ""}${pc.cyan(depsInstalled ? "2." : "3.")} ${runCmd} dev
|
${!depsInstalled ? `${pc.cyan("2.")} ${packageManager} install\n` : ""}${pc.cyan(depsInstalled ? "2." : "3.")} ${runCmd} dev
|
||||||
|
|
||||||
${pc.bold("Your project will be available at:")}
|
${pc.bold("Your project will be available at:")}
|
||||||
@@ -68,9 +68,9 @@ ${
|
|||||||
: `${pc.yellow("NOTE:")} You are creating a backend-only app (no frontend selected)\n`
|
: `${pc.yellow("NOTE:")} You are creating a backend-only app (no frontend selected)\n`
|
||||||
}${pc.cyan("•")} API: http://localhost:3000
|
}${pc.cyan("•")} API: http://localhost:3000
|
||||||
${addons?.includes("starlight") ? `${pc.cyan("•")} Docs: http://localhost:4321\n` : ""}${nativeInstructions ? `\n${nativeInstructions.trim()}` : ""}${databaseInstructions ? `\n${databaseInstructions.trim()}` : ""}${tauriInstructions ? `\n${tauriInstructions.trim()}` : ""}${lintingInstructions ? `\n${lintingInstructions.trim()}` : ""}${pwaInstructions ? `\n${pwaInstructions.trim()}` : ""}${starlightInstructions ? `\n${starlightInstructions.trim()}` : ""}
|
${addons?.includes("starlight") ? `${pc.cyan("•")} Docs: http://localhost:4321\n` : ""}${nativeInstructions ? `\n${nativeInstructions.trim()}` : ""}${databaseInstructions ? `\n${databaseInstructions.trim()}` : ""}${tauriInstructions ? `\n${tauriInstructions.trim()}` : ""}${lintingInstructions ? `\n${lintingInstructions.trim()}` : ""}${pwaInstructions ? `\n${pwaInstructions.trim()}` : ""}${starlightInstructions ? `\n${starlightInstructions.trim()}` : ""}
|
||||||
\n${pc.bold("Like Better-T Stack?")} Please consider giving us a star on GitHub:
|
|
||||||
|
${pc.bold("Like Better-T Stack?")} Please consider giving us a star on GitHub:
|
||||||
${pc.cyan("https://github.com/AmanVarshney01/create-better-t-stack")}`,
|
${pc.cyan("https://github.com/AmanVarshney01/create-better-t-stack")}`,
|
||||||
"Next steps",
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { cancel, isCancel, log, password, spinner } from "@clack/prompts";
|
import { cancel, isCancel, log, password, spinner } from "@clack/prompts";
|
||||||
|
import { consola } from "consola";
|
||||||
import { execa } from "execa";
|
import { execa } from "execa";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
@@ -62,7 +63,7 @@ async function initPrismaDatabase(
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
s.stop(pc.red("Failed to initialize Prisma PostgreSQL"));
|
s.stop(pc.red("Failed to initialize Prisma PostgreSQL"));
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
log.error(error.message);
|
consola.error(error.message);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -93,7 +94,7 @@ async function writeEnvFile(projectDir: string, config?: PrismaConfig) {
|
|||||||
|
|
||||||
await fs.writeFile(envPath, envContent.trim());
|
await fs.writeFile(envPath, envContent.trim());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error("Failed to update environment configuration");
|
consola.error("Failed to update environment configuration");
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,7 +182,7 @@ export async function setupPrismaPostgres(
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
s.stop(pc.red("Prisma PostgreSQL setup failed"));
|
s.stop(pc.red("Prisma PostgreSQL setup failed"));
|
||||||
log.error(
|
consola.error(
|
||||||
pc.red(
|
pc.red(
|
||||||
`Error during Prisma PostgreSQL setup: ${error instanceof Error ? error.message : String(error)}`,
|
`Error during Prisma PostgreSQL setup: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { log, spinner } from "@clack/prompts";
|
import { log, spinner } from "@clack/prompts";
|
||||||
|
import consola from "consola";
|
||||||
import { execa } from "execa";
|
import { execa } from "execa";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
import type { ProjectPackageManager } from "../types";
|
import type { ProjectPackageManager } from "../types";
|
||||||
@@ -57,7 +58,7 @@ export async function setupStarlight(
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
s.stop(pc.red("Failed to set up Starlight documentation site"));
|
s.stop(pc.red("Failed to set up Starlight documentation site"));
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
log.error(pc.red(error.message));
|
consola.error(pc.red(error.message));
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { log, spinner } from "@clack/prompts";
|
import { log, spinner } from "@clack/prompts";
|
||||||
|
import { consola } from "consola";
|
||||||
import { execa } from "execa";
|
import { execa } from "execa";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
@@ -88,7 +89,7 @@ export async function setupTauri(
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
s.stop(pc.red("Failed to set up Tauri"));
|
s.stop(pc.red("Failed to set up Tauri"));
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
log.error(pc.red(error.message));
|
consola.error(pc.red(error.message));
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
spinner,
|
spinner,
|
||||||
text,
|
text,
|
||||||
} from "@clack/prompts";
|
} from "@clack/prompts";
|
||||||
|
import consola from "consola";
|
||||||
import { $ } from "execa";
|
import { $ } from "execa";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
@@ -301,7 +302,7 @@ export async function setupTurso(
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setupSpinner.stop(pc.red("Failed to set up Turso database"));
|
setupSpinner.stop(pc.red("Failed to set up Turso database"));
|
||||||
log.error(
|
consola.error(
|
||||||
pc.red(
|
pc.red(
|
||||||
`Error during Turso setup: ${error instanceof Error ? error.message : String(error)}`,
|
`Error during Turso setup: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { cancel, intro, log, outro, spinner } from "@clack/prompts";
|
import { cancel, intro, log, outro } from "@clack/prompts";
|
||||||
|
import { consola } from "consola";
|
||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
import yargs from "yargs";
|
import yargs from "yargs";
|
||||||
import { hideBin } from "yargs/helpers";
|
import { hideBin } from "yargs/helpers";
|
||||||
@@ -49,7 +50,6 @@ process.on("SIGTERM", exit);
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const s = spinner();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const argv = await yargs(hideBin(process.argv))
|
const argv = await yargs(hideBin(process.argv))
|
||||||
@@ -146,14 +146,15 @@ async function main() {
|
|||||||
.wrap(null)
|
.wrap(null)
|
||||||
.parse();
|
.parse();
|
||||||
|
|
||||||
renderTitle();
|
|
||||||
intro(pc.magenta("Creating a new Better-T-Stack project"));
|
|
||||||
|
|
||||||
const options = argv as YargsArgv;
|
const options = argv as YargsArgv;
|
||||||
const projectDirectory = options.projectDirectory;
|
const projectDirectory = options.projectDirectory;
|
||||||
|
|
||||||
|
renderTitle();
|
||||||
|
|
||||||
const flagConfig = processAndValidateFlags(options, projectDirectory);
|
const flagConfig = processAndValidateFlags(options, projectDirectory);
|
||||||
|
|
||||||
|
intro(pc.magenta("Creating a new Better-T-Stack project"));
|
||||||
|
|
||||||
if (!options.yes && Object.keys(flagConfig).length > 0) {
|
if (!options.yes && Object.keys(flagConfig).length > 0) {
|
||||||
log.info(pc.yellow("Using these pre-selected options:"));
|
log.info(pc.yellow("Using these pre-selected options:"));
|
||||||
log.message(displayConfig(flagConfig));
|
log.message(displayConfig(flagConfig));
|
||||||
@@ -177,9 +178,11 @@ async function main() {
|
|||||||
await createProject(config);
|
await createProject(config);
|
||||||
|
|
||||||
log.success(
|
log.success(
|
||||||
`You can reproduce this setup with the following command:\n${pc.white(
|
pc.blue(
|
||||||
generateReproducibleCommand(config),
|
`You can reproduce this setup with the following command:\n${generateReproducibleCommand(
|
||||||
)}`,
|
config,
|
||||||
|
)}`,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const elapsedTimeInSeconds = ((Date.now() - startTime) / 1000).toFixed(2);
|
const elapsedTimeInSeconds = ((Date.now() - startTime) / 1000).toFixed(2);
|
||||||
@@ -189,16 +192,16 @@ async function main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
s.stop(pc.red("Failed"));
|
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
if (error.name === "YError") {
|
if (error.name === "YError") {
|
||||||
cancel(pc.red(`Invalid arguments: ${error.message}`));
|
cancel(pc.red(`Invalid arguments: ${error.message}`));
|
||||||
} else {
|
} else {
|
||||||
cancel(pc.red(`An unexpected error occurred: ${error.message}`));
|
consola.error(`An unexpected error occurred: ${error.message}`);
|
||||||
|
consola.error(error.stack);
|
||||||
}
|
}
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
cancel(pc.red("An unexpected error occurred."));
|
consola.error("An unexpected error occurred.");
|
||||||
console.error(error);
|
console.error(error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -227,10 +230,8 @@ function processAndValidateFlags(
|
|||||||
(config.database ?? options.database) === "mongodb" &&
|
(config.database ?? options.database) === "mongodb" &&
|
||||||
(config.orm ?? options.orm) === "drizzle"
|
(config.orm ?? options.orm) === "drizzle"
|
||||||
) {
|
) {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"MongoDB is only available with Prisma. Cannot use --database mongodb with --orm drizzle",
|
||||||
"MongoDB is only available with Prisma. Cannot use --database mongodb with --orm drizzle",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -243,50 +244,40 @@ function processAndValidateFlags(
|
|||||||
|
|
||||||
if (dbSetup === "turso") {
|
if (dbSetup === "turso") {
|
||||||
if (options.database && options.database !== "sqlite") {
|
if (options.database && options.database !== "sqlite") {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
`Turso setup requires a SQLite database. Cannot use --db-setup turso with --database ${options.database}`,
|
||||||
`Turso setup requires a SQLite database. Cannot use --db-setup turso with --database ${options.database}`,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
config.database = "sqlite";
|
config.database = "sqlite";
|
||||||
|
|
||||||
if (options.orm === "prisma") {
|
if (options.orm === "prisma") {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"Turso setup is not compatible with Prisma. Cannot use --db-setup turso with --orm prisma",
|
||||||
"Turso setup is not compatible with Prisma. Cannot use --db-setup turso with --orm prisma",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
config.orm = "drizzle";
|
config.orm = "drizzle";
|
||||||
} else if (dbSetup === "prisma-postgres") {
|
} else if (dbSetup === "prisma-postgres") {
|
||||||
if (options.database && options.database !== "postgres") {
|
if (options.database && options.database !== "postgres") {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"Prisma PostgreSQL setup requires PostgreSQL database. Cannot use --db-setup prisma-postgres with a different database type.",
|
||||||
"Prisma PostgreSQL setup requires PostgreSQL database. Cannot use --db-setup prisma-postgres with a different database type.",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
config.database = "postgres";
|
config.database = "postgres";
|
||||||
|
|
||||||
if (options.orm && options.orm !== "prisma" && options.orm !== "none") {
|
if (options.orm && options.orm !== "prisma" && options.orm !== "none") {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"Prisma PostgreSQL setup requires Prisma ORM. Cannot use --db-setup prisma-postgres with a different ORM.",
|
||||||
"Prisma PostgreSQL setup requires Prisma ORM. Cannot use --db-setup prisma-postgres with a different ORM.",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
config.orm = "prisma";
|
config.orm = "prisma";
|
||||||
} else if (dbSetup === "mongodb-atlas") {
|
} else if (dbSetup === "mongodb-atlas") {
|
||||||
if (options.database && options.database !== "mongodb") {
|
if (options.database && options.database !== "mongodb") {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"MongoDB Atlas setup requires MongoDB database. Cannot use --db-setup mongodb-atlas with a different database type.",
|
||||||
"MongoDB Atlas setup requires MongoDB database. Cannot use --db-setup mongodb-atlas with a different database type.",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -294,10 +285,8 @@ function processAndValidateFlags(
|
|||||||
config.orm = "prisma";
|
config.orm = "prisma";
|
||||||
} else if (dbSetup === "neon") {
|
} else if (dbSetup === "neon") {
|
||||||
if (options.database && options.database !== "postgres") {
|
if (options.database && options.database !== "postgres") {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"Neon PostgreSQL setup requires PostgreSQL database. Cannot use --db-setup neon with a different database type.",
|
||||||
"Neon PostgreSQL setup requires PostgreSQL database. Cannot use --db-setup neon with a different database type.",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -311,20 +300,16 @@ function processAndValidateFlags(
|
|||||||
const effectiveDatabase = config.database ?? options.database;
|
const effectiveDatabase = config.database ?? options.database;
|
||||||
if (effectiveDatabase === "none") {
|
if (effectiveDatabase === "none") {
|
||||||
if (options.auth === true) {
|
if (options.auth === true) {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"Authentication requires a database. Cannot use --auth with --database none.",
|
||||||
"Authentication requires a database. Cannot use --auth with --database none.",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const effectiveOrm = config.orm ?? options.orm;
|
const effectiveOrm = config.orm ?? options.orm;
|
||||||
if (effectiveOrm && effectiveOrm !== "none") {
|
if (effectiveOrm && effectiveOrm !== "none") {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
`Cannot use ORM with no database. Cannot use --orm ${effectiveOrm} with --database none.`,
|
||||||
`Cannot use ORM with no database. Cannot use --orm ${effectiveOrm} with --database none.`,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -332,10 +317,8 @@ function processAndValidateFlags(
|
|||||||
|
|
||||||
const effectiveDbSetup = config.dbSetup ?? options.dbSetup;
|
const effectiveDbSetup = config.dbSetup ?? options.dbSetup;
|
||||||
if (effectiveDbSetup && effectiveDbSetup !== "none") {
|
if (effectiveDbSetup && effectiveDbSetup !== "none") {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
`Database setup requires a database. Cannot use --db-setup ${effectiveDbSetup} with --database none.`,
|
||||||
`Database setup requires a database. Cannot use --db-setup ${effectiveDbSetup} with --database none.`,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -357,7 +340,7 @@ function processAndValidateFlags(
|
|||||||
if (options.frontend && options.frontend.length > 0) {
|
if (options.frontend && options.frontend.length > 0) {
|
||||||
if (options.frontend.includes("none")) {
|
if (options.frontend.includes("none")) {
|
||||||
if (options.frontend.length > 1) {
|
if (options.frontend.length > 1) {
|
||||||
cancel(pc.red(`Cannot combine 'none' with other frontend options.`));
|
consola.fatal(`Cannot combine 'none' with other frontend options.`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
config.frontend = [];
|
config.frontend = [];
|
||||||
@@ -374,10 +357,8 @@ function processAndValidateFlags(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (webFrontends.length > 1) {
|
if (webFrontends.length > 1) {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router",
|
||||||
"Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -388,7 +369,7 @@ function processAndValidateFlags(
|
|||||||
if (options.addons && options.addons.length > 0) {
|
if (options.addons && options.addons.length > 0) {
|
||||||
if (options.addons.includes("none")) {
|
if (options.addons.includes("none")) {
|
||||||
if (options.addons.length > 1) {
|
if (options.addons.length > 1) {
|
||||||
cancel(pc.red(`Cannot combine 'none' with other addons.`));
|
consola.fatal(`Cannot combine 'none' with other addons.`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
config.addons = [];
|
config.addons = [];
|
||||||
@@ -411,18 +392,14 @@ function processAndValidateFlags(
|
|||||||
|
|
||||||
if (hasWebSpecificAddons && !hasCompatibleWebFrontend) {
|
if (hasWebSpecificAddons && !hasCompatibleWebFrontend) {
|
||||||
if (options.frontend) {
|
if (options.frontend) {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"PWA and Tauri addons require tanstack-router or react-router. Cannot use these addons with your frontend selection.",
|
||||||
"PWA and Tauri addons require tanstack-router or react-router. Cannot use these addons with your frontend selection.",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else if (!options.yes) {
|
} else if (!options.yes) {
|
||||||
} else {
|
} else {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"PWA and Tauri addons require tanstack-router or react-router (default frontend incompatible).",
|
||||||
"PWA and Tauri addons require tanstack-router or react-router (default frontend incompatible).",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -439,7 +416,7 @@ function processAndValidateFlags(
|
|||||||
if (options.examples && options.examples.length > 0) {
|
if (options.examples && options.examples.length > 0) {
|
||||||
if (options.examples.includes("none")) {
|
if (options.examples.includes("none")) {
|
||||||
if (options.examples.length > 1) {
|
if (options.examples.length > 1) {
|
||||||
cancel(pc.red("Cannot combine 'none' with other examples."));
|
consola.fatal("Cannot combine 'none' with other examples.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
config.examples = [];
|
config.examples = [];
|
||||||
@@ -454,10 +431,8 @@ function processAndValidateFlags(
|
|||||||
effectiveBackend === "elysia" &&
|
effectiveBackend === "elysia" &&
|
||||||
!(options.yes && DEFAULT_CONFIG.backend !== "elysia")
|
!(options.yes && DEFAULT_CONFIG.backend !== "elysia")
|
||||||
) {
|
) {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"AI example is only compatible with Hono backend. Cannot use --examples ai with --backend elysia",
|
||||||
"AI example is only compatible with Hono backend. Cannot use --examples ai with --backend elysia",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -473,18 +448,14 @@ function processAndValidateFlags(
|
|||||||
|
|
||||||
if (!hasWebFrontend) {
|
if (!hasWebFrontend) {
|
||||||
if (options.frontend) {
|
if (options.frontend) {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"Examples require a web frontend (tanstack-router, react-router, or tanstack-start). Cannot use --examples with your frontend selection.",
|
||||||
"Examples require a web frontend (tanstack-router, react-router, or tanstack-start). Cannot use --examples with your frontend selection.",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else if (!options.yes) {
|
} else if (!options.yes) {
|
||||||
} else {
|
} else {
|
||||||
cancel(
|
consola.fatal(
|
||||||
pc.red(
|
"Examples require a web frontend (tanstack-router, react-router, or tanstack-start) (default frontend incompatible).",
|
||||||
"Examples require a web frontend (tanstack-router, react-router, or tanstack-start) (default frontend incompatible).",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -514,12 +485,12 @@ function processAndValidateFlags(
|
|||||||
}
|
}
|
||||||
|
|
||||||
main().catch((err) => {
|
main().catch((err) => {
|
||||||
log.error("Aborting installation due to unexpected error...");
|
consola.error("Aborting installation due to unexpected error...");
|
||||||
if (err instanceof Error) {
|
if (err instanceof Error) {
|
||||||
log.error(err.message);
|
consola.error(err.message);
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
} else {
|
} else {
|
||||||
log.error(
|
consola.error(
|
||||||
"An unknown error has occurred. Please open an issue on GitHub with the below:",
|
"An unknown error has occurred. Please open an issue on GitHub with the below:",
|
||||||
);
|
);
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|||||||
7
bun.lock
7
bun.lock
@@ -14,12 +14,13 @@
|
|||||||
},
|
},
|
||||||
"apps/cli": {
|
"apps/cli": {
|
||||||
"name": "create-better-t-stack",
|
"name": "create-better-t-stack",
|
||||||
"version": "1.12.3",
|
"version": "1.13.1",
|
||||||
"bin": {
|
"bin": {
|
||||||
"create-better-t-stack": "dist/index.js",
|
"create-better-t-stack": "dist/index.js",
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@clack/prompts": "^0.10.1",
|
"@clack/prompts": "^0.10.1",
|
||||||
|
"consola": "^3.4.2",
|
||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
"fs-extra": "^11.3.0",
|
"fs-extra": "^11.3.0",
|
||||||
"gradient-string": "^3.0.0",
|
"gradient-string": "^3.0.0",
|
||||||
@@ -677,7 +678,7 @@
|
|||||||
|
|
||||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||||
|
|
||||||
"consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="],
|
"consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
|
||||||
|
|
||||||
"create-better-t-stack": ["create-better-t-stack@workspace:apps/cli"],
|
"create-better-t-stack": ["create-better-t-stack@workspace:apps/cli"],
|
||||||
|
|
||||||
@@ -1793,6 +1794,8 @@
|
|||||||
|
|
||||||
"tinyglobby/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
"tinyglobby/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||||
|
|
||||||
|
"tsup/consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="],
|
||||||
|
|
||||||
"web/@types/node": ["@types/node@22.13.11", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g=="],
|
"web/@types/node": ["@types/node@22.13.11", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g=="],
|
||||||
|
|
||||||
"web/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
"web/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||||
|
|||||||
Reference in New Issue
Block a user