@studious-lms/server 1.0.4 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/API_SPECIFICATION.md +1117 -0
  2. package/dist/exportType.js +1 -2
  3. package/dist/index.js +25 -30
  4. package/dist/lib/fileUpload.d.ts.map +1 -1
  5. package/dist/lib/fileUpload.js +31 -29
  6. package/dist/lib/googleCloudStorage.js +9 -14
  7. package/dist/lib/prisma.js +4 -7
  8. package/dist/lib/thumbnailGenerator.js +12 -20
  9. package/dist/middleware/auth.d.ts.map +1 -1
  10. package/dist/middleware/auth.js +17 -22
  11. package/dist/middleware/logging.js +5 -9
  12. package/dist/routers/_app.d.ts +3483 -1801
  13. package/dist/routers/_app.d.ts.map +1 -1
  14. package/dist/routers/_app.js +28 -27
  15. package/dist/routers/agenda.d.ts +13 -8
  16. package/dist/routers/agenda.d.ts.map +1 -1
  17. package/dist/routers/agenda.js +14 -17
  18. package/dist/routers/announcement.d.ts +4 -3
  19. package/dist/routers/announcement.d.ts.map +1 -1
  20. package/dist/routers/announcement.js +28 -31
  21. package/dist/routers/assignment.d.ts +282 -196
  22. package/dist/routers/assignment.d.ts.map +1 -1
  23. package/dist/routers/assignment.js +256 -202
  24. package/dist/routers/attendance.d.ts +5 -4
  25. package/dist/routers/attendance.d.ts.map +1 -1
  26. package/dist/routers/attendance.js +31 -34
  27. package/dist/routers/auth.d.ts +1 -0
  28. package/dist/routers/auth.d.ts.map +1 -1
  29. package/dist/routers/auth.js +80 -75
  30. package/dist/routers/class.d.ts +284 -14
  31. package/dist/routers/class.d.ts.map +1 -1
  32. package/dist/routers/class.js +435 -164
  33. package/dist/routers/event.d.ts +47 -38
  34. package/dist/routers/event.d.ts.map +1 -1
  35. package/dist/routers/event.js +76 -79
  36. package/dist/routers/file.d.ts +71 -1
  37. package/dist/routers/file.d.ts.map +1 -1
  38. package/dist/routers/file.js +267 -32
  39. package/dist/routers/folder.d.ts +296 -0
  40. package/dist/routers/folder.d.ts.map +1 -0
  41. package/dist/routers/folder.js +693 -0
  42. package/dist/routers/notifications.d.ts +103 -0
  43. package/dist/routers/notifications.d.ts.map +1 -0
  44. package/dist/routers/notifications.js +91 -0
  45. package/dist/routers/school.d.ts +208 -0
  46. package/dist/routers/school.d.ts.map +1 -0
  47. package/dist/routers/school.js +481 -0
  48. package/dist/routers/section.d.ts +1 -0
  49. package/dist/routers/section.d.ts.map +1 -1
  50. package/dist/routers/section.js +30 -33
  51. package/dist/routers/user.d.ts +2 -1
  52. package/dist/routers/user.d.ts.map +1 -1
  53. package/dist/routers/user.js +21 -24
  54. package/dist/seedDatabase.d.ts +22 -0
  55. package/dist/seedDatabase.d.ts.map +1 -0
  56. package/dist/seedDatabase.js +57 -0
  57. package/dist/socket/handlers.js +26 -30
  58. package/dist/trpc.d.ts +5 -0
  59. package/dist/trpc.d.ts.map +1 -1
  60. package/dist/trpc.js +35 -26
  61. package/dist/types/trpc.js +1 -2
  62. package/dist/utils/email.js +2 -8
  63. package/dist/utils/generateInviteCode.js +1 -5
  64. package/dist/utils/logger.d.ts.map +1 -1
  65. package/dist/utils/logger.js +13 -9
  66. package/dist/utils/prismaErrorHandler.d.ts +9 -0
  67. package/dist/utils/prismaErrorHandler.d.ts.map +1 -0
  68. package/dist/utils/prismaErrorHandler.js +234 -0
  69. package/dist/utils/prismaWrapper.d.ts +14 -0
  70. package/dist/utils/prismaWrapper.d.ts.map +1 -0
  71. package/dist/utils/prismaWrapper.js +64 -0
  72. package/package.json +17 -4
  73. package/prisma/migrations/20250807062924_init/migration.sql +436 -0
  74. package/prisma/migrations/migration_lock.toml +3 -0
  75. package/prisma/schema.prisma +67 -0
  76. package/src/index.ts +2 -2
  77. package/src/lib/fileUpload.ts +16 -7
  78. package/src/middleware/auth.ts +0 -2
  79. package/src/routers/_app.ts +5 -1
  80. package/src/routers/assignment.ts +82 -22
  81. package/src/routers/auth.ts +80 -54
  82. package/src/routers/class.ts +330 -36
  83. package/src/routers/file.ts +283 -20
  84. package/src/routers/folder.ts +755 -0
  85. package/src/routers/notifications.ts +93 -0
  86. package/src/seedDatabase.ts +66 -0
  87. package/src/socket/handlers.ts +4 -4
  88. package/src/trpc.ts +13 -0
  89. package/src/utils/logger.ts +14 -4
  90. package/src/utils/prismaErrorHandler.ts +275 -0
  91. package/src/utils/prismaWrapper.ts +91 -0
  92. package/tests/auth.test.ts +25 -0
  93. package/tests/class.test.ts +281 -0
  94. package/tests/setup.ts +98 -0
  95. package/tests/startup.test.ts +5 -0
  96. package/tsconfig.json +2 -1
  97. package/vitest.config.ts +11 -0
  98. package/dist/logger.d.ts +0 -26
  99. package/dist/logger.d.ts.map +0 -1
  100. package/dist/logger.js +0 -135
  101. package/src/logger.ts +0 -163
@@ -0,0 +1,1117 @@
1
+ # Easy LMS API Specification
2
+
3
+ ## Overview
4
+
5
+ Easy LMS is a comprehensive Learning Management System built with tRPC, Prisma, and PostgreSQL. This document provides a complete API specification for frontend developers.
6
+
7
+ ### Base URL
8
+ - **Development**: `http://localhost:3001/trpc`
9
+ - **Production**: `https://your-domain.com/trpc`
10
+
11
+ ### Authentication
12
+ - **Method**: Bearer Token Authentication
13
+ - **Header**: `Authorization: Bearer <token>`
14
+ - **Session Management**: Token-based sessions with expiration
15
+
16
+ ---
17
+
18
+ ## 🔐 Authentication Endpoints
19
+
20
+ ### `auth.register`
21
+ **Type**: Mutation
22
+ **Access**: Public
23
+ **Description**: Register a new user account
24
+
25
+ **Input**:
26
+ ```typescript
27
+ {
28
+ username: string; // min 3 characters
29
+ email: string; // valid email format
30
+ password: string; // min 6 characters
31
+ confirmPassword: string;
32
+ }
33
+ ```
34
+
35
+ **Output**:
36
+ ```typescript
37
+ {
38
+ user: {
39
+ id: string;
40
+ username: string;
41
+ };
42
+ }
43
+ ```
44
+
45
+ ### `auth.login`
46
+ **Type**: Mutation
47
+ **Access**: Public
48
+ **Description**: Login with username and password
49
+
50
+ **Input**:
51
+ ```typescript
52
+ {
53
+ username: string;
54
+ password: string;
55
+ }
56
+ ```
57
+
58
+ **Output**:
59
+ ```typescript
60
+ {
61
+ token: string;
62
+ user: {
63
+ id: string;
64
+ username: string;
65
+ };
66
+ verified?: boolean;
67
+ }
68
+ ```
69
+
70
+ ### `auth.logout`
71
+ **Type**: Mutation
72
+ **Access**: Public
73
+ **Description**: Logout and invalidate session
74
+
75
+ **Output**:
76
+ ```typescript
77
+ {
78
+ success: boolean;
79
+ }
80
+ ```
81
+
82
+ ### `auth.check`
83
+ **Type**: Query
84
+ **Access**: Protected
85
+ **Description**: Verify current authentication status
86
+
87
+ **Output**:
88
+ ```typescript
89
+ {
90
+ user: {
91
+ id: string;
92
+ username: string;
93
+ };
94
+ }
95
+ ```
96
+
97
+ ### `auth.verify`
98
+ **Type**: Mutation
99
+ **Access**: Public
100
+ **Description**: Verify email with token
101
+
102
+ **Input**:
103
+ ```typescript
104
+ {
105
+ token: string;
106
+ }
107
+ ```
108
+
109
+ ### `auth.resendVerificationEmail`
110
+ **Type**: Mutation
111
+ **Access**: Public
112
+ **Description**: Resend verification email
113
+
114
+ **Input**:
115
+ ```typescript
116
+ {
117
+ email: string;
118
+ }
119
+ ```
120
+
121
+ ---
122
+
123
+ ## 👤 User Management
124
+
125
+ ### `user.getProfile`
126
+ **Type**: Query
127
+ **Access**: Protected
128
+ **Description**: Get current user profile
129
+
130
+ **Output**:
131
+ ```typescript
132
+ {
133
+ id: string;
134
+ username: string;
135
+ profile: Record<string, any>;
136
+ }
137
+ ```
138
+
139
+ ### `user.updateProfile`
140
+ **Type**: Mutation
141
+ **Access**: Protected
142
+ **Description**: Update user profile
143
+
144
+ **Input**:
145
+ ```typescript
146
+ {
147
+ profile: Record<string, any>;
148
+ profilePicture?: {
149
+ name: string;
150
+ type: string;
151
+ size: number;
152
+ data: string; // base64
153
+ };
154
+ }
155
+ ```
156
+
157
+ ---
158
+
159
+ ## 🏫 Class Management
160
+
161
+ ### `class.getAll`
162
+ **Type**: Query
163
+ **Access**: Protected
164
+ **Description**: Get all classes for current user
165
+
166
+ **Output**:
167
+ ```typescript
168
+ {
169
+ teacherInClass: Array<{
170
+ id: string;
171
+ name: string;
172
+ section: string;
173
+ subject: string;
174
+ color?: string;
175
+ dueToday: Assignment[];
176
+ assignments: Assignment[];
177
+ }>;
178
+ studentInClass: Array<{
179
+ id: string;
180
+ name: string;
181
+ section: string;
182
+ subject: string;
183
+ color?: string;
184
+ dueToday: Assignment[];
185
+ assignments: Assignment[];
186
+ }>;
187
+ }
188
+ ```
189
+
190
+ ### `class.get`
191
+ **Type**: Query
192
+ **Access**: Protected
193
+ **Description**: Get specific class details
194
+
195
+ **Input**:
196
+ ```typescript
197
+ {
198
+ classId: string;
199
+ }
200
+ ```
201
+
202
+ **Output**:
203
+ ```typescript
204
+ {
205
+ class: {
206
+ id: string;
207
+ name: string;
208
+ subject: string;
209
+ section: string;
210
+ color?: string;
211
+ teachers: Array<{
212
+ id: string;
213
+ username: string;
214
+ }>;
215
+ students: Array<{
216
+ id: string;
217
+ username: string;
218
+ }>;
219
+ announcements: Array<{
220
+ id: string;
221
+ remarks: string;
222
+ createdAt: Date;
223
+ teacher: {
224
+ id: string;
225
+ username: string;
226
+ };
227
+ }>;
228
+ assignments: Assignment[];
229
+ sections: Section[];
230
+ };
231
+ }
232
+ ```
233
+
234
+ ### `class.create`
235
+ **Type**: Mutation
236
+ **Access**: Protected
237
+ **Description**: Create a new class
238
+
239
+ **Input**:
240
+ ```typescript
241
+ {
242
+ name: string;
243
+ section: string;
244
+ subject: string;
245
+ color?: string;
246
+ students?: string[];
247
+ teachers?: string[];
248
+ }
249
+ ```
250
+
251
+ ### `class.update`
252
+ **Type**: Mutation
253
+ **Access**: Teacher Only
254
+ **Description**: Update class details
255
+
256
+ **Input**:
257
+ ```typescript
258
+ {
259
+ classId: string;
260
+ name?: string;
261
+ section?: string;
262
+ subject?: string;
263
+ }
264
+ ```
265
+
266
+ ### `class.delete`
267
+ **Type**: Mutation
268
+ **Access**: Teacher Only
269
+ **Description**: Delete a class
270
+
271
+ **Input**:
272
+ ```typescript
273
+ {
274
+ classId: string;
275
+ id: string;
276
+ }
277
+ ```
278
+
279
+ ### `class.join`
280
+ **Type**: Mutation
281
+ **Access**: Protected
282
+ **Description**: Join class with invite code
283
+
284
+ **Input**:
285
+ ```typescript
286
+ {
287
+ classCode: string;
288
+ }
289
+ ```
290
+
291
+ ### `class.getInviteCode`
292
+ **Type**: Query
293
+ **Access**: Teacher Only
294
+ **Description**: Get class invite code
295
+
296
+ **Input**:
297
+ ```typescript
298
+ {
299
+ classId: string;
300
+ }
301
+ ```
302
+
303
+ **Output**:
304
+ ```typescript
305
+ {
306
+ code: string;
307
+ }
308
+ ```
309
+
310
+ ### `class.addStudent`
311
+ **Type**: Mutation
312
+ **Access**: Teacher Only
313
+ **Description**: Add student to class
314
+
315
+ **Input**:
316
+ ```typescript
317
+ {
318
+ classId: string;
319
+ studentId: string;
320
+ }
321
+ ```
322
+
323
+ ### `class.changeRole`
324
+ **Type**: Mutation
325
+ **Access**: Teacher Only
326
+ **Description**: Change user role in class
327
+
328
+ **Input**:
329
+ ```typescript
330
+ {
331
+ classId: string;
332
+ userId: string;
333
+ type: 'teacher' | 'student';
334
+ }
335
+ ```
336
+
337
+ ### `class.removeMember`
338
+ **Type**: Mutation
339
+ **Access**: Teacher Only
340
+ **Description**: Remove member from class
341
+
342
+ **Input**:
343
+ ```typescript
344
+ {
345
+ classId: string;
346
+ userId: string;
347
+ }
348
+ ```
349
+
350
+ ---
351
+
352
+ ## 📝 Assignment Management
353
+
354
+ ### `assignment.create`
355
+ **Type**: Mutation
356
+ **Access**: Protected
357
+ **Description**: Create a new assignment
358
+
359
+ **Input**:
360
+ ```typescript
361
+ {
362
+ classId: string;
363
+ title: string;
364
+ instructions: string;
365
+ dueDate: string;
366
+ files?: File[];
367
+ existingFileIds?: string[];
368
+ maxGrade?: number;
369
+ graded?: boolean;
370
+ weight?: number;
371
+ sectionId?: string;
372
+ type?: 'HOMEWORK' | 'QUIZ' | 'TEST' | 'PROJECT' | 'ESSAY' | 'DISCUSSION' | 'PRESENTATION' | 'LAB' | 'OTHER';
373
+ markSchemeId?: string;
374
+ gradingBoundaryId?: string;
375
+ inProgress?: boolean;
376
+ }
377
+ ```
378
+
379
+ ### `assignment.update`
380
+ **Type**: Mutation
381
+ **Access**: Protected
382
+ **Description**: Update assignment
383
+
384
+ **Input**:
385
+ ```typescript
386
+ {
387
+ classId: string;
388
+ id: string;
389
+ title?: string;
390
+ instructions?: string;
391
+ dueDate?: string;
392
+ files?: File[];
393
+ existingFileIds?: string[];
394
+ removedAttachments?: string[];
395
+ maxGrade?: number;
396
+ graded?: boolean;
397
+ weight?: number;
398
+ sectionId?: string | null;
399
+ type?: AssignmentType;
400
+ inProgress?: boolean;
401
+ }
402
+ ```
403
+
404
+ ### `assignment.delete`
405
+ **Type**: Mutation
406
+ **Access**: Protected
407
+ **Description**: Delete assignment
408
+
409
+ **Input**:
410
+ ```typescript
411
+ {
412
+ id: string;
413
+ classId: string;
414
+ }
415
+ ```
416
+
417
+ ### `assignment.get`
418
+ **Type**: Query
419
+ **Access**: Protected
420
+ **Description**: Get assignment details
421
+
422
+ **Input**:
423
+ ```typescript
424
+ {
425
+ id: string;
426
+ classId: string;
427
+ }
428
+ ```
429
+
430
+ ### `assignment.getSubmission`
431
+ **Type**: Query
432
+ **Access**: Class Member
433
+ **Description**: Get student's submission for assignment
434
+
435
+ **Input**:
436
+ ```typescript
437
+ {
438
+ assignmentId: string;
439
+ classId: string;
440
+ }
441
+ ```
442
+
443
+ ### `assignment.getSubmissions`
444
+ **Type**: Query
445
+ **Access**: Teacher Only
446
+ **Description**: Get all submissions for assignment
447
+
448
+ **Input**:
449
+ ```typescript
450
+ {
451
+ assignmentId: string;
452
+ classId: string;
453
+ }
454
+ ```
455
+
456
+ ### `assignment.updateSubmission`
457
+ **Type**: Mutation
458
+ **Access**: Class Member
459
+ **Description**: Update student submission
460
+
461
+ **Input**:
462
+ ```typescript
463
+ {
464
+ assignmentId: string;
465
+ classId: string;
466
+ submissionId: string;
467
+ submit?: boolean;
468
+ newAttachments?: File[];
469
+ existingFileIds?: string[];
470
+ removedAttachments?: string[];
471
+ }
472
+ ```
473
+
474
+ ### `assignment.updateSubmissionAsTeacher`
475
+ **Type**: Mutation
476
+ **Access**: Teacher Only
477
+ **Description**: Update submission as teacher (grading)
478
+
479
+ **Input**:
480
+ ```typescript
481
+ {
482
+ assignmentId: string;
483
+ classId: string;
484
+ submissionId: string;
485
+ return?: boolean;
486
+ gradeReceived?: number | null;
487
+ newAttachments?: File[];
488
+ existingFileIds?: string[];
489
+ removedAttachments?: string[];
490
+ rubricGrades?: Array<{
491
+ criteriaId: string;
492
+ selectedLevelId: string;
493
+ points: number;
494
+ comments: string;
495
+ }>;
496
+ }
497
+ ```
498
+
499
+ ---
500
+
501
+ ## 📢 Announcements
502
+
503
+ ### `announcement.getAll`
504
+ **Type**: Query
505
+ **Access**: Class Member
506
+ **Description**: Get all class announcements
507
+
508
+ **Input**:
509
+ ```typescript
510
+ {
511
+ classId: string;
512
+ }
513
+ ```
514
+
515
+ **Output**:
516
+ ```typescript
517
+ {
518
+ announcements: Array<{
519
+ id: string;
520
+ remarks: string;
521
+ createdAt: Date;
522
+ teacher: {
523
+ id: string;
524
+ username: string;
525
+ };
526
+ }>;
527
+ }
528
+ ```
529
+
530
+ ### `announcement.create`
531
+ **Type**: Mutation
532
+ **Access**: Teacher Only
533
+ **Description**: Create new announcement
534
+
535
+ **Input**:
536
+ ```typescript
537
+ {
538
+ classId: string;
539
+ remarks: string;
540
+ }
541
+ ```
542
+
543
+ ### `announcement.update`
544
+ **Type**: Mutation
545
+ **Access**: Protected
546
+ **Description**: Update announcement
547
+
548
+ **Input**:
549
+ ```typescript
550
+ {
551
+ id: string;
552
+ data: {
553
+ content: string;
554
+ };
555
+ }
556
+ ```
557
+
558
+ ### `announcement.delete`
559
+ **Type**: Mutation
560
+ **Access**: Protected
561
+ **Description**: Delete announcement
562
+
563
+ **Input**:
564
+ ```typescript
565
+ {
566
+ id: string;
567
+ }
568
+ ```
569
+
570
+ ---
571
+
572
+ ## 📁 File Management
573
+
574
+ ### `file.getSignedUrl`
575
+ **Type**: Mutation
576
+ **Access**: Protected
577
+ **Description**: Get signed URL for file download
578
+
579
+ **Input**:
580
+ ```typescript
581
+ {
582
+ fileId: string;
583
+ }
584
+ ```
585
+
586
+ **Output**:
587
+ ```typescript
588
+ {
589
+ url: string;
590
+ }
591
+ ```
592
+
593
+ ### `file.move`
594
+ **Type**: Mutation
595
+ **Access**: Teacher Only
596
+ **Description**: Move file to different folder
597
+
598
+ **Input**:
599
+ ```typescript
600
+ {
601
+ fileId: string;
602
+ targetFolderId: string;
603
+ classId: string;
604
+ }
605
+ ```
606
+
607
+ ### `file.rename`
608
+ **Type**: Mutation
609
+ **Access**: Teacher Only
610
+ **Description**: Rename file
611
+
612
+ **Input**:
613
+ ```typescript
614
+ {
615
+ fileId: string;
616
+ newName: string;
617
+ classId: string;
618
+ }
619
+ ```
620
+
621
+ ### `file.delete`
622
+ **Type**: Mutation
623
+ **Access**: Teacher Only
624
+ **Description**: Delete file
625
+
626
+ **Input**:
627
+ ```typescript
628
+ {
629
+ fileId: string;
630
+ classId: string;
631
+ }
632
+ ```
633
+
634
+ ---
635
+
636
+ ## 🔔 Notifications
637
+
638
+ ### `notification.list`
639
+ **Type**: Query
640
+ **Access**: Protected
641
+ **Description**: Get all notifications for user
642
+
643
+ **Output**:
644
+ ```typescript
645
+ Array<{
646
+ id: string;
647
+ title: string;
648
+ content: string;
649
+ createdAt: Date;
650
+ read: boolean;
651
+ sender?: {
652
+ username: string;
653
+ };
654
+ receiver: {
655
+ username: string;
656
+ };
657
+ }>
658
+ ```
659
+
660
+ ### `notification.get`
661
+ **Type**: Query
662
+ **Access**: Protected
663
+ **Description**: Get specific notification
664
+
665
+ **Input**:
666
+ ```typescript
667
+ {
668
+ id: string;
669
+ }
670
+ ```
671
+
672
+ ### `notification.sendTo`
673
+ **Type**: Mutation
674
+ **Access**: Protected
675
+ **Description**: Send notification to user
676
+
677
+ **Input**:
678
+ ```typescript
679
+ {
680
+ receiverId: string;
681
+ title: string;
682
+ content: string;
683
+ }
684
+ ```
685
+
686
+ ### `notification.sendToMultiple`
687
+ **Type**: Mutation
688
+ **Access**: Protected
689
+ **Description**: Send notification to multiple users
690
+
691
+ **Input**:
692
+ ```typescript
693
+ {
694
+ receiverIds: string[];
695
+ title: string;
696
+ content: string;
697
+ }
698
+ ```
699
+
700
+ ### `notification.markAsRead`
701
+ **Type**: Mutation
702
+ **Access**: Protected
703
+ **Description**: Mark notification as read
704
+
705
+ **Input**:
706
+ ```typescript
707
+ {
708
+ id: string;
709
+ }
710
+ ```
711
+
712
+ ---
713
+
714
+ ## 🏫 School Management
715
+
716
+ *Note: Router exists but implementation details need to be examined*
717
+
718
+ ---
719
+
720
+ ## 📊 Grading & Assessment
721
+
722
+ ### `class.getGrades`
723
+ **Type**: Query
724
+ **Access**: Class Member
725
+ **Description**: Get grades for a user
726
+
727
+ **Input**:
728
+ ```typescript
729
+ {
730
+ classId: string;
731
+ userId: string;
732
+ }
733
+ ```
734
+
735
+ ### `class.updateGrade`
736
+ **Type**: Mutation
737
+ **Access**: Teacher Only
738
+ **Description**: Update student grade
739
+
740
+ **Input**:
741
+ ```typescript
742
+ {
743
+ classId: string;
744
+ assignmentId: string;
745
+ submissionId: string;
746
+ gradeReceived: number | null;
747
+ }
748
+ ```
749
+
750
+ ### Mark Schemes
751
+
752
+ ### `class.listMarkSchemes`
753
+ **Type**: Query
754
+ **Access**: Teacher Only
755
+
756
+ ### `class.createMarkScheme`
757
+ **Type**: Mutation
758
+ **Access**: Teacher Only
759
+
760
+ ### `class.updateMarkScheme`
761
+ **Type**: Mutation
762
+ **Access**: Teacher Only
763
+
764
+ ### `class.deleteMarkScheme`
765
+ **Type**: Mutation
766
+ **Access**: Teacher Only
767
+
768
+ ### Grading Boundaries
769
+
770
+ ### `class.listGradingBoundaries`
771
+ **Type**: Query
772
+ **Access**: Teacher Only
773
+
774
+ ### `class.createGradingBoundary`
775
+ **Type**: Mutation
776
+ **Access**: Teacher Only
777
+
778
+ ### `class.updateGradingBoundary`
779
+ **Type**: Mutation
780
+ **Access**: Teacher Only
781
+
782
+ ### `class.deleteGradingBoundary`
783
+ **Type**: Mutation
784
+ **Access**: Teacher Only
785
+
786
+ ---
787
+
788
+ ## 📅 Calendar & Events
789
+
790
+ ### `class.getEvents`
791
+ **Type**: Query
792
+ **Access**: Teacher Only
793
+ **Description**: Get class events
794
+
795
+ **Input**:
796
+ ```typescript
797
+ {
798
+ classId: string;
799
+ }
800
+ ```
801
+
802
+ ### `assignment.attachToEvent`
803
+ **Type**: Mutation
804
+ **Access**: Teacher Only
805
+ **Description**: Attach assignment to event
806
+
807
+ **Input**:
808
+ ```typescript
809
+ {
810
+ assignmentId: string;
811
+ eventId: string;
812
+ }
813
+ ```
814
+
815
+ ### `assignment.detachEvent`
816
+ **Type**: Mutation
817
+ **Access**: Teacher Only
818
+ **Description**: Detach assignment from event
819
+
820
+ **Input**:
821
+ ```typescript
822
+ {
823
+ assignmentId: string;
824
+ }
825
+ ```
826
+
827
+ ### `assignment.getAvailableEvents`
828
+ **Type**: Query
829
+ **Access**: Teacher Only
830
+ **Description**: Get available events for assignment
831
+
832
+ **Input**:
833
+ ```typescript
834
+ {
835
+ assignmentId: string;
836
+ }
837
+ ```
838
+
839
+ ---
840
+
841
+ ## 🔧 Lab Management (Draft System)
842
+
843
+ ### `class.listLabDrafts`
844
+ **Type**: Query
845
+ **Access**: Teacher Only
846
+ **Description**: Get lab drafts
847
+
848
+ **Input**:
849
+ ```typescript
850
+ {
851
+ classId: string;
852
+ }
853
+ ```
854
+
855
+ ### `class.createLabDraft`
856
+ **Type**: Mutation
857
+ **Access**: Teacher Only
858
+ **Description**: Create lab draft
859
+
860
+ ### `class.updateLabDraft`
861
+ **Type**: Mutation
862
+ **Access**: Teacher Only
863
+ **Description**: Update lab draft
864
+
865
+ ### `class.deleteLabDraft`
866
+ **Type**: Mutation
867
+ **Access**: Teacher Only
868
+ **Description**: Delete lab draft
869
+
870
+ ### `class.publishLabDraft`
871
+ **Type**: Mutation
872
+ **Access**: Teacher Only
873
+ **Description**: Publish lab draft as assignment
874
+
875
+ ---
876
+
877
+ ## 📄 Syllabus Management
878
+
879
+ ### `class.getSyllabus`
880
+ **Type**: Query
881
+ **Access**: Class Member
882
+ **Description**: Get class syllabus
883
+
884
+ **Input**:
885
+ ```typescript
886
+ {
887
+ classId: string;
888
+ }
889
+ ```
890
+
891
+ **Output**:
892
+ ```typescript
893
+ {
894
+ syllabus: string;
895
+ gradingBoundaries: GradingBoundary[];
896
+ markSchemes: MarkScheme[];
897
+ }
898
+ ```
899
+
900
+ ### `class.updateSyllabus`
901
+ **Type**: Mutation
902
+ **Access**: Teacher Only
903
+ **Description**: Update class syllabus
904
+
905
+ **Input**:
906
+ ```typescript
907
+ {
908
+ classId: string;
909
+ contents: string;
910
+ }
911
+ ```
912
+
913
+ ---
914
+
915
+ ## 🗂️ File Organization
916
+
917
+ ### `class.getFiles`
918
+ **Type**: Query
919
+ **Access**: Class Member
920
+ **Description**: Get organized files for class
921
+
922
+ **Input**:
923
+ ```typescript
924
+ {
925
+ classId: string;
926
+ }
927
+ ```
928
+
929
+ **Output**:
930
+ ```typescript
931
+ Array<{
932
+ id: string;
933
+ title: string;
934
+ teacher: {
935
+ id: string;
936
+ username: string;
937
+ };
938
+ teacherAttachments: File[];
939
+ students: Array<{
940
+ id: string;
941
+ username: string;
942
+ attachments: File[];
943
+ annotations: File[];
944
+ }>;
945
+ }>
946
+ ```
947
+
948
+ ---
949
+
950
+ ## 🌐 Real-time Features
951
+
952
+ ### Socket.IO Events
953
+ - **Connection**: `/socket.io/`
954
+ - **Events**: Class updates, new assignments, submissions, etc.
955
+
956
+ ---
957
+
958
+ ## 📊 Data Models
959
+
960
+ ### File Object
961
+ ```typescript
962
+ {
963
+ id: string;
964
+ name: string;
965
+ type: string;
966
+ size: number;
967
+ data: string; // base64 encoded
968
+ }
969
+ ```
970
+
971
+ ### Assignment Object
972
+ ```typescript
973
+ {
974
+ id: string;
975
+ title: string;
976
+ instructions: string;
977
+ dueDate: Date;
978
+ maxGrade?: number;
979
+ graded: boolean;
980
+ weight: number;
981
+ type: AssignmentType;
982
+ inProgress: boolean;
983
+ template: boolean;
984
+ attachments: File[];
985
+ submissions: Submission[];
986
+ section?: Section;
987
+ teacher: User;
988
+ class: Class;
989
+ markScheme?: MarkScheme;
990
+ gradingBoundary?: GradingBoundary;
991
+ eventAttached?: Event;
992
+ }
993
+ ```
994
+
995
+ ### User Roles
996
+ - `STUDENT`: Can view classes, submit assignments
997
+ - `TEACHER`: Can create/manage classes, grade assignments
998
+ - `ADMIN`: System administration
999
+ - `NONE`: No specific role
1000
+
1001
+ ### Assignment Types
1002
+ - `HOMEWORK`
1003
+ - `QUIZ`
1004
+ - `TEST`
1005
+ - `PROJECT`
1006
+ - `ESSAY`
1007
+ - `DISCUSSION`
1008
+ - `PRESENTATION`
1009
+ - `LAB`
1010
+ - `OTHER`
1011
+
1012
+ ---
1013
+
1014
+ ## 🔒 Access Control
1015
+
1016
+ ### Public Endpoints
1017
+ - All `auth.*` endpoints
1018
+
1019
+ ### Protected Endpoints
1020
+ - Require valid authentication token
1021
+ - User must be logged in
1022
+
1023
+ ### Class Member Endpoints
1024
+ - Require `classId` parameter
1025
+ - User must be student or teacher in the class
1026
+
1027
+ ### Teacher Only Endpoints
1028
+ - User must be teacher in the specified class
1029
+ - Full management capabilities
1030
+
1031
+ ---
1032
+
1033
+ ## ⚠️ Error Handling
1034
+
1035
+ ### Common Error Codes
1036
+ - `UNAUTHORIZED`: Invalid or missing authentication
1037
+ - `FORBIDDEN`: Insufficient permissions
1038
+ - `NOT_FOUND`: Resource doesn't exist
1039
+ - `BAD_REQUEST`: Invalid input data
1040
+ - `CONFLICT`: Resource already exists
1041
+ - `INTERNAL_SERVER_ERROR`: Server error
1042
+
1043
+ ### Error Response Format
1044
+ ```typescript
1045
+ {
1046
+ error: {
1047
+ code: string;
1048
+ message: string;
1049
+ data?: {
1050
+ zodError?: any;
1051
+ prismaError?: any;
1052
+ };
1053
+ };
1054
+ }
1055
+ ```
1056
+
1057
+ ---
1058
+
1059
+ ## 🚀 Usage Examples
1060
+
1061
+ ### TypeScript Client Setup
1062
+ ```typescript
1063
+ import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
1064
+ import type { AppRouter } from '@studious-lms/server';
1065
+
1066
+ const trpc = createTRPCProxyClient<AppRouter>({
1067
+ links: [
1068
+ httpBatchLink({
1069
+ url: 'http://localhost:3001/trpc',
1070
+ headers() {
1071
+ return {
1072
+ authorization: `Bearer ${getAuthToken()}`,
1073
+ };
1074
+ },
1075
+ }),
1076
+ ],
1077
+ });
1078
+ ```
1079
+
1080
+ ### Example API Calls
1081
+ ```typescript
1082
+ // Login
1083
+ const loginResult = await trpc.auth.login.mutate({
1084
+ username: 'john_doe',
1085
+ password: 'password123'
1086
+ });
1087
+
1088
+ // Get classes
1089
+ const classes = await trpc.class.getAll.query();
1090
+
1091
+ // Create assignment
1092
+ const assignment = await trpc.assignment.create.mutate({
1093
+ classId: 'class-id',
1094
+ title: 'Math Homework',
1095
+ instructions: 'Complete problems 1-10',
1096
+ dueDate: '2024-01-15T23:59:59Z',
1097
+ maxGrade: 100,
1098
+ graded: true
1099
+ });
1100
+ ```
1101
+
1102
+ ---
1103
+
1104
+ ## 📝 Notes for Frontend Developers
1105
+
1106
+ 1. **File Uploads**: Files are sent as base64 encoded strings in the `data` field
1107
+ 2. **Date Handling**: All dates are ISO 8601 strings
1108
+ 3. **Authentication**: Store JWT token and include in all requests
1109
+ 4. **Real-time Updates**: Use Socket.IO for live updates
1110
+ 5. **Error Handling**: Always handle tRPC errors appropriately
1111
+ 6. **Type Safety**: Use the exported TypeScript types for full type safety
1112
+
1113
+ ---
1114
+
1115
+ *Generated on: $(date)*
1116
+ *Version: 1.0.6*
1117
+ *Last Updated: January 2024*