diff --git a/docs/classroom-split-plan.md b/docs/classroom-split-plan.md new file mode 100644 index 0000000..fa10edb --- /dev/null +++ b/docs/classroom-split-plan.md @@ -0,0 +1,206 @@ +# classroomController.js split plan + +**Source:** `backend/src/controllers/classroomController.js` — 1618 lines, 70 functions +**Target:** `backend/src/controllers/classroom/` — 8 files +**Strategy:** pure mechanical split, no behaviour changes, facade preserves compatibility + +--- + +## Target structure + +``` +backend/src/controllers/ + classroomController.js ← 8-line re-export facade (unchanged public API) + classroom/ + _shared.js ← shared helpers used by multiple files + sessions.js ← session lifecycle + guest tokens + strokes.js ← whiteboard strokes + cursor preview + pages.js ← page CRUD + templates + board theme + chat.js ← chat messages, reactions, attachments, export + permissions.js ← draw permissions, hand-raise, mute, screen, attendance + sim.js ← simulation relay (simOpen/State/Mode/Annotate/Close) + admin.js ← history, notes, templates, admin views +``` + +--- + +## File mapping + +### `classroom/_shared.js` +Helpers used by 2+ files. Exports: `{ GUEST_EVENTS, emitToSession, hasAccess, canDraw }` + +| Symbol | Lines | Used by | +|--------|-------|---------| +| `GUEST_EVENTS` | 21–27 | sessions, strokes, pages, permissions, sim | +| `emitToSession` | 31–34 | sessions, strokes, pages, chat, permissions, sim | +| `hasAccess` | 37–48 | sessions, strokes, pages, chat, permissions, admin | +| `canDraw` | 13–18 | strokes | + +Imports: `db`, `broadcastToSession` from `ws-server` + +--- + +### `classroom/sessions.js` +Session lifecycle, signal (WebRTC), guest tokens. + +| Function | Lines | +|----------|-------| +| `createSession` | 51–105 | +| `getSession` | 106–128 | +| `endSession` | 129–145 | +| `getActiveSession` | 146–163 | +| `getMyActive` | 164–177 | +| `joinSession` | 178–210 | +| `leaveSession` | 211–231 | +| `getMySession` | 385–433 | +| `signal` | 359–384 | +| `generateGuestToken` | 1520–1531 | +| `revokeGuestToken` | 1532–1542 | +| `getGuestToken` | 1543–end | + +Imports: `db`, `crypto`, `invalidateSession`, `emitToUser` (from `ws-server`), `_shared` + +--- + +### `classroom/strokes.js` +Whiteboard stroke CRUD + live cursor/preview broadcast. + +| Function | Lines | +|----------|-------| +| `postStrokes` | 568–608 | +| `getStrokes` | 609–635 | +| `updateStroke` | 636–662 | +| `deleteStroke` | 663–686 | +| `clearPage` | 687–700 | +| `previewStroke` | 815–840 | +| `broadcastCursor` | 901–918 | + +Imports: `db`, `_shared` + +--- + +### `classroom/pages.js` +Page CRUD, templates, board theme. + +| Function | Lines | +|----------|-------| +| `getPages` | 701–723 | +| `addPage` | 449–472 | +| `changePage` | 473–488 | +| `updatePageTemplate` | 489–503 | +| `updateBoardTheme` | 504–518 | +| `renamePage` | 724–740 | +| `duplicatePage` | 741–769 | +| `deletePage` | 770–799 | + +Imports: `db`, `_shared` + +--- + +### `classroom/chat.js` +Chat messages, reactions, file attachments, export, CHAT_UPLOADS_DIR setup. + +| Symbol | Lines | +|--------|-------| +| `CHAT_UPLOADS_DIR` | 9–10 | +| `ALLOWED_REACTIONS` | 1027 | +| `sendChat` | 232–268 | +| `getChat` | 269–320 | +| `pinMessage` | 841–864 | +| `reactToMessage` | 1028–1074 | +| `uploadChatAttachment` | 1019–1026 | +| `exportChat` | 1244–1275 | + +Imports: `db`, `path`, `fs`, `crypto`, `emitToUser` (from `ws-server`), `_shared` + +--- + +### `classroom/permissions.js` +Draw permits, hand-raise, mute, screen share, online students. + +| Function | Lines | +|----------|-------| +| `getParticipants` | 321–340 | +| `getAttendance` | 341–358 | +| `getOnlineStudents` | 434–448 | +| `raiseHand` | 519–537 | +| `lowerHand` | 538–550 | +| `getHands` | 551–567 | +| `allowDraw` | 865–882 | +| `revokeDraw` | 883–900 | +| `mutePeer` | 800–814 | +| `screenStart` | 919–930 | +| `screenStop` | 931–941 | + +Imports: `db`, `emitToUser`, `invalidateDrawCache` (from `ws-server`), `getOnlineUserIds` (from `sse`), `_shared` + +--- + +### `classroom/sim.js` +Simulation relay — teacher broadcasts sim events to students. + +| Function | Lines | +|----------|-------| +| `simOpen` | 945–958 | +| `simState` | 961–976 | +| `simMode` | 979–991 | +| `simAnnotate` | 994–1004 | +| `simClose` | 1007–1018 | + +Imports: `db`, `_shared` + +--- + +### `classroom/admin.js` +History, notes, board templates, admin dashboards. + +| Function | Lines | +|----------|-------| +| `getNotes` | 1075–1082 | +| `saveNotes` | 1083–1097 | +| `getClassHistory` | 1098–1140 | +| `getMyHistory` | 1141–1188 | +| `getSessionSummary` | 1189–1243 | +| `getAllNotes` | 1276–1294 | +| `deleteHistorySession` | 1295–1320 | +| `adminGetActiveSessions` | 1321–1341 | +| `adminGetAllSessions` | 1342–1422 | +| `adminGetTeachersList` | 1423–1434 | +| `getTemplates` | 1435–1441 | +| `saveTemplate` | 1442–1473 | +| `deleteTemplate` | 1474–1479 | +| `loadTemplate` | 1480–1519 | + +Imports: `db`, `_shared` + +--- + +## Facade (`classroomController.js` after split) + +```js +module.exports = { + ...require('./classroom/sessions'), + ...require('./classroom/strokes'), + ...require('./classroom/pages'), + ...require('./classroom/chat'), + ...require('./classroom/permissions'), + ...require('./classroom/sim'), + ...require('./classroom/admin'), +}; +``` + +`routes/classroom.js` imports from `'../controllers/classroomController'` — unchanged. + +--- + +## What does NOT change +- All function names — unchanged +- All route bindings in `routes/classroom.js` — unchanged +- All public exports from `classroomController.js` — same set +- DB queries — moved verbatim, not rewritten +- Error responses — unchanged + +## Risks +- `simClose` (line 1007) references `emitToSession` — must be imported from `_shared` +- `sendChat` builds URLs with `req.protocol + '://' + req.get('host')` — needs no extra imports +- `getSessionSummary` (line 1189) is 54 lines — complex, move carefully