mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
Refactor Prisma integration and improve project setup
- Move Prisma files to standard /prisma directory - Remove Turso adapter dependencies for Prisma - Fix auth configuration in templates - Update router devtools package name - Simplify post-installation instructions - Improve npm scripts with cleaner commands
This commit is contained in:
@@ -31,7 +31,6 @@ export const dependencyVersionMap = {
|
|||||||
|
|
||||||
// Database - Prisma
|
// Database - Prisma
|
||||||
"@prisma/client": "^5.7.1",
|
"@prisma/client": "^5.7.1",
|
||||||
"@prisma/adapter-libsql": "^5.7.1",
|
|
||||||
prisma: "^5.7.1",
|
prisma: "^5.7.1",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ services:
|
|||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
- TURSO_DATABASE_URL=\${TURSO_DATABASE_URL}
|
- TURSO_CONNECTION_URL=\${TURSO_CONNECTION_URL}
|
||||||
- TURSO_AUTH_TOKEN=\${TURSO_AUTH_TOKEN}
|
- TURSO_AUTH_TOKEN=\${TURSO_AUTH_TOKEN}
|
||||||
- CORS_ORIGIN=\${CORS_ORIGIN}
|
- CORS_ORIGIN=\${CORS_ORIGIN}
|
||||||
restart: always
|
restart: always
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export async function createProject(options: ProjectConfig): Promise<string> {
|
|||||||
const serverPackageJson = await fs.readJson(serverPackageJsonPath);
|
const serverPackageJson = await fs.readJson(serverPackageJsonPath);
|
||||||
|
|
||||||
if (options.database !== "none") {
|
if (options.database !== "none") {
|
||||||
if (options.database === "sqlite" && options.turso) {
|
if (options.database === "sqlite") {
|
||||||
serverPackageJson.scripts["db:local"] =
|
serverPackageJson.scripts["db:local"] =
|
||||||
"turso dev --db-file local.db";
|
"turso dev --db-file local.db";
|
||||||
}
|
}
|
||||||
@@ -99,19 +99,19 @@ export async function createProject(options: ProjectConfig): Promise<string> {
|
|||||||
"npx @better-auth/cli generate --output ./src/db/auth-schema.ts";
|
"npx @better-auth/cli generate --output ./src/db/auth-schema.ts";
|
||||||
|
|
||||||
if (options.orm === "prisma") {
|
if (options.orm === "prisma") {
|
||||||
serverPackageJson.scripts["db:push"] = "npx prisma db push";
|
serverPackageJson.scripts["db:push"] = "prisma db push";
|
||||||
serverPackageJson.scripts["db:studio"] = "npx prisma studio";
|
serverPackageJson.scripts["db:studio"] = "prisma studio";
|
||||||
} else if (options.orm === "drizzle") {
|
} else if (options.orm === "drizzle") {
|
||||||
serverPackageJson.scripts["db:push"] = "npx drizzle-kit push";
|
serverPackageJson.scripts["db:push"] = "drizzle-kit push";
|
||||||
serverPackageJson.scripts["db:studio"] = "npx drizzle-kit studio";
|
serverPackageJson.scripts["db:studio"] = "drizzle-kit studio";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (options.orm === "prisma") {
|
if (options.orm === "prisma") {
|
||||||
serverPackageJson.scripts["db:push"] = "npx prisma db push";
|
serverPackageJson.scripts["db:push"] = "prisma db push";
|
||||||
serverPackageJson.scripts["db:studio"] = "npx prisma studio";
|
serverPackageJson.scripts["db:studio"] = "prisma studio";
|
||||||
} else if (options.orm === "drizzle") {
|
} else if (options.orm === "drizzle") {
|
||||||
serverPackageJson.scripts["db:push"] = "npx drizzle-kit push";
|
serverPackageJson.scripts["db:push"] = "drizzle-kit push";
|
||||||
serverPackageJson.scripts["db:studio"] = "npx drizzle-kit studio";
|
serverPackageJson.scripts["db:studio"] = "drizzle-kit studio";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,6 @@ export async function createProject(options: ProjectConfig): Promise<string> {
|
|||||||
await createReadme(projectDir, options);
|
await createReadme(projectDir, options);
|
||||||
|
|
||||||
displayPostInstallInstructions(
|
displayPostInstallInstructions(
|
||||||
options.auth,
|
|
||||||
options.database,
|
options.database,
|
||||||
options.projectName,
|
options.projectName,
|
||||||
options.packageManager,
|
options.packageManager,
|
||||||
|
|||||||
@@ -32,11 +32,7 @@ export async function setupDatabase(
|
|||||||
}
|
}
|
||||||
} else if (orm === "prisma") {
|
} else if (orm === "prisma") {
|
||||||
addPackageDependency({
|
addPackageDependency({
|
||||||
dependencies: [
|
dependencies: ["@prisma/client"],
|
||||||
"@prisma/client",
|
|
||||||
"@prisma/adapter-libsql",
|
|
||||||
"@libsql/client",
|
|
||||||
],
|
|
||||||
devDependencies: false,
|
devDependencies: false,
|
||||||
projectDir: serverDir,
|
projectDir: serverDir,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ export async function setupEnvironmentVariables(
|
|||||||
const serverDir = path.join(projectDir, "packages/server");
|
const serverDir = path.join(projectDir, "packages/server");
|
||||||
const clientDir = path.join(projectDir, "packages/client");
|
const clientDir = path.join(projectDir, "packages/client");
|
||||||
|
|
||||||
// Set up server env variables
|
|
||||||
const envPath = path.join(serverDir, ".env");
|
const envPath = path.join(serverDir, ".env");
|
||||||
let envContent = "";
|
let envContent = "";
|
||||||
|
|
||||||
@@ -18,7 +17,6 @@ export async function setupEnvironmentVariables(
|
|||||||
envContent = await fs.readFile(envPath, "utf8");
|
envContent = await fs.readFile(envPath, "utf8");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth environment variables
|
|
||||||
if (options.auth) {
|
if (options.auth) {
|
||||||
if (!envContent.includes("BETTER_AUTH_SECRET")) {
|
if (!envContent.includes("BETTER_AUTH_SECRET")) {
|
||||||
envContent += `\nBETTER_AUTH_SECRET=${generateAuthSecret()}`;
|
envContent += `\nBETTER_AUTH_SECRET=${generateAuthSecret()}`;
|
||||||
@@ -33,12 +31,11 @@ export async function setupEnvironmentVariables(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database environment variables
|
|
||||||
if (options.database !== "none") {
|
if (options.database !== "none") {
|
||||||
if (options.orm === "prisma" && !envContent.includes("DATABASE_URL")) {
|
if (options.orm === "prisma" && !envContent.includes("DATABASE_URL")) {
|
||||||
const databaseUrlLine =
|
const databaseUrlLine =
|
||||||
options.database === "sqlite"
|
options.database === "sqlite"
|
||||||
? `\nDATABASE_URL="file:./dev.db"`
|
? ""
|
||||||
: `\nDATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"`;
|
: `\nDATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"`;
|
||||||
envContent += databaseUrlLine;
|
envContent += databaseUrlLine;
|
||||||
}
|
}
|
||||||
@@ -54,7 +51,6 @@ export async function setupEnvironmentVariables(
|
|||||||
|
|
||||||
await fs.writeFile(envPath, envContent.trim());
|
await fs.writeFile(envPath, envContent.trim());
|
||||||
|
|
||||||
// Set up client env variables
|
|
||||||
if (options.auth) {
|
if (options.auth) {
|
||||||
const clientEnvPath = path.join(clientDir, ".env");
|
const clientEnvPath = path.join(clientDir, ".env");
|
||||||
if (!(await fs.pathExists(clientEnvPath))) {
|
if (!(await fs.pathExists(clientEnvPath))) {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { log } from "@clack/prompts";
|
|||||||
import pc from "picocolors";
|
import pc from "picocolors";
|
||||||
|
|
||||||
export function displayPostInstallInstructions(
|
export function displayPostInstallInstructions(
|
||||||
hasAuth: boolean,
|
|
||||||
database: string,
|
database: string,
|
||||||
projectName: string,
|
projectName: string,
|
||||||
packageManager: string,
|
packageManager: string,
|
||||||
@@ -12,52 +11,56 @@ export function displayPostInstallInstructions(
|
|||||||
const runCmd = packageManager === "npm" ? "npm run" : packageManager;
|
const runCmd = packageManager === "npm" ? "npm run" : packageManager;
|
||||||
const cdCmd = `cd ${projectName}`;
|
const cdCmd = `cd ${projectName}`;
|
||||||
|
|
||||||
const steps = [];
|
log.info(`${pc.cyan("Project created successfully!")}
|
||||||
|
|
||||||
if (!depsInstalled) {
|
${pc.bold("Next steps:")}
|
||||||
steps.push(`${pc.cyan(packageManager)} install`);
|
${pc.cyan("1.")} ${cdCmd}
|
||||||
}
|
${!depsInstalled ? `${pc.cyan("2.")} ${packageManager} install\n` : ""}${pc.cyan(depsInstalled ? "2." : "3.")} ${runCmd} dev
|
||||||
|
|
||||||
if (hasAuth && database !== "none") {
|
${pc.bold("Your project will be available at:")}
|
||||||
steps.push(`${pc.yellow("Database Setup:")}`);
|
${pc.cyan("•")} Frontend: http://localhost:3001
|
||||||
|
${pc.cyan("•")} API: http://localhost:3000
|
||||||
|
|
||||||
if (orm === "prisma") {
|
${database !== "none" ? getDatabaseInstructions(database, orm, runCmd) : ""}`);
|
||||||
steps.push(
|
}
|
||||||
`${pc.cyan("1.")} Generate Prisma client: ${pc.green(`${runCmd} prisma:generate`)}`,
|
|
||||||
);
|
function getDatabaseInstructions(
|
||||||
steps.push(
|
database: string,
|
||||||
`${pc.cyan("2.")} Push schema to database: ${pc.green(`${runCmd} prisma:push`)}`,
|
orm?: string,
|
||||||
);
|
runCmd?: string,
|
||||||
} else if (orm === "drizzle") {
|
): string {
|
||||||
steps.push(
|
const instructions = [];
|
||||||
`${pc.cyan("1.")} Apply migrations: ${pc.green(`${runCmd} db:push`)}`,
|
|
||||||
|
if (orm === "prisma") {
|
||||||
|
instructions.push(
|
||||||
|
`${pc.cyan("•")} Apply schema: ${pc.dim(`${runCmd} db:push`)}`,
|
||||||
|
);
|
||||||
|
instructions.push(
|
||||||
|
`${pc.cyan("•")} Database UI: ${pc.dim(`${runCmd} db:studio`)}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (database === "turso") {
|
||||||
|
instructions.push(
|
||||||
|
`${pc.yellow("NOTE:")} Turso support with Prisma is in Early Access and requires additional setup.`,
|
||||||
|
`${pc.dim("Learn more at: https://www.prisma.io/docs/orm/overview/databases/turso")}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
} else if (orm === "drizzle") {
|
||||||
|
instructions.push(
|
||||||
if (database === "postgres") {
|
`${pc.cyan("•")} Apply schema: ${pc.dim(`${runCmd} db:push`)}`,
|
||||||
steps.push(`${pc.yellow("PostgreSQL Configuration:")}`);
|
|
||||||
steps.push(
|
|
||||||
`Make sure to update ${pc.cyan("packages/server/.env")} with your PostgreSQL connection string.`,
|
|
||||||
);
|
);
|
||||||
} else if (database === "sqlite") {
|
instructions.push(
|
||||||
steps.push(`${pc.yellow("Database Configuration:")}`);
|
`${pc.cyan("•")} Database UI: ${pc.dim(`${runCmd} db:studio`)}`,
|
||||||
steps.push(
|
|
||||||
`${pc.cyan("packages/server/.env")} contains your SQLite connection details. Update if needed.`,
|
|
||||||
);
|
|
||||||
steps.push(
|
|
||||||
`Start the local SQLite database with: ${pc.green(`${runCmd} db:local`)}`,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
steps.push(`${pc.yellow("Start Development:")}`);
|
if (database === "sqlite") {
|
||||||
steps.push(`${pc.green(`${runCmd} dev`)}`);
|
instructions.push(
|
||||||
|
`${pc.cyan("•")} Start local DB: ${pc.dim(`cd packages/server && ${runCmd} db:local`)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
log.info(`${pc.cyan("Installation completed!")} Here are some next steps:
|
return instructions.length
|
||||||
|
? `${pc.bold("Database commands:")}\n${instructions.join("\n")}\n\n`
|
||||||
${cdCmd}
|
: "";
|
||||||
${steps.join("\n")}
|
|
||||||
|
|
||||||
The client application will be available at ${pc.cyan("http://localhost:3001")}
|
|
||||||
The API server will be running at ${pc.cyan("http://localhost:3000")}`);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export async function gatherConfig(
|
|||||||
auth: ({ results }) =>
|
auth: ({ results }) =>
|
||||||
getAuthChoice(flags.auth, results.database !== "none"),
|
getAuthChoice(flags.auth, results.database !== "none"),
|
||||||
turso: ({ results }) =>
|
turso: ({ results }) =>
|
||||||
results.database === "sqlite"
|
results.database === "sqlite" && results.orm !== "prisma"
|
||||||
? getTursoSetupChoice(flags.turso)
|
? getTursoSetupChoice(flags.turso)
|
||||||
: Promise.resolve(false),
|
: Promise.resolve(false),
|
||||||
addons: () => getAddonsChoice(flags.addons),
|
addons: () => getAddonsChoice(flags.addons),
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
"@tanstack/react-query": "^5.66.0",
|
"@tanstack/react-query": "^5.66.0",
|
||||||
"@tanstack/react-query-devtools": "^5.66.0",
|
"@tanstack/react-query-devtools": "^5.66.0",
|
||||||
"@tanstack/react-router": "^1.101.0",
|
"@tanstack/react-router": "^1.101.0",
|
||||||
"@tanstack/router-devtools": "^1.101.0",
|
"@tanstack/react-router-devtools": "^1.114.25",
|
||||||
"@trpc/client": "^11.0.0-rc.748",
|
"@trpc/client": "^11.0.0-rc.748",
|
||||||
"@trpc/react-query": "^11.0.0-rc.748",
|
"@trpc/react-query": "^11.0.0-rc.748",
|
||||||
"@trpc/server": "^11.0.0-rc.748",
|
"@trpc/server": "^11.0.0-rc.748",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
createRootRouteWithContext,
|
createRootRouteWithContext,
|
||||||
useRouterState,
|
useRouterState,
|
||||||
} from "@tanstack/react-router";
|
} from "@tanstack/react-router";
|
||||||
import { TanStackRouterDevtools } from "@tanstack/router-devtools";
|
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
|
||||||
import "../index.css";
|
import "../index.css";
|
||||||
|
|
||||||
export interface RouterAppContext {
|
export interface RouterAppContext {
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
import { betterAuth } from "better-auth";
|
import { betterAuth } from "better-auth";
|
||||||
import { prismaAdapter } from "better-auth/adapters/prisma";
|
import { prismaAdapter } from "better-auth/adapters/prisma";
|
||||||
import prisma from "../db";
|
import prisma from "../../prisma";
|
||||||
|
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
database: prismaAdapter(prisma, {
|
database: prismaAdapter(prisma, {
|
||||||
provider: "pg",
|
provider: "pg",
|
||||||
}),
|
}),
|
||||||
|
trustedOrigins: [process.env.CORS_ORIGIN!],
|
||||||
|
emailAndPassword: { enabled: true },
|
||||||
|
advanced: {
|
||||||
|
defaultCookieAttributes: {
|
||||||
|
sameSite: "none",
|
||||||
|
secure: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
|
||||||
|
let prisma = new PrismaClient();
|
||||||
|
|
||||||
|
export default prisma;
|
||||||
@@ -6,12 +6,11 @@
|
|||||||
|
|
||||||
generator client {
|
generator client {
|
||||||
provider = "prisma-client-js"
|
provider = "prisma-client-js"
|
||||||
previewFeatures = ["driverAdapters"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "sqlite"
|
provider = "sqlite"
|
||||||
url = env("TURSO_DATABASE_URL")
|
url = "file:./dev.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import { PrismaClient } from "@prisma/client";
|
|
||||||
import { PrismaLibSQL } from "@prisma/adapter-libsql";
|
|
||||||
import { createClient } from "@libsql/client";
|
|
||||||
|
|
||||||
const libsql = createClient({
|
|
||||||
url: process.env.TURSO_DATABASE_URL!,
|
|
||||||
authToken: process.env.TURSO_AUTH_TOKEN,
|
|
||||||
});
|
|
||||||
|
|
||||||
const adapter = new PrismaLibSQL(libsql);
|
|
||||||
const prisma = new PrismaClient({ adapter });
|
|
||||||
|
|
||||||
export default prisma;
|
|
||||||
@@ -1,9 +1,17 @@
|
|||||||
import { betterAuth } from "better-auth";
|
import { betterAuth } from "better-auth";
|
||||||
import { prismaAdapter } from "better-auth/adapters/prisma";
|
import { prismaAdapter } from "better-auth/adapters/prisma";
|
||||||
import prisma from "../db";
|
import prisma from "../../prisma";
|
||||||
|
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
database: prismaAdapter(prisma, {
|
database: prismaAdapter(prisma, {
|
||||||
provider: "sqlite",
|
provider: "sqlite",
|
||||||
}),
|
}),
|
||||||
|
trustedOrigins: [process.env.CORS_ORIGIN!],
|
||||||
|
emailAndPassword: { enabled: true },
|
||||||
|
advanced: {
|
||||||
|
defaultCookieAttributes: {
|
||||||
|
sameSite: "none",
|
||||||
|
secure: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,9 +4,12 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "turbo build",
|
"build": "turbo build",
|
||||||
"dev": "turbo dev",
|
"dev": "turbo dev",
|
||||||
|
"dev:cli": "turbo run dev --filter=create-better-t-stack",
|
||||||
|
"cli": "cd apps/cli && node dist/index.js",
|
||||||
|
"dev:web": "turbo run dev --filter=web",
|
||||||
"build:web": "turbo run build --filter=web",
|
"build:web": "turbo run build --filter=web",
|
||||||
"build:web:cloudflare": "bun install && bun run build:web",
|
"build:web:cloudflare": "bun install && bun run build:web",
|
||||||
"build:cli": "turbo run build --filter=cli",
|
"build:cli": "turbo run build --filter=create-better-t-stack",
|
||||||
"check": "turbo check",
|
"check": "turbo check",
|
||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
"publish-packages": "turbo run build && changeset publish"
|
"publish-packages": "turbo run build && changeset publish"
|
||||||
|
|||||||
Reference in New Issue
Block a user