Skip to content

Commit b7ac81d

Browse files
Add dependency version constants and package management utility
1 parent bda0d5a commit b7ac81d

File tree

10 files changed

+169
-176
lines changed

10 files changed

+169
-176
lines changed

.changeset/icy-clowns-jam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-better-t-stack": patch
3+
---
4+
5+
Add dependency version constants and package management utility

apps/cli/src/constants.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,23 @@ export const DEFAULT_CONFIG: ProjectConfig = {
1616
packageManager: "npm",
1717
noInstall: false,
1818
};
19+
20+
export const dependencyVersionMap = {
21+
// Authentication
22+
"better-auth": "^1.1.16",
23+
24+
// Database - Drizzle
25+
"drizzle-orm": "^0.38.4",
26+
"drizzle-kit": "^0.30.4",
27+
28+
// Database - SQLite/PostgreSQL
29+
"@libsql/client": "^0.14.0",
30+
postgres: "^3.4.5",
31+
32+
// Database - Prisma
33+
"@prisma/client": "^5.7.1",
34+
"@prisma/adapter-libsql": "^5.7.1",
35+
prisma: "^5.7.1",
36+
} as const;
37+
38+
export type AvailableDependencies = keyof typeof dependencyVersionMap;

apps/cli/src/helpers/auth-setup.ts

Lines changed: 39 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import path from "node:path";
22
import { log } from "@clack/prompts";
33
import fs from "fs-extra";
44
import pc from "picocolors";
5-
import { PKG_ROOT } from "../constants";
65
import type { ProjectConfig } from "../types";
6+
import { addPackageDependency } from "../utils/add-package-deps";
77

88
export async function setupAuth(
99
projectDir: string,
@@ -18,53 +18,54 @@ export async function setupAuth(
1818
return;
1919
}
2020

21+
addPackageDependency({
22+
dependencies: ["better-auth"],
23+
devDependencies: false,
24+
projectDir: serverDir,
25+
});
26+
2127
const envPath = path.join(serverDir, ".env");
22-
const templateEnvPath = path.join(
23-
PKG_ROOT,
24-
getOrmTemplatePath(options.orm, options.database, "packages/server/_env"),
25-
);
26-
27-
if (!(await fs.pathExists(envPath))) {
28-
if (await fs.pathExists(templateEnvPath)) {
29-
await fs.copy(templateEnvPath, envPath);
30-
} else {
31-
const defaultEnv = `BETTER_AUTH_SECRET=${generateAuthSecret()}
32-
BETTER_AUTH_URL=http://localhost:3000
33-
CORS_ORIGIN=http://localhost:3001
34-
${options.database === "sqlite" ? "TURSO_CONNECTION_URL=http://127.0.0.1:8080" : ""}
35-
${options.orm === "prisma" ? 'DATABASE_URL="file:./dev.db"' : ""}
36-
`;
37-
await fs.writeFile(envPath, defaultEnv);
38-
}
39-
} else {
40-
let envContent = await fs.readFile(envPath, "utf8");
4128

42-
if (!envContent.includes("BETTER_AUTH_SECRET")) {
43-
envContent += `\nBETTER_AUTH_SECRET=${generateAuthSecret()}`;
44-
}
29+
// Create or update the .env file directly with required variables
30+
let envContent = "";
4531

46-
if (!envContent.includes("BETTER_AUTH_URL")) {
47-
envContent += "\nBETTER_AUTH_URL=http://localhost:3000";
48-
}
32+
if (await fs.pathExists(envPath)) {
33+
envContent = await fs.readFile(envPath, "utf8");
34+
}
4935

50-
if (!envContent.includes("CORS_ORIGIN")) {
51-
envContent += "\nCORS_ORIGIN=http://localhost:3001";
52-
}
36+
// Only add variables that don't already exist
37+
if (!envContent.includes("BETTER_AUTH_SECRET")) {
38+
envContent += `\nBETTER_AUTH_SECRET=${generateAuthSecret()}`;
39+
}
5340

54-
if (
55-
options.database === "sqlite" &&
56-
!envContent.includes("TURSO_CONNECTION_URL")
57-
) {
58-
envContent += "\nTURSO_CONNECTION_URL=http://127.0.0.1:8080";
59-
}
41+
if (!envContent.includes("BETTER_AUTH_URL")) {
42+
envContent += "\nBETTER_AUTH_URL=http://localhost:3000";
43+
}
6044

61-
if (options.orm === "prisma" && !envContent.includes("DATABASE_URL")) {
45+
if (!envContent.includes("CORS_ORIGIN")) {
46+
envContent += "\nCORS_ORIGIN=http://localhost:3001";
47+
}
48+
49+
if (
50+
options.database === "sqlite" &&
51+
!envContent.includes("TURSO_CONNECTION_URL")
52+
) {
53+
envContent += "\nTURSO_CONNECTION_URL=http://127.0.0.1:8080";
54+
}
55+
56+
if (options.orm === "prisma" && !envContent.includes("DATABASE_URL")) {
57+
if (options.database === "sqlite") {
6258
envContent += '\nDATABASE_URL="file:./dev.db"';
59+
} else if (options.database === "postgres") {
60+
envContent +=
61+
'\nDATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"';
6362
}
64-
65-
await fs.writeFile(envPath, envContent);
6663
}
6764

65+
// Write the updated content
66+
await fs.writeFile(envPath, envContent.trim());
67+
68+
// Create client .env file if it doesn't exist
6869
const clientEnvPath = path.join(clientDir, ".env");
6970
if (!(await fs.pathExists(clientEnvPath))) {
7071
const clientEnvContent = "VITE_SERVER_URL=http://localhost:3000\n";
@@ -109,24 +110,6 @@ ${options.orm === "prisma" ? 'DATABASE_URL="file:./dev.db"' : ""}
109110
}
110111
}
111112

112-
function getOrmTemplatePath(
113-
orm: string,
114-
database: string,
115-
relativePath: string,
116-
): string {
117-
if (orm === "drizzle") {
118-
return database === "sqlite"
119-
? `template/with-drizzle-sqlite/${relativePath}`
120-
: `template/with-drizzle-postgres/${relativePath}`;
121-
}
122-
if (orm === "prisma") {
123-
return database === "sqlite"
124-
? `template/with-prisma-sqlite/${relativePath}`
125-
: `template/with-prisma-postgres/${relativePath}`;
126-
}
127-
return `template/base/${relativePath}`;
128-
}
129-
130113
function generateAuthSecret(length = 32): string {
131114
const characters =
132115
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

apps/cli/src/helpers/create-project.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,6 @@ export async function createProject(options: ProjectConfig): Promise<string> {
4242
}
4343
}
4444

45-
const envFiles = [
46-
[
47-
path.join(projectDir, "packages/server/_env"),
48-
path.join(projectDir, "packages/server/.env"),
49-
],
50-
[
51-
path.join(projectDir, "packages/client/_env"),
52-
path.join(projectDir, "packages/client/.env"),
53-
],
54-
];
55-
56-
for (const [source, target] of envFiles) {
57-
if (await fs.pathExists(source)) {
58-
if (!(await fs.pathExists(target))) {
59-
await fs.move(source, target);
60-
} else {
61-
await fs.remove(source);
62-
}
63-
}
64-
}
65-
6645
await setupDatabase(
6746
projectDir,
6847
options.database,

apps/cli/src/helpers/db-setup.ts

Lines changed: 76 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import path from "node:path";
22
import { log, spinner } from "@clack/prompts";
33
import fs from "fs-extra";
44
import pc from "picocolors";
5+
import { addPackageDependency } from "../utils/add-package-deps";
56
import { setupTurso } from "./turso-setup";
67

78
export async function setupDatabase(
@@ -21,115 +22,100 @@ export async function setupDatabase(
2122
try {
2223
if (databaseType === "sqlite") {
2324
if (orm === "drizzle") {
24-
await setupDrizzleDependencies(projectDir, "sqlite");
25+
addPackageDependency({
26+
dependencies: ["drizzle-orm", "drizzle-kit", "@libsql/client"],
27+
devDependencies: false,
28+
projectDir: serverDir,
29+
});
2530
if (setupTursoDb) {
2631
await setupTurso(projectDir, true);
2732
}
2833
} else if (orm === "prisma") {
29-
await setupPrismaDependencies(projectDir, "sqlite");
34+
addPackageDependency({
35+
dependencies: [
36+
"@prisma/client",
37+
"@prisma/adapter-libsql",
38+
"@libsql/client",
39+
],
40+
devDependencies: false,
41+
projectDir: serverDir,
42+
});
43+
addPackageDependency({
44+
dependencies: ["prisma"],
45+
devDependencies: true,
46+
projectDir: serverDir,
47+
});
3048
if (setupTursoDb) {
3149
await setupTurso(projectDir, true);
3250
}
3351
}
3452
} else if (databaseType === "postgres") {
3553
if (orm === "drizzle") {
36-
await setupDrizzleDependencies(projectDir, "postgres");
54+
addPackageDependency({
55+
dependencies: ["drizzle-orm", "postgres"],
56+
devDependencies: false,
57+
projectDir: serverDir,
58+
});
59+
addPackageDependency({
60+
dependencies: ["drizzle-kit"],
61+
devDependencies: true,
62+
projectDir: serverDir,
63+
});
3764
} else if (orm === "prisma") {
38-
await setupPrismaDependencies(projectDir, "postgres");
65+
addPackageDependency({
66+
dependencies: ["@prisma/client"],
67+
devDependencies: false,
68+
projectDir: serverDir,
69+
});
70+
addPackageDependency({
71+
dependencies: ["prisma"],
72+
devDependencies: true,
73+
projectDir: serverDir,
74+
});
3975
}
4076
}
41-
} catch (error) {
42-
s.stop(pc.red("Failed to set up database"));
43-
if (error instanceof Error) {
44-
log.error(pc.red(error.message));
45-
}
46-
throw error;
47-
}
48-
}
4977

50-
async function setupDrizzleDependencies(
51-
projectDir: string,
52-
dbType: string,
53-
): Promise<void> {
54-
const serverDir = path.join(projectDir, "packages/server");
55-
56-
const packageJsonPath = path.join(serverDir, "package.json");
57-
if (await fs.pathExists(packageJsonPath)) {
58-
const packageJson = await fs.readJSON(packageJsonPath);
78+
const packageJsonPath = path.join(serverDir, "package.json");
79+
if (await fs.pathExists(packageJsonPath)) {
80+
const packageJson = await fs.readJSON(packageJsonPath);
5981

60-
packageJson.dependencies = {
61-
...packageJson.dependencies,
62-
"drizzle-orm": "^0.38.4",
63-
};
82+
if (orm === "drizzle") {
83+
packageJson.scripts = {
84+
...packageJson.scripts,
85+
"db:generate": "drizzle-kit generate",
86+
"db:migrate": "drizzle-kit push",
87+
"db:studio": "drizzle-kit studio",
88+
};
89+
} else if (orm === "prisma") {
90+
packageJson.scripts = {
91+
...packageJson.scripts,
92+
"prisma:generate": "prisma generate",
93+
"prisma:push": "prisma db push",
94+
"prisma:studio": "prisma studio",
95+
};
96+
}
6497

65-
if (dbType === "sqlite") {
66-
packageJson.dependencies["@libsql/client"] = "^0.14.0";
67-
} else if (dbType === "postgres") {
68-
packageJson.dependencies.postgres = "^3.4.5";
98+
await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
6999
}
70100

71-
packageJson.devDependencies = {
72-
...packageJson.devDependencies,
73-
"drizzle-kit": "^0.30.4",
74-
};
75-
76-
packageJson.scripts = {
77-
...packageJson.scripts,
78-
"db:generate": "drizzle-kit generate",
79-
"db:migrate": "drizzle-kit push",
80-
"db:studio": "drizzle-kit studio",
81-
};
82-
83-
await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
84-
}
85-
}
86-
87-
async function setupPrismaDependencies(
88-
projectDir: string,
89-
dbType: string,
90-
): Promise<void> {
91-
const serverDir = path.join(projectDir, "packages/server");
92-
93-
const packageJsonPath = path.join(serverDir, "package.json");
94-
if (await fs.pathExists(packageJsonPath)) {
95-
const packageJson = await fs.readJSON(packageJsonPath);
96-
97-
packageJson.dependencies = {
98-
...packageJson.dependencies,
99-
"@prisma/client": "^5.7.1",
100-
};
101-
102-
if (dbType === "sqlite") {
103-
packageJson.dependencies["@prisma/adapter-libsql"] = "^5.7.1";
104-
packageJson.dependencies["@libsql/client"] = "^0.14.0";
105-
} else if (dbType === "postgres") {
106-
// PostgreSQL specific dependencies if needed
101+
if (orm === "prisma") {
102+
const envPath = path.join(serverDir, ".env");
103+
if (await fs.pathExists(envPath)) {
104+
const envContent = await fs.readFile(envPath, "utf8");
105+
if (!envContent.includes("DATABASE_URL")) {
106+
const databaseUrlLine =
107+
databaseType === "sqlite"
108+
? `\nDATABASE_URL="file:./dev.db"`
109+
: `\nDATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"`;
110+
await fs.appendFile(envPath, databaseUrlLine);
111+
}
112+
}
107113
}
108-
109-
packageJson.devDependencies = {
110-
...packageJson.devDependencies,
111-
prisma: "^5.7.1",
112-
};
113-
114-
packageJson.scripts = {
115-
...packageJson.scripts,
116-
"prisma:generate": "prisma generate",
117-
"prisma:push": "prisma db push",
118-
"prisma:studio": "prisma studio",
119-
};
120-
121-
await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
122-
}
123-
124-
const envPath = path.join(serverDir, ".env");
125-
if (await fs.pathExists(envPath)) {
126-
const envContent = await fs.readFile(envPath, "utf8");
127-
if (!envContent.includes("DATABASE_URL")) {
128-
const databaseUrlLine =
129-
dbType === "sqlite"
130-
? `\nDATABASE_URL="file:./dev.db"`
131-
: `\nDATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"`;
132-
await fs.appendFile(envPath, databaseUrlLine);
114+
} catch (error) {
115+
s.stop(pc.red("Failed to set up database"));
116+
if (error instanceof Error) {
117+
log.error(pc.red(error.message));
133118
}
119+
throw error;
134120
}
135121
}

0 commit comments

Comments
 (0)