Files
STCourses/docs/contract-requests/learner.md
T

1.8 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

@stc/feature-learner's index exports both learnerFeature (server) and learnerWeb/LessonView (browser). Bun's browser bundler tree-shakes the server half (checked), so one entry works. The web shell imports learnerWeb from @stc/feature-learner; the studio can import LessonView the same way.