feat(learner): library, search, course outline with gating, lesson payload API

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas Winther
2026-10-30 03:23:30 +01:00
co-authored by Claude Opus 5.5
parent a8a8e32bcb
commit 5f85ce1d4b
10 changed files with 699 additions and 1 deletions
+11 -1
View File
@@ -1,8 +1,10 @@
import type { AuthService, Feature, ServerContext } from "@stc/contracts";
import type { AuthService, Feature, RouteHandler, ServerContext } from "@stc/contracts";
import { createAuth } from "./auth";
import { runMigrations } from "./migrate";
import { json } from "./http";
import { adminRoutes } from "./admin";
import { libraryRoutes } from "./catalog";
import { lessonRoutes } from "./lesson";
/**
* The learner feature: auth, library, reader, notes, progress and exercises.
@@ -22,6 +24,14 @@ export function learnerFeature(ctx: ServerContext): Feature & { auth: AuthServic
GET: async () => json({ emailPassword: true, providers: auth.providers(), sso: await auth.hasSso() }),
},
...adminRoutes(ctx, auth.service.invalidate),
...libraryRoutes(ctx),
...lessonRoutes(ctx),
};
// Every handler waits for the learner migrations (a no-op once Phase 2 runs them in migrate()).
for (const methods of Object.values(routes)) {
for (const [m, h] of Object.entries(methods)) {
(methods as Record<string, RouteHandler>)[m] = async (req, rc) => { await ready; return h!(req, rc); };
}
}
return { name: "learner", routes, auth: auth.service };
}