feat: add mysql database

This commit is contained in:
Aman Varshney
2025-04-09 11:54:01 +05:30
parent 3cd9f31e01
commit c9b7e25e1d
25 changed files with 607 additions and 518 deletions

View File

@@ -30,58 +30,44 @@ export async function setupDatabase(
}
try {
if (databaseType === "sqlite") {
if (orm === "drizzle") {
if (orm === "prisma") {
addPackageDependency({
dependencies: ["@prisma/client"],
devDependencies: ["prisma"],
projectDir: serverDir,
});
} else if (orm === "drizzle") {
if (databaseType === "sqlite") {
addPackageDependency({
dependencies: ["drizzle-orm", "@libsql/client"],
devDependencies: ["drizzle-kit"],
projectDir: serverDir,
});
} else if (orm === "prisma") {
addPackageDependency({
dependencies: ["@prisma/client"],
devDependencies: ["prisma"],
projectDir: serverDir,
});
}
if (setupTursoDb) {
await setupTurso(projectDir, true);
}
} else if (databaseType === "postgres") {
if (orm === "drizzle") {
} else if (databaseType === "postgres") {
addPackageDependency({
dependencies: ["drizzle-orm", "postgres"],
devDependencies: ["drizzle-kit"],
projectDir: serverDir,
});
} else if (orm === "prisma") {
} else if (databaseType === "mysql") {
addPackageDependency({
dependencies: ["@prisma/client"],
devDependencies: ["prisma"],
projectDir: serverDir,
});
if (
databaseType === "postgres" &&
orm === "prisma" &&
setupPrismaPostgresDb
) {
await setupPrismaPostgres(projectDir, packageManager);
}
}
} else if (databaseType === "mongodb") {
if (orm === "prisma") {
addPackageDependency({
dependencies: ["@prisma/client"],
devDependencies: ["prisma"],
dependencies: ["drizzle-orm", "mysql2"],
devDependencies: ["drizzle-kit"],
projectDir: serverDir,
});
}
}
if (setupMongoDBAtlasDb) {
await setupMongoDBAtlas(projectDir);
}
if (databaseType === "sqlite" && setupTursoDb) {
await setupTurso(projectDir, orm === "drizzle");
} else if (
databaseType === "postgres" &&
orm === "prisma" &&
setupPrismaPostgresDb
) {
await setupPrismaPostgres(projectDir, packageManager);
} else if (databaseType === "mongodb" && setupMongoDBAtlasDb) {
await setupMongoDBAtlas(projectDir);
}
} catch (error) {
s.stop(pc.red("Failed to set up database"));

View File

@@ -3,73 +3,50 @@ import fs from "fs-extra";
import type { ProjectConfig } from "../types";
import { generateAuthSecret } from "./auth-setup";
interface EnvVariable {
key: string;
value: string;
condition: boolean;
}
async function addEnvVariablesToFile(
filePath: string,
variables: EnvVariable[],
): Promise<void> {
await fs.ensureDir(path.dirname(filePath));
let envContent = "";
if (await fs.pathExists(filePath)) {
envContent = await fs.readFile(filePath, "utf8");
}
let modified = false;
for (const { key, value, condition } of variables) {
if (condition) {
const regex = new RegExp(`^${key}=.*$`, "m");
if (regex.test(envContent)) {
if (value) {
envContent = envContent.replace(regex, `${key}=${value}`);
modified = true;
}
} else {
envContent += `\n${key}=${value}`;
modified = true;
}
}
}
if (modified) {
await fs.writeFile(filePath, envContent.trim());
}
}
export async function setupEnvironmentVariables(
projectDir: string,
options: ProjectConfig,
): Promise<void> {
const serverDir = path.join(projectDir, "apps/server");
const envPath = path.join(serverDir, ".env");
let envContent = "";
if (await fs.pathExists(envPath)) {
envContent = await fs.readFile(envPath, "utf8");
}
if (!envContent.includes("CORS_ORIGIN")) {
const hasReactRouter = options.frontend.includes("react-router");
const hasTanStackRouter = options.frontend.includes("tanstack-router");
const hasTanStackStart = options.frontend.includes("tanstack-start");
let corsOrigin = "http://localhost:3000";
if (hasReactRouter) {
corsOrigin = "http://localhost:5173";
} else if (hasTanStackRouter || hasTanStackStart) {
corsOrigin = "http://localhost:3001";
}
envContent += `\nCORS_ORIGIN=${corsOrigin}`;
}
if (options.auth) {
if (!envContent.includes("BETTER_AUTH_SECRET")) {
envContent += `\nBETTER_AUTH_SECRET=${generateAuthSecret()}`;
}
if (!envContent.includes("BETTER_AUTH_URL")) {
envContent += "\nBETTER_AUTH_URL=http://localhost:3000";
}
}
if (options.database !== "none") {
if (options.orm === "prisma" && !envContent.includes("DATABASE_URL")) {
let databaseUrlLine = "";
if (options.database === "sqlite") {
databaseUrlLine = "";
} else if (options.database === "postgres") {
databaseUrlLine = `\nDATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"`;
} else if (options.database === "mongodb") {
databaseUrlLine = `\nDATABASE_URL="mongodb://localhost:27017/mydatabase"`;
}
envContent += databaseUrlLine;
}
if (options.database === "sqlite" && options.dbSetup !== "turso") {
if (!envContent.includes("DATABASE_URL")) {
envContent += "\nDATABASE_URL=file:./local.db";
}
}
}
if (
options.examples?.includes("ai") &&
!envContent.includes("GOOGLE_GENERATIVE_AI_API_KEY")
) {
envContent += "\nGOOGLE_GENERATIVE_AI_API_KEY=";
}
await fs.writeFile(envPath, envContent.trim());
const hasReactRouter = options.frontend.includes("react-router");
const hasTanStackRouter = options.frontend.includes("tanstack-router");
@@ -77,39 +54,84 @@ export async function setupEnvironmentVariables(
const hasWebFrontend =
hasReactRouter || hasTanStackRouter || hasTanStackStart;
let corsOrigin = "http://localhost:3000";
if (hasReactRouter) {
corsOrigin = "http://localhost:5173";
} else if (hasTanStackRouter || hasTanStackStart) {
corsOrigin = "http://localhost:3001";
}
let databaseUrl = "";
const specializedSetup =
options.dbSetup === "turso" ||
options.dbSetup === "prisma-postgres" ||
options.dbSetup === "mongodb-atlas";
if (!specializedSetup) {
if (options.database === "postgres") {
databaseUrl =
"postgresql://postgres:postgres@localhost:5432/mydb?schema=public";
} else if (options.database === "mysql") {
databaseUrl = "mysql://root:password@localhost:3306/mydb";
} else if (options.database === "mongodb") {
databaseUrl = "mongodb://localhost:27017/mydatabase";
} else if (options.database === "sqlite") {
databaseUrl = "file:./local.db";
}
}
const serverVars: EnvVariable[] = [
{
key: "CORS_ORIGIN",
value: corsOrigin,
condition: true,
},
{
key: "BETTER_AUTH_SECRET",
value: generateAuthSecret(),
condition: !!options.auth,
},
{
key: "BETTER_AUTH_URL",
value: "http://localhost:3000",
condition: !!options.auth,
},
{
key: "DATABASE_URL",
value: databaseUrl,
condition:
options.database !== "none" && databaseUrl !== "" && !specializedSetup,
},
{
key: "GOOGLE_GENERATIVE_AI_API_KEY",
value: "",
condition: options.examples?.includes("ai") || false,
},
];
await addEnvVariablesToFile(envPath, serverVars);
if (hasWebFrontend) {
const clientDir = path.join(projectDir, "apps/web");
await setupClientEnvFile(clientDir);
const clientVars: EnvVariable[] = [
{
key: "VITE_SERVER_URL",
value: "http://localhost:3000",
condition: true,
},
];
await addEnvVariablesToFile(path.join(clientDir, ".env"), clientVars);
}
if (options.frontend.includes("native")) {
const nativeDir = path.join(projectDir, "apps/native");
const nativeEnvPath = path.join(nativeDir, ".env");
let nativeEnvContent = "";
if (await fs.pathExists(nativeEnvPath)) {
nativeEnvContent = await fs.readFile(nativeEnvPath, "utf8");
}
if (!nativeEnvContent.includes("EXPO_PUBLIC_SERVER_URL")) {
nativeEnvContent += "EXPO_PUBLIC_SERVER_URL=http://localhost:3000\n";
}
await fs.writeFile(nativeEnvPath, nativeEnvContent.trim());
const nativeVars: EnvVariable[] = [
{
key: "EXPO_PUBLIC_SERVER_URL",
value: "http://localhost:3000",
condition: true,
},
];
await addEnvVariablesToFile(path.join(nativeDir, ".env"), nativeVars);
}
}
async function setupClientEnvFile(clientDir: string) {
const clientEnvPath = path.join(clientDir, ".env");
let clientEnvContent = "";
if (await fs.pathExists(clientEnvPath)) {
clientEnvContent = await fs.readFile(clientEnvPath, "utf8");
}
if (!clientEnvContent.includes("VITE_SERVER_URL")) {
clientEnvContent += "VITE_SERVER_URL=http://localhost:3000\n";
}
await fs.writeFile(clientEnvPath, clientEnvContent.trim());
}

View File

@@ -366,14 +366,15 @@ async function findGitignoreFiles(dir: string): Promise<string[]> {
function getOrmTemplateDir(orm: ProjectOrm, database: ProjectDatabase): string {
if (orm === "drizzle") {
return database === "sqlite"
? "template/with-drizzle-sqlite"
: "template/with-drizzle-postgres";
if (database === "sqlite") return "template/with-drizzle-sqlite";
if (database === "postgres") return "template/with-drizzle-postgres";
if (database === "mysql") return "template/with-drizzle-mysql";
}
if (orm === "prisma") {
if (database === "sqlite") return "template/with-prisma-sqlite";
if (database === "postgres") return "template/with-prisma-postgres";
if (database === "mysql") return "template/with-prisma-mysql";
if (database === "mongodb") return "template/with-prisma-mongodb";
}
@@ -382,14 +383,15 @@ function getOrmTemplateDir(orm: ProjectOrm, database: ProjectDatabase): string {
function getAuthLibDir(orm: ProjectOrm, database: ProjectDatabase): string {
if (orm === "drizzle") {
return database === "sqlite"
? "with-drizzle-sqlite-lib"
: "with-drizzle-postgres-lib";
if (database === "sqlite") return "with-drizzle-sqlite-lib";
if (database === "postgres") return "with-drizzle-postgres-lib";
if (database === "mysql") return "with-drizzle-mysql-lib";
}
if (orm === "prisma") {
if (database === "sqlite") return "with-prisma-sqlite-lib";
if (database === "postgres") return "with-prisma-postgres-lib";
if (database === "mysql") return "with-prisma-mysql-lib";
if (database === "mongodb") return "with-prisma-mongodb-lib";
}