3.1 KiB
Contract requests from WP-A (learner)
1. Feature factories and the auth service (apps/server/src/main.ts, @stc/contracts)
Problem. Phase 0 passes Feature[] to startServer, but ServerContext is built inside startServer, so a feature that needs ctx (every Phase 1 package exports xFeature(ctx)) cannot be listed. There is also no way for a feature to replace the anonymous AuthService.
Workaround in feat/learner (applied, small): startServer accepts FeatureEntry = Feature | ((ctx) => Feature & { auth?: AuthService }). Factories run after ctx exists (with ctx.jobs set right after they return, so factories must not use jobs synchronously), and a feature carrying auth replaces ctx.auth. The main entry lists learnerFeature.
Proposal. Move both into the contract:
export type FeatureFactory = (ctx: ServerContext) => Feature;
export interface Feature { /* … */ auth?: AuthService; migrationsDirs?: string[] }
and let startServer take Array<Feature | FeatureFactory>.
2. Migrations per package
migrate() only reads packages/db/migrations. The learner package exports migrationsDirs and, until Phase 2 wires it in, runs its own migrations lazily inside learnerFeature(ctx) through runMigrations(db, dirs), which uses the same schema_migrations table and file-name keys. When migrate() learns about migrationsDirs, the lazy call becomes a no-op; it can then be removed.
3. Package entry for the browser
Problem. The package index exports both the server (learnerFeature, which pulls in Better Auth and @better-auth/sso) and the browser half (learnerWeb, LessonView). A browser bundle of the index fails: @better-auth/sso imports X509Certificate from node:crypto, which has no browser polyfill. The root tsconfig.json maps @stc/* to packages/*/src, so package.json exports subpaths are not used either.
Workaround in feat/learner (applied). LessonView and learnerWeb are exported from the index (for server-side and type use) and from a browser-only entry, @stc/feature-learner/web. That subpath resolves through the existing mapping to packages/feature-learner/web/src/index.ts, a one-line re-export of src/web. apps/web/src/features.ts imports learnerWeb from it, and the studio should import LessonView from it too.
Proposal. Add "@stc/*/web": ["packages/*/src/web"] ahead of the general mapping in tsconfig.json (Bun honours tsconfig paths), and let every feature package expose src/web/index.ts. The shim directory can then be deleted. This also settles the importer's relative import in features.ts.
4. LessonView for the studio preview
import { LessonView } from "@stc/feature-learner/web". Props: lesson: LessonPayload (the JSON from GET /api/courses/:id/lessons/:lessonId), plus optional look, track, onTrackChange, preview. With preview set, it makes no notes, attempt or progress requests; it still loads code listings and decks through the normal media routes. It injects its own stylesheet (scoped under .lr) and works with or without a router.