mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
chore(cli): add tests (#576)
This commit is contained in:
@@ -174,7 +174,7 @@ export async function createProjectHandler(
|
||||
);
|
||||
}
|
||||
|
||||
await createProject(config);
|
||||
await createProject(config, { manualDb: input.manualDb });
|
||||
|
||||
const reproducibleCommand = generateReproducibleCommand(config);
|
||||
log.success(
|
||||
|
||||
@@ -32,7 +32,10 @@ import {
|
||||
setupFrontendTemplates,
|
||||
} from "./template-manager";
|
||||
|
||||
export async function createProject(options: ProjectConfig) {
|
||||
export async function createProject(
|
||||
options: ProjectConfig,
|
||||
cliInput?: { manualDb?: boolean },
|
||||
) {
|
||||
const projectDir = options.projectDir;
|
||||
const isConvex = options.backend === "convex";
|
||||
|
||||
@@ -58,7 +61,7 @@ export async function createProject(options: ProjectConfig) {
|
||||
|
||||
if (!isConvex) {
|
||||
await setupBackendDependencies(options);
|
||||
await setupDatabase(options);
|
||||
await setupDatabase(options, cliInput);
|
||||
await setupRuntime(options);
|
||||
if (options.examples.length > 0 && options.examples[0] !== "none") {
|
||||
await setupExamples(options);
|
||||
|
||||
@@ -14,7 +14,10 @@ import { setupPrismaPostgres } from "../database-providers/prisma-postgres-setup
|
||||
import { setupSupabase } from "../database-providers/supabase-setup";
|
||||
import { setupTurso } from "../database-providers/turso-setup";
|
||||
|
||||
export async function setupDatabase(config: ProjectConfig) {
|
||||
export async function setupDatabase(
|
||||
config: ProjectConfig,
|
||||
cliInput?: { manualDb?: boolean },
|
||||
) {
|
||||
const { database, orm, dbSetup, backend, projectDir } = config;
|
||||
|
||||
if (backend === "convex" || database === "none") {
|
||||
@@ -113,25 +116,25 @@ export async function setupDatabase(config: ProjectConfig) {
|
||||
if (dbSetup === "docker") {
|
||||
await setupDockerCompose(config);
|
||||
} else if (database === "sqlite" && dbSetup === "turso") {
|
||||
await setupTurso(config);
|
||||
await setupTurso(config, cliInput);
|
||||
} else if (database === "sqlite" && dbSetup === "d1") {
|
||||
await setupCloudflareD1(config);
|
||||
} else if (database === "postgres") {
|
||||
if (dbSetup === "prisma-postgres") {
|
||||
await setupPrismaPostgres(config);
|
||||
await setupPrismaPostgres(config, cliInput);
|
||||
} else if (dbSetup === "neon") {
|
||||
await setupNeonPostgres(config);
|
||||
await setupNeonPostgres(config, cliInput);
|
||||
} else if (dbSetup === "planetscale") {
|
||||
await setupPlanetScale(config);
|
||||
} else if (dbSetup === "supabase") {
|
||||
await setupSupabase(config);
|
||||
await setupSupabase(config, cliInput);
|
||||
}
|
||||
} else if (database === "mysql") {
|
||||
if (dbSetup === "planetscale") {
|
||||
await setupPlanetScale(config);
|
||||
}
|
||||
} else if (database === "mongodb" && dbSetup === "mongodb-atlas") {
|
||||
await setupMongoDBAtlas(config);
|
||||
await setupMongoDBAtlas(config, cliInput);
|
||||
}
|
||||
} catch (error) {
|
||||
s.stop(pc.red("Failed to set up database"));
|
||||
|
||||
@@ -120,8 +120,12 @@ ${pc.green("MongoDB Atlas Manual Setup Instructions:")}
|
||||
`);
|
||||
}
|
||||
|
||||
export async function setupMongoDBAtlas(config: ProjectConfig) {
|
||||
export async function setupMongoDBAtlas(
|
||||
config: ProjectConfig,
|
||||
cliInput?: { manualDb?: boolean },
|
||||
) {
|
||||
const { projectDir } = config;
|
||||
const manualDb = cliInput?.manualDb ?? false;
|
||||
const mainSpinner = spinner();
|
||||
mainSpinner.start("Setting up MongoDB Atlas...");
|
||||
|
||||
@@ -129,6 +133,13 @@ export async function setupMongoDBAtlas(config: ProjectConfig) {
|
||||
try {
|
||||
await fs.ensureDir(serverDir);
|
||||
|
||||
if (manualDb) {
|
||||
mainSpinner.stop("MongoDB Atlas manual setup selected");
|
||||
await writeEnvFile(projectDir);
|
||||
displayManualSetupInstructions();
|
||||
return;
|
||||
}
|
||||
|
||||
const mode = await select({
|
||||
message: "MongoDB Atlas setup: choose mode",
|
||||
options: [
|
||||
|
||||
@@ -154,10 +154,20 @@ function displayManualSetupInstructions() {
|
||||
DATABASE_URL="your_connection_string"`);
|
||||
}
|
||||
|
||||
export async function setupNeonPostgres(config: ProjectConfig) {
|
||||
export async function setupNeonPostgres(
|
||||
config: ProjectConfig,
|
||||
cliInput?: { manualDb?: boolean },
|
||||
) {
|
||||
const { packageManager, projectDir } = config;
|
||||
const manualDb = cliInput?.manualDb ?? false;
|
||||
|
||||
try {
|
||||
if (manualDb) {
|
||||
await writeEnvFile(projectDir);
|
||||
displayManualSetupInstructions();
|
||||
return;
|
||||
}
|
||||
|
||||
const mode = await select({
|
||||
message: "Neon setup: choose mode",
|
||||
options: [
|
||||
|
||||
@@ -212,13 +212,23 @@ async function addPrismaAccelerateExtension(serverDir: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function setupPrismaPostgres(config: ProjectConfig) {
|
||||
export async function setupPrismaPostgres(
|
||||
config: ProjectConfig,
|
||||
cliInput?: { manualDb?: boolean },
|
||||
) {
|
||||
const { packageManager, projectDir, orm } = config;
|
||||
const manualDb = cliInput?.manualDb ?? false;
|
||||
const serverDir = path.join(projectDir, "apps/server");
|
||||
|
||||
try {
|
||||
await fs.ensureDir(serverDir);
|
||||
|
||||
if (manualDb) {
|
||||
await writeEnvFile(projectDir);
|
||||
displayManualSetupInstructions();
|
||||
return;
|
||||
}
|
||||
|
||||
const mode = await select({
|
||||
message: "Prisma Postgres setup: choose mode",
|
||||
options: [
|
||||
|
||||
@@ -152,14 +152,24 @@ ${pc.dim(output)}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function setupSupabase(config: ProjectConfig) {
|
||||
export async function setupSupabase(
|
||||
config: ProjectConfig,
|
||||
cliInput?: { manualDb?: boolean },
|
||||
) {
|
||||
const { projectDir, packageManager } = config;
|
||||
const manualDb = cliInput?.manualDb ?? false;
|
||||
|
||||
const serverDir = path.join(projectDir, "apps", "server");
|
||||
|
||||
try {
|
||||
await fs.ensureDir(serverDir);
|
||||
|
||||
if (manualDb) {
|
||||
displayManualSupabaseInstructions();
|
||||
await writeSupabaseEnvFile(projectDir, "");
|
||||
return;
|
||||
}
|
||||
|
||||
const mode = await select({
|
||||
message: "Supabase setup: choose mode",
|
||||
options: [
|
||||
|
||||
@@ -186,12 +186,22 @@ DATABASE_URL=your_database_url
|
||||
DATABASE_AUTH_TOKEN=your_auth_token`);
|
||||
}
|
||||
|
||||
export async function setupTurso(config: ProjectConfig) {
|
||||
export async function setupTurso(
|
||||
config: ProjectConfig,
|
||||
cliInput?: { manualDb?: boolean },
|
||||
) {
|
||||
const { orm, projectDir } = config;
|
||||
const manualDb = cliInput?.manualDb ?? false;
|
||||
const _isDrizzle = orm === "drizzle";
|
||||
const setupSpinner = spinner();
|
||||
|
||||
try {
|
||||
if (manualDb) {
|
||||
await writeEnvFile(projectDir);
|
||||
displayManualSetupInstructions();
|
||||
return;
|
||||
}
|
||||
|
||||
const mode = await select({
|
||||
message: "Turso setup: choose mode",
|
||||
options: [
|
||||
|
||||
@@ -99,6 +99,13 @@ export const router = t.router({
|
||||
.optional()
|
||||
.default(false)
|
||||
.describe("Disable analytics"),
|
||||
manualDb: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.default(false)
|
||||
.describe(
|
||||
"Skip automatic/manual database setup prompt and use manual setup",
|
||||
),
|
||||
}),
|
||||
]),
|
||||
)
|
||||
|
||||
@@ -147,6 +147,7 @@ export type CreateInput = {
|
||||
directoryConflict?: DirectoryConflict;
|
||||
renderTitle?: boolean;
|
||||
disableAnalytics?: boolean;
|
||||
manualDb?: boolean;
|
||||
};
|
||||
|
||||
export type AddInput = {
|
||||
|
||||
@@ -2,16 +2,11 @@ import path from "node:path";
|
||||
import { Biome } from "@biomejs/js-api/nodejs";
|
||||
import consola from "consola";
|
||||
|
||||
let biome: Biome | null = null;
|
||||
let projectKey: number | null = null;
|
||||
|
||||
async function initializeBiome() {
|
||||
if (biome && projectKey !== null) return { biome, projectKey };
|
||||
|
||||
function initializeBiome() {
|
||||
try {
|
||||
biome = new Biome();
|
||||
const biome = new Biome();
|
||||
const result = biome.openProject("./");
|
||||
projectKey = result.projectKey;
|
||||
const projectKey = result.projectKey;
|
||||
|
||||
biome.applyConfiguration(projectKey, {
|
||||
formatter: {
|
||||
@@ -61,18 +56,18 @@ function shouldSkipFile(filePath: string) {
|
||||
return skipPatterns.some((pattern) => basename.includes(pattern));
|
||||
}
|
||||
|
||||
export async function formatFileWithBiome(filePath: string, content: string) {
|
||||
export function formatFileWithBiome(filePath: string, content: string) {
|
||||
if (!isSupportedFile(filePath) || shouldSkipFile(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const biomeResult = await initializeBiome();
|
||||
const biomeResult = initializeBiome();
|
||||
if (!biomeResult) return null;
|
||||
|
||||
const { biome: biomeInstance, projectKey: key } = biomeResult;
|
||||
const { biome, projectKey } = biomeResult;
|
||||
|
||||
const result = biomeInstance.formatContent(key, content, {
|
||||
const result = biome.formatContent(projectKey, content, {
|
||||
filePath: path.basename(filePath),
|
||||
});
|
||||
|
||||
|
||||
@@ -380,7 +380,8 @@ export function validateApiConstraints(
|
||||
if (
|
||||
options.examples &&
|
||||
!(options.examples.length === 1 && options.examples[0] === "none") &&
|
||||
options.backend !== "convex"
|
||||
options.backend !== "convex" &&
|
||||
options.backend !== "none"
|
||||
) {
|
||||
exitWithError(
|
||||
"Cannot use '--examples' when '--api' is set to 'none'. Please remove the --examples flag or choose an API type.",
|
||||
|
||||
Reference in New Issue
Block a user