chore(cli): add tests (#576)

This commit is contained in:
Aman Varshney
2025-09-14 11:29:01 +05:30
committed by GitHub
parent d39fa6e306
commit 98a0ab9ee6
29 changed files with 5720 additions and 4611 deletions

View File

@@ -174,7 +174,7 @@ export async function createProjectHandler(
);
}
await createProject(config);
await createProject(config, { manualDb: input.manualDb });
const reproducibleCommand = generateReproducibleCommand(config);
log.success(

View File

@@ -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);

View File

@@ -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"));

View File

@@ -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: [

View File

@@ -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: [

View File

@@ -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: [

View File

@@ -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: [

View File

@@ -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: [

View File

@@ -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",
),
}),
]),
)

View File

@@ -147,6 +147,7 @@ export type CreateInput = {
directoryConflict?: DirectoryConflict;
renderTitle?: boolean;
disableAnalytics?: boolean;
manualDb?: boolean;
};
export type AddInput = {

View File

@@ -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),
});

View File

@@ -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.",