From 478ebeb255478af2b5b3f5d9dc3a5d8de2b7aaf5 Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Fri, 30 Oct 2026 03:24:28 +0100 Subject: [PATCH] fix(learner): narrow lesson target result for the type checker Co-Authored-By: Claude Opus 5.5 --- packages/feature-learner/src/server/userdata.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/feature-learner/src/server/userdata.ts b/packages/feature-learner/src/server/userdata.ts index 050b243..f2f21f2 100644 --- a/packages/feature-learner/src/server/userdata.ts +++ b/packages/feature-learner/src/server/userdata.ts @@ -45,7 +45,7 @@ export function userDataRoutes(ctx: ServerContext): Feature["routes"] { if (!b || !STATES.includes(b.state as ProgressState)) return badRequest("state must be not-started, in-progress or done"); if (b.positionSeconds !== undefined && (typeof b.positionSeconds !== "number" || !Number.isFinite(b.positionSeconds) || b.positionSeconds < 0)) return badRequest("positionSeconds must be a non-negative number"); const t = await target(user.id, user, courseId, lessonId); - if ("error" in t) return t.error; + if (t.error) return t.error; const prior = t.progress[lessonId]; // A position report ("in-progress") never undoes "done"; only an explicit not-started does. const state = prior?.state === "done" && b.state === "in-progress" ? "done" : b.state!; @@ -103,7 +103,7 @@ export function userDataRoutes(ctx: ServerContext): Feature["routes"] { if (!b || typeof b.code !== "string") return badRequest("code is required"); if (b.code.length > MAX_CODE) return badRequest("code is too long"); const t = await target(user.id, user, courseId, lessonId); - if ("error" in t) return t.error; + if (t.error) return t.error; if (t.entry.lesson.type !== "exercise") return badRequest("not an exercise"); const passed = b.passed === true; await attempts.save({ userId: user.id, courseId, lessonId, track: b.track || "default", code: b.code, result: b.result ?? null, passed, updatedAt: new Date().toISOString() });