harden database interactions and improve error handling
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import { db } from "../../../db/index";
|
||||
import { topics, lessons } from "../../../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const id = getRouterParam(event, "id")!;
|
||||
|
||||
const topic = await db.query.topics.findFirst({ where: eq(topics.id, id) });
|
||||
if (!topic) throw createError({ statusCode: 404, message: "Topic not found" });
|
||||
|
||||
const lesson = await db.query.lessons.findFirst({ where: eq(lessons.topicId, id) });
|
||||
if (!lesson) throw createError({ statusCode: 404, message: "No lesson for this topic" });
|
||||
|
||||
return { branchStatus: lesson.branchStatus };
|
||||
});
|
||||
@@ -29,7 +29,7 @@ export default defineEventHandler(async (event) => {
|
||||
eq(topics.status, "pending")
|
||||
)
|
||||
});
|
||||
if (nextTopic) generateLesson(nextTopic.id);
|
||||
if (nextTopic) generateLesson(nextTopic.id).catch((e) => console.error("[pre-gen]", e));
|
||||
|
||||
return { status: "ready" };
|
||||
} catch (err: any) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { db } from "../../../db/index";
|
||||
import { topics, userProgress } from "../../../db/schema";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { eq, and, sql } from "drizzle-orm";
|
||||
import { randomUUID } from "crypto";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
@@ -12,26 +12,25 @@ export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
const { lessonComplete, quizScore, tookBranches, branchCount } = body ?? {};
|
||||
|
||||
const existing = await db.query.userProgress.findFirst({
|
||||
where: and(
|
||||
eq(userProgress.topicId, id),
|
||||
eq(userProgress.courseId, topic.courseId)
|
||||
),
|
||||
});
|
||||
// manual validation — no zod
|
||||
if (lessonComplete !== undefined && typeof lessonComplete !== "boolean") {
|
||||
throw createError({ statusCode: 400, message: "lessonComplete must be a boolean" });
|
||||
}
|
||||
if (quizScore !== undefined && quizScore !== null) {
|
||||
if (!Number.isInteger(quizScore)) throw createError({ statusCode: 400, message: "quizScore must be an integer" });
|
||||
}
|
||||
if (tookBranches !== undefined && typeof tookBranches !== "boolean") {
|
||||
throw createError({ statusCode: 400, message: "tookBranches must be a boolean" });
|
||||
}
|
||||
if (branchCount !== undefined && !Number.isInteger(branchCount)) {
|
||||
throw createError({ statusCode: 400, message: "branchCount must be an integer" });
|
||||
}
|
||||
|
||||
if (existing) {
|
||||
await db
|
||||
.update(userProgress)
|
||||
.set({
|
||||
lessonComplete: lessonComplete ?? existing.lessonComplete,
|
||||
quizScore: quizScore ?? existing.quizScore,
|
||||
tookBranches: tookBranches ?? existing.tookBranches,
|
||||
branchCount: branchCount ?? existing.branchCount,
|
||||
updatedAt: new Date().toISOString(),
|
||||
})
|
||||
.where(eq(userProgress.id, existing.id));
|
||||
} else {
|
||||
await db.insert(userProgress).values({
|
||||
|
||||
// NOTE: this requires a UNIQUE constraint on (course_id, topic_id) in user_progress — the migration adds this
|
||||
await db
|
||||
.insert(userProgress)
|
||||
.values({
|
||||
id: randomUUID(),
|
||||
courseId: topic.courseId,
|
||||
topicId: id,
|
||||
@@ -39,8 +38,18 @@ export default defineEventHandler(async (event) => {
|
||||
quizScore: quizScore ?? null,
|
||||
tookBranches: tookBranches ?? false,
|
||||
branchCount: branchCount ?? 0,
|
||||
updatedAt: sql`datetime('now')`,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: [userProgress.courseId, userProgress.topicId],
|
||||
set: {
|
||||
lessonComplete: lessonComplete ?? sql`excluded.lesson_complete`,
|
||||
quizScore: quizScore !== undefined ? quizScore : sql`excluded.quiz_score`,
|
||||
tookBranches: tookBranches ?? sql`excluded.took_branches`,
|
||||
branchCount: branchCount ?? sql`excluded.branch_count`,
|
||||
updatedAt: sql`datetime('now')`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user