40 lines
1.6 KiB
TypeScript
40 lines
1.6 KiB
TypeScript
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";
|
|
import { userDataRoutes } from "./userdata";
|
|
|
|
/**
|
|
* The learner feature: auth, library, reader, notes, progress and exercises.
|
|
* Returns the routes plus the `AuthService` that replaces the server's anonymous one.
|
|
*/
|
|
export function learnerFeature(ctx: ServerContext): Feature & { auth: AuthService } {
|
|
const ready = runMigrations(ctx.db);
|
|
ready.catch((e) => console.error("[learner] migrations failed", e));
|
|
const auth = createAuth(ctx, ready);
|
|
const routes: Feature["routes"] = {
|
|
"/api/auth/*": {
|
|
GET: (req, rc) => auth.handler(req, rc.user),
|
|
POST: (req, rc) => auth.handler(req, rc.user),
|
|
},
|
|
"/api/me": { GET: async (_req, rc) => json({ user: rc.user }) },
|
|
"/api/learner/providers": {
|
|
GET: async () => json({ emailPassword: true, providers: auth.providers(), sso: await auth.hasSso() }),
|
|
},
|
|
...adminRoutes(ctx, auth.service.invalidate),
|
|
...libraryRoutes(ctx),
|
|
...lessonRoutes(ctx),
|
|
...userDataRoutes(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 };
|
|
}
|