Switch database from SQLite to PostgreSQL
Replace in-memory JSON file storage with Prisma ORM using PostgreSQL. Update environment variables and Prisma schema accordingly.
This commit is contained in:
@@ -26,7 +26,7 @@ export async function POST(request: Request) {
|
||||
.filter((product): product is Product => Boolean(product))
|
||||
.map((product) => setupVerification[product.id])
|
||||
.filter(Boolean);
|
||||
const prefs = store.preferences();
|
||||
const prefs = await store.preferences();
|
||||
const prompt = [
|
||||
"You are a professional mountain bike suspension and tire setup tuner.",
|
||||
"Combine manufacturer setup ranges, community setup patterns, and the rider's past preferences.",
|
||||
|
||||
@@ -21,7 +21,7 @@ const schema = z.object({
|
||||
});
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json(store.listBuilds());
|
||||
return NextResponse.json(await store.listBuilds());
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
@@ -35,7 +35,7 @@ export async function POST(request: Request) {
|
||||
rearTireId: body.rearTireId,
|
||||
};
|
||||
const setup = { ...buildSetupDefaults(selection, body.rider), ...body.setup };
|
||||
const build = store.createBuild({
|
||||
const build = await store.createBuild({
|
||||
name: body.name,
|
||||
riderWeightKg: body.rider.weight,
|
||||
discipline: body.rider.discipline,
|
||||
|
||||
@@ -19,6 +19,6 @@ const schema = z.object({
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = schema.parse(await request.json());
|
||||
const review = store.createReview(body);
|
||||
const review = await store.createReview(body);
|
||||
return NextResponse.json(review, { status: 201 });
|
||||
}
|
||||
|
||||
+31
-53
@@ -1,58 +1,36 @@
|
||||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { prisma } from "./prisma";
|
||||
|
||||
type Database = {
|
||||
builds: any[];
|
||||
reviews: any[];
|
||||
};
|
||||
|
||||
const dbPath = path.join(process.cwd(), "data", "bike-app.json");
|
||||
|
||||
function readDb(): Database {
|
||||
mkdirSync(path.dirname(dbPath), { recursive: true });
|
||||
try {
|
||||
return JSON.parse(readFileSync(dbPath, "utf8")) as Database;
|
||||
} catch {
|
||||
return { builds: [], reviews: [] };
|
||||
}
|
||||
}
|
||||
|
||||
function writeDb(data: Database) {
|
||||
mkdirSync(path.dirname(dbPath), { recursive: true });
|
||||
writeFileSync(dbPath, JSON.stringify(data, null, 2));
|
||||
function parseSetup(build: any) {
|
||||
return {
|
||||
...build,
|
||||
setup: build.setup ? JSON.parse(build.setup) : {},
|
||||
};
|
||||
}
|
||||
|
||||
export const store = {
|
||||
listBuilds() {
|
||||
return readDb().builds.sort((a, b) => String(b.createdAt).localeCompare(String(a.createdAt)));
|
||||
},
|
||||
createBuild(input: any) {
|
||||
const data = readDb();
|
||||
const build = {
|
||||
id: crypto.randomUUID(),
|
||||
...input,
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
data.builds.unshift(build);
|
||||
writeDb(data);
|
||||
return build;
|
||||
},
|
||||
createReview(input: any) {
|
||||
const data = readDb();
|
||||
const review = {
|
||||
id: crypto.randomUUID(),
|
||||
...input,
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
data.reviews.unshift(review);
|
||||
writeDb(data);
|
||||
return review;
|
||||
},
|
||||
preferences() {
|
||||
const reviews = readDb().reviews;
|
||||
return {
|
||||
harshTendency: reviews.filter((review) => review.suspFeel >= 7).length,
|
||||
softTendency: reviews.filter((review) => review.suspFeel <= 3).length,
|
||||
};
|
||||
},
|
||||
async listBuilds() {
|
||||
const builds = await prisma.bikeBuild.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
return builds.map(parseSetup);
|
||||
},
|
||||
async createBuild(input: any) {
|
||||
const build = await prisma.bikeBuild.create({
|
||||
data: {
|
||||
...input,
|
||||
setup: JSON.stringify(input.setup ?? {}),
|
||||
},
|
||||
});
|
||||
return parseSetup(build);
|
||||
},
|
||||
async createReview(input: any) {
|
||||
return prisma.rideReview.create({ data: input });
|
||||
},
|
||||
async preferences() {
|
||||
const reviews = await prisma.rideReview.findMany();
|
||||
return {
|
||||
harshTendency: reviews.filter((review) => review.suspFeel >= 7).length,
|
||||
softTendency: reviews.filter((review) => review.suspFeel <= 3).length,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
|
||||
|
||||
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
|
||||
|
||||
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
||||
Reference in New Issue
Block a user