UNPKG

@iota-big3/sdk-education-teacher-api

Version:

Teacher Tools API for Education Platform - Classroom management, grading, and insights

240 lines 10.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TeacherAPI = void 0; const express_1 = __importDefault(require("express")); const http_1 = require("http"); const multer_1 = __importDefault(require("multer")); const sdk_auth_1 = require("@iota-big3/sdk-auth"); const sdk_middleware_1 = require("@iota-big3/sdk-middleware"); const sdk_observability_1 = require("@iota-big3/sdk-observability"); const sdk_realtime_1 = require("@iota-big3/sdk-realtime"); const class_access_1 = require("./middleware/class-access"); const validate_teacher_1 = require("./middleware/validate-teacher"); const analytics_service_1 = require("./services/analytics-service"); const assignment_service_1 = require("./services/assignment-service"); const attendance_service_1 = require("./services/attendance-service"); const classroom_service_1 = require("./services/classroom-service"); const communication_service_1 = require("./services/communication-service"); const grading_service_1 = require("./services/grading-service"); const insights_service_1 = require("./services/insights-service"); const analytics_1 = require("./routes/analytics"); const assignments_1 = require("./routes/assignments"); const attendance_1 = require("./routes/attendance"); const classroom_1 = require("./routes/classroom"); const communication_1 = require("./routes/communication"); const dashboard_1 = require("./routes/dashboard"); const grading_1 = require("./routes/grading"); const insights_1 = require("./routes/insights"); const logger = new sdk_observability_1.CentralizedLogger({ level: 'info', appName: 'teacher-api', enableConsole: true, enableFile: false }); const upload = (0, multer_1.default)({ dest: 'uploads/', limits: { fileSize: 10 * 1024 * 1024, }, }); class TeacherAPI { constructor(config) { this.upload = upload; this.app = (0, express_1.default)(); this.server = (0, http_1.createServer)(this.app); const sdkIntegrations = { auth: new sdk_auth_1.SDKAuth({ jwtSecret: process.env.JWT_SECRET || 'teacher-api-secret-key', jwtExpiry: 28800, refreshTokenExpiry: 604800, }), logger: logger, }; this.middlewareManager = (0, sdk_middleware_1.createMiddlewareManager)(sdkIntegrations); this.services = { classroom: new classroom_service_1.ClassroomService(), grading: new grading_service_1.GradingService(), assignment: new assignment_service_1.AssignmentService(), attendance: new attendance_service_1.AttendanceService(), insights: new insights_service_1.InsightsService(), communication: new communication_service_1.CommunicationService(), analytics: new analytics_service_1.AnalyticsService(), }; this.setupMiddleware(config); this.setupRoutes(); this.setupWebSocket(config?.corsOrigins); this.services.grading.setSocketIO(this.io); this.services.communication.setSocketIO(this.io); } setupMiddleware(config) { this.middlewareManager.register('cors', this.middlewareManager.createCorsMiddleware({ origin: config?.corsOrigins || ['http://localhost:3000'], credentials: true, })); this.middlewareManager.register('rateLimit', this.middlewareManager.createRateLimitMiddleware({ windowMs: config?.rateLimits?.windowMs || 15 * 60 * 1000, max: config?.rateLimits?.max || 100, })); this.middlewareManager.register('auth', this.middlewareManager.createAuthMiddleware({ requireAuth: true, tokenLocation: 'header' })); this.app.use(this.middlewareManager.apply()); this.app.use(express_1.default.json({ limit: '10mb' })); this.app.use(express_1.default.urlencoded({ extended: true, limit: '10mb' })); this.app.use('/api', validate_teacher_1.validateTeacher); this.app.use('/api', class_access_1.classAccessMiddleware); } setupRoutes() { this.app.get('/health', (req, res) => { res.json({ success: true, data: { status: 'healthy', timestamp: new Date().toISOString(), service: 'teacher-api', }, }); }); this.app.use('/api/dashboard', (0, dashboard_1.dashboardRoutes)(this.services)); this.app.use('/api/classroom', class_access_1.classAccessMiddleware, (0, classroom_1.classroomRoutes)(this.services, this.upload)); this.app.use('/api/grading', class_access_1.classAccessMiddleware, (0, grading_1.gradingRoutes)(this.services, this.upload)); this.app.use('/api/assignments', class_access_1.classAccessMiddleware, (0, assignments_1.assignmentRoutes)(this.services, this.upload)); this.app.use('/api/attendance', class_access_1.classAccessMiddleware, (0, attendance_1.attendanceRoutes)(this.services)); this.app.use('/api/insights', class_access_1.classAccessMiddleware, (0, insights_1.insightsRoutes)(this.services)); this.app.use('/api/communication', (0, communication_1.communicationRoutes)(this.services)); this.app.use('/api/analytics', class_access_1.classAccessMiddleware, (0, analytics_1.analyticsRoutes)(this.services)); this.app.use('*', (req, res) => { res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: 'Endpoint not found', }, }); }); } setupWebSocket(corsOrigins) { const realtimeService = new sdk_realtime_1.RealtimeService({ cors: { origin: corsOrigins || ['http://localhost:3000'], methods: ['GET', 'POST'], credentials: true, }, }); this.io = realtimeService.attach(this.server); this.io.use(async (socket, next) => { try { const token = socket.handshake.auth.token; if (!token) { return next(new Error('Authentication error')); } const authService = new sdk_auth_1.SDKAuth({ jwtSecret: process.env.JWT_SECRET || 'teacher-api-secret-key', jwtExpiry: 28800, refreshTokenExpiry: 604800, sessionConfig: { maxAge: 28800, renewable: true, secureCookie: false, sameSite: 'strict' }, passwordPolicy: { minLength: 8, requireUppercase: true, requireLowercase: true, requireNumbers: true, requireSpecialChars: false }, enableMFA: false, enableAudit: false }); const result = await authService.validateToken(token); if (!result.success) { return next(new Error('Invalid token')); } socket.data.teacher = result.data; next(); } catch (error) { next(new Error('Authentication error')); } }); this.io.on('connection', (socket) => { logger.info(`Teacher connected: ${socket.data.teacher.id}`); socket.join(`teacher:${socket.data.teacher.id}`); if (socket.data.teacher.classIds) { socket.data.teacher.classIds.forEach((classId) => { socket.join(`class:${classId}`); }); } socket.on('grade:update', (data) => { this.emitGradeUpdate(data.classId, data.studentId, data.gradeData); }); socket.on('attendance:update', (data) => { this.emitAttendanceUpdate(data.classId, data.attendanceData); }); socket.on('announcement:create', (data) => { this.emitAnnouncement(data.classIds, data.announcement); }); socket.on('disconnect', () => { logger.info(`Teacher disconnected: ${socket.data.teacher.id}`); }); }); } start(port = 3003) { this.server.listen(port, () => { logger.info(`Teacher API running on port ${port}`); }); } stop() { this.server.close(); } emitClassUpdate(classId, eventType, data) { this.io.to(`class:${classId}`).emit('class:update', { type: eventType, classId, data, timestamp: new Date(), }); } emitGradeUpdate(classId, studentId, gradeData) { this.io.to(`class:${classId}`).emit('grade:updated', { studentId, gradeData, classId, timestamp: new Date(), }); this.io.to(`student:${studentId}:parents`).emit('grade:updated', { studentId, gradeData, timestamp: new Date(), }); } emitAttendanceUpdate(classId, attendanceData) { this.io.to(`class:${classId}`).emit('attendance:updated', { classId, attendanceData, timestamp: new Date(), }); } emitAnnouncement(classIds, announcement) { classIds.forEach(classId => { this.io.to(`class:${classId}`).emit('announcement:new', announcement); }); } emit(event, data) { logger.debug(`Emitting ${event}:`, data); this.io.emit(event, data); } } exports.TeacherAPI = TeacherAPI; exports.default = TeacherAPI; __exportStar(require("./types"), exports); //# sourceMappingURL=index.js.map