@studious-lms/server 1.2.53 → 1.3.0

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 (477) hide show
  1. package/.coderabbit.yaml +9 -0
  2. package/.env.example +9 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +102 -8
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/config/env.d.ts +21 -0
  7. package/dist/lib/config/env.d.ts.map +1 -1
  8. package/dist/lib/config/env.js +8 -2
  9. package/dist/lib/config/env.js.map +1 -1
  10. package/dist/lib/fileUpload.d.ts.map +1 -1
  11. package/dist/lib/fileUpload.js +2 -2
  12. package/dist/lib/fileUpload.js.map +1 -1
  13. package/dist/lib/googleCloudStorage.d.ts +6 -0
  14. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  15. package/dist/lib/googleCloudStorage.js +19 -2
  16. package/dist/lib/googleCloudStorage.js.map +1 -1
  17. package/dist/lib/pusher.d.ts +4 -1
  18. package/dist/lib/pusher.d.ts.map +1 -1
  19. package/dist/lib/pusher.js +6 -3
  20. package/dist/lib/pusher.js.map +1 -1
  21. package/dist/lib/redis.d.ts +5 -0
  22. package/dist/lib/redis.d.ts.map +1 -0
  23. package/dist/lib/redis.js +53 -0
  24. package/dist/lib/redis.js.map +1 -0
  25. package/dist/lib/thumbnailGenerator.d.ts +0 -21
  26. package/dist/lib/thumbnailGenerator.d.ts.map +1 -1
  27. package/dist/lib/thumbnailGenerator.js +157 -160
  28. package/dist/lib/thumbnailGenerator.js.map +1 -1
  29. package/dist/middleware/auth.d.ts.map +1 -1
  30. package/dist/middleware/auth.js +33 -95
  31. package/dist/middleware/auth.js.map +1 -1
  32. package/dist/models/agenda.d.ts +97 -0
  33. package/dist/models/agenda.d.ts.map +1 -0
  34. package/dist/models/agenda.js +40 -0
  35. package/dist/models/agenda.js.map +1 -0
  36. package/dist/models/announcement.d.ts +223 -0
  37. package/dist/models/announcement.d.ts.map +1 -0
  38. package/dist/models/announcement.js +120 -0
  39. package/dist/models/announcement.js.map +1 -0
  40. package/dist/models/assignment.d.ts +1292 -0
  41. package/dist/models/assignment.d.ts.map +1 -0
  42. package/dist/models/assignment.js +309 -0
  43. package/dist/models/assignment.js.map +1 -0
  44. package/dist/models/attendance.d.ts +180 -0
  45. package/dist/models/attendance.d.ts.map +1 -0
  46. package/dist/models/attendance.js +188 -0
  47. package/dist/models/attendance.js.map +1 -0
  48. package/dist/models/auth.d.ts +153 -0
  49. package/dist/models/auth.d.ts.map +1 -0
  50. package/dist/models/auth.js +217 -0
  51. package/dist/models/auth.js.map +1 -0
  52. package/dist/models/class.d.ts +439 -0
  53. package/dist/models/class.d.ts.map +1 -0
  54. package/dist/models/class.js +546 -0
  55. package/dist/models/class.js.map +1 -0
  56. package/dist/models/comment.d.ts +171 -0
  57. package/dist/models/comment.d.ts.map +1 -0
  58. package/dist/models/comment.js +138 -0
  59. package/dist/models/comment.js.map +1 -0
  60. package/dist/models/conversation.d.ts +164 -0
  61. package/dist/models/conversation.d.ts.map +1 -0
  62. package/dist/models/conversation.js +175 -0
  63. package/dist/models/conversation.js.map +1 -0
  64. package/dist/models/event.d.ts +295 -0
  65. package/dist/models/event.d.ts.map +1 -0
  66. package/dist/models/event.js +145 -0
  67. package/dist/models/event.js.map +1 -0
  68. package/dist/models/file.d.ts +536 -0
  69. package/dist/models/file.d.ts.map +1 -0
  70. package/dist/models/file.js +126 -0
  71. package/dist/models/file.js.map +1 -0
  72. package/dist/models/folder.d.ts +295 -0
  73. package/dist/models/folder.d.ts.map +1 -0
  74. package/dist/models/folder.js +202 -0
  75. package/dist/models/folder.js.map +1 -0
  76. package/dist/models/labChat.d.ts +243 -0
  77. package/dist/models/labChat.d.ts.map +1 -0
  78. package/dist/models/labChat.js +204 -0
  79. package/dist/models/labChat.js.map +1 -0
  80. package/dist/models/marketing.d.ts +72 -0
  81. package/dist/models/marketing.d.ts.map +1 -0
  82. package/dist/models/marketing.js +26 -0
  83. package/dist/models/marketing.js.map +1 -0
  84. package/dist/models/message.d.ts +100 -0
  85. package/dist/models/message.d.ts.map +1 -0
  86. package/dist/models/message.js +131 -0
  87. package/dist/models/message.js.map +1 -0
  88. package/dist/models/newtonChat.d.ts +72 -0
  89. package/dist/models/newtonChat.d.ts.map +1 -0
  90. package/dist/models/newtonChat.js +61 -0
  91. package/dist/models/newtonChat.js.map +1 -0
  92. package/dist/models/notification.d.ts +65 -0
  93. package/dist/models/notification.d.ts.map +1 -0
  94. package/dist/models/notification.js +46 -0
  95. package/dist/models/notification.js.map +1 -0
  96. package/dist/models/section.d.ts +102 -0
  97. package/dist/models/section.d.ts.map +1 -0
  98. package/dist/models/section.js +83 -0
  99. package/dist/models/section.js.map +1 -0
  100. package/dist/models/user.d.ts +39 -0
  101. package/dist/models/user.d.ts.map +1 -0
  102. package/dist/models/user.js +38 -0
  103. package/dist/models/user.js.map +1 -0
  104. package/dist/models/worksheet.d.ts +460 -0
  105. package/dist/models/worksheet.d.ts.map +1 -0
  106. package/dist/models/worksheet.js +200 -0
  107. package/dist/models/worksheet.js.map +1 -0
  108. package/dist/pipelines/aiLabChat.d.ts +21 -0
  109. package/dist/pipelines/aiLabChat.d.ts.map +1 -0
  110. package/dist/pipelines/aiLabChat.js +460 -0
  111. package/dist/pipelines/aiLabChat.js.map +1 -0
  112. package/dist/pipelines/aiNewtonChat.d.ts +30 -0
  113. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -0
  114. package/dist/pipelines/aiNewtonChat.js +289 -0
  115. package/dist/pipelines/aiNewtonChat.js.map +1 -0
  116. package/dist/pipelines/gradeWorksheet.d.ts +30 -0
  117. package/dist/pipelines/gradeWorksheet.d.ts.map +1 -0
  118. package/dist/pipelines/gradeWorksheet.js +252 -0
  119. package/dist/pipelines/gradeWorksheet.js.map +1 -0
  120. package/dist/routers/_app.d.ts +1393 -1267
  121. package/dist/routers/_app.d.ts.map +1 -1
  122. package/dist/routers/agenda.d.ts +22 -22
  123. package/dist/routers/agenda.d.ts.map +1 -1
  124. package/dist/routers/agenda.js +4 -65
  125. package/dist/routers/agenda.js.map +1 -1
  126. package/dist/routers/announcement.d.ts +16 -16
  127. package/dist/routers/announcement.d.ts.map +1 -1
  128. package/dist/routers/announcement.js +37 -446
  129. package/dist/routers/announcement.js.map +1 -1
  130. package/dist/routers/assignment.d.ts +300 -378
  131. package/dist/routers/assignment.d.ts.map +1 -1
  132. package/dist/routers/assignment.js +78 -1868
  133. package/dist/routers/assignment.js.map +1 -1
  134. package/dist/routers/attendance.d.ts +19 -9
  135. package/dist/routers/attendance.d.ts.map +1 -1
  136. package/dist/routers/attendance.js +7 -264
  137. package/dist/routers/attendance.js.map +1 -1
  138. package/dist/routers/auth.d.ts +2 -2
  139. package/dist/routers/auth.d.ts.map +1 -1
  140. package/dist/routers/auth.js +29 -354
  141. package/dist/routers/auth.js.map +1 -1
  142. package/dist/routers/class.d.ts +139 -68
  143. package/dist/routers/class.d.ts.map +1 -1
  144. package/dist/routers/class.js +82 -1052
  145. package/dist/routers/class.js.map +1 -1
  146. package/dist/routers/comment.d.ts +6 -42
  147. package/dist/routers/comment.d.ts.map +1 -1
  148. package/dist/routers/comment.js +24 -244
  149. package/dist/routers/comment.js.map +1 -1
  150. package/dist/routers/conversation.d.ts +45 -7
  151. package/dist/routers/conversation.d.ts.map +1 -1
  152. package/dist/routers/conversation.js +19 -327
  153. package/dist/routers/conversation.js.map +1 -1
  154. package/dist/routers/event.d.ts +36 -36
  155. package/dist/routers/event.d.ts.map +1 -1
  156. package/dist/routers/event.js +13 -433
  157. package/dist/routers/event.js.map +1 -1
  158. package/dist/routers/file.d.ts +2 -2
  159. package/dist/routers/file.d.ts.map +1 -1
  160. package/dist/routers/file.js +9 -323
  161. package/dist/routers/file.js.map +1 -1
  162. package/dist/routers/folder.d.ts +21 -14
  163. package/dist/routers/folder.d.ts.map +1 -1
  164. package/dist/routers/folder.js +34 -745
  165. package/dist/routers/folder.js.map +1 -1
  166. package/dist/routers/labChat.d.ts +11 -10
  167. package/dist/routers/labChat.d.ts.map +1 -1
  168. package/dist/routers/labChat.js +19 -570
  169. package/dist/routers/labChat.js.map +1 -1
  170. package/dist/routers/marketing.d.ts +1 -1
  171. package/dist/routers/marketing.d.ts.map +1 -1
  172. package/dist/routers/marketing.js +7 -56
  173. package/dist/routers/marketing.js.map +1 -1
  174. package/dist/routers/message.d.ts +2 -2
  175. package/dist/routers/message.d.ts.map +1 -1
  176. package/dist/routers/message.js +27 -522
  177. package/dist/routers/message.js.map +1 -1
  178. package/dist/routers/newtonChat.d.ts +1 -1
  179. package/dist/routers/newtonChat.d.ts.map +1 -1
  180. package/dist/routers/newtonChat.js +7 -246
  181. package/dist/routers/newtonChat.js.map +1 -1
  182. package/dist/routers/notifications.d.ts +4 -4
  183. package/dist/routers/notifications.d.ts.map +1 -1
  184. package/dist/routers/notifications.js +18 -83
  185. package/dist/routers/notifications.js.map +1 -1
  186. package/dist/routers/section.d.ts +4 -4
  187. package/dist/routers/section.d.ts.map +1 -1
  188. package/dist/routers/section.js +14 -286
  189. package/dist/routers/section.js.map +1 -1
  190. package/dist/routers/user.d.ts +1 -1
  191. package/dist/routers/user.d.ts.map +1 -1
  192. package/dist/routers/user.js +32 -207
  193. package/dist/routers/user.js.map +1 -1
  194. package/dist/routers/worksheet.d.ts +51 -38
  195. package/dist/routers/worksheet.d.ts.map +1 -1
  196. package/dist/routers/worksheet.js +79 -394
  197. package/dist/routers/worksheet.js.map +1 -1
  198. package/dist/seedDatabase.d.ts +1 -1
  199. package/dist/server/pipelines/gradeWorksheet.d.ts +6 -6
  200. package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -1
  201. package/dist/server/pipelines/gradeWorksheet.js +12 -5
  202. package/dist/server/pipelines/gradeWorksheet.js.map +1 -1
  203. package/dist/services/agenda.d.ts +100 -0
  204. package/dist/services/agenda.d.ts.map +1 -0
  205. package/dist/services/agenda.js +21 -0
  206. package/dist/services/agenda.js.map +1 -0
  207. package/dist/services/announcement.d.ts +135 -0
  208. package/dist/services/announcement.d.ts.map +1 -0
  209. package/dist/services/announcement.js +223 -0
  210. package/dist/services/announcement.js.map +1 -0
  211. package/dist/services/assignment.d.ts +1462 -0
  212. package/dist/services/assignment.d.ts.map +1 -0
  213. package/dist/services/assignment.js +898 -0
  214. package/dist/services/assignment.js.map +1 -0
  215. package/dist/services/attendance.d.ts +93 -0
  216. package/dist/services/attendance.d.ts.map +1 -0
  217. package/dist/services/attendance.js +61 -0
  218. package/dist/services/attendance.js.map +1 -0
  219. package/dist/services/auth.d.ts +68 -0
  220. package/dist/services/auth.d.ts.map +1 -0
  221. package/dist/services/auth.js +218 -0
  222. package/dist/services/auth.js.map +1 -0
  223. package/dist/services/class.d.ts +621 -0
  224. package/dist/services/class.d.ts.map +1 -0
  225. package/dist/services/class.js +474 -0
  226. package/dist/services/class.js.map +1 -0
  227. package/dist/services/comment.d.ts +100 -0
  228. package/dist/services/comment.d.ts.map +1 -0
  229. package/dist/services/comment.js +83 -0
  230. package/dist/services/comment.js.map +1 -0
  231. package/dist/services/conversation.d.ts +159 -0
  232. package/dist/services/conversation.d.ts.map +1 -0
  233. package/dist/services/conversation.js +138 -0
  234. package/dist/services/conversation.js.map +1 -0
  235. package/dist/services/event.d.ts +216 -0
  236. package/dist/services/event.d.ts.map +1 -0
  237. package/dist/services/event.js +168 -0
  238. package/dist/services/event.js.map +1 -0
  239. package/dist/services/file.d.ts +74 -0
  240. package/dist/services/file.d.ts.map +1 -0
  241. package/dist/services/file.js +133 -0
  242. package/dist/services/file.js.map +1 -0
  243. package/dist/services/folder.d.ts +239 -0
  244. package/dist/services/folder.d.ts.map +1 -0
  245. package/dist/services/folder.js +248 -0
  246. package/dist/services/folder.js.map +1 -0
  247. package/dist/services/labChat.d.ts +165 -0
  248. package/dist/services/labChat.d.ts.map +1 -0
  249. package/dist/services/labChat.js +289 -0
  250. package/dist/services/labChat.js.map +1 -0
  251. package/dist/services/marketing.d.ts +50 -0
  252. package/dist/services/marketing.d.ts.map +1 -0
  253. package/dist/services/marketing.js +32 -0
  254. package/dist/services/marketing.js.map +1 -0
  255. package/dist/services/message.d.ts +95 -0
  256. package/dist/services/message.d.ts.map +1 -0
  257. package/dist/services/message.js +350 -0
  258. package/dist/services/message.js.map +1 -0
  259. package/dist/services/newtonChat.d.ts +22 -0
  260. package/dist/services/newtonChat.d.ts.map +1 -0
  261. package/dist/services/newtonChat.js +174 -0
  262. package/dist/services/newtonChat.js.map +1 -0
  263. package/dist/services/notification.d.ts +65 -0
  264. package/dist/services/notification.d.ts.map +1 -0
  265. package/dist/services/notification.js +33 -0
  266. package/dist/services/notification.js.map +1 -0
  267. package/dist/services/section.d.ts +53 -0
  268. package/dist/services/section.d.ts.map +1 -0
  269. package/dist/services/section.js +199 -0
  270. package/dist/services/section.js.map +1 -0
  271. package/dist/services/user.d.ts +48 -0
  272. package/dist/services/user.d.ts.map +1 -0
  273. package/dist/services/user.js +141 -0
  274. package/dist/services/user.js.map +1 -0
  275. package/dist/services/worksheet.d.ts +239 -0
  276. package/dist/services/worksheet.d.ts.map +1 -0
  277. package/dist/services/worksheet.js +235 -0
  278. package/dist/services/worksheet.js.map +1 -0
  279. package/dist/utils/aiUser.d.ts +1 -3
  280. package/dist/utils/aiUser.d.ts.map +1 -1
  281. package/dist/utils/aiUser.js +6 -5
  282. package/dist/utils/aiUser.js.map +1 -1
  283. package/dist/utils/email.d.ts +3 -0
  284. package/dist/utils/email.d.ts.map +1 -1
  285. package/dist/utils/email.js +7 -4
  286. package/dist/utils/email.js.map +1 -1
  287. package/dist/utils/generateInviteCode.d.ts +1 -2
  288. package/dist/utils/generateInviteCode.d.ts.map +1 -1
  289. package/dist/utils/generateInviteCode.js +3 -4
  290. package/dist/utils/generateInviteCode.js.map +1 -1
  291. package/dist/utils/inference.d.ts +3 -0
  292. package/dist/utils/inference.d.ts.map +1 -1
  293. package/dist/utils/inference.js +7 -4
  294. package/dist/utils/inference.js.map +1 -1
  295. package/dist/utils/logger.d.ts +3 -0
  296. package/dist/utils/logger.d.ts.map +1 -1
  297. package/dist/utils/logger.js +5 -2
  298. package/dist/utils/logger.js.map +1 -1
  299. package/dist/utils/prismaErrorHandler.d.ts.map +1 -1
  300. package/dist/utils/prismaErrorHandler.js +5 -2
  301. package/dist/utils/prismaErrorHandler.js.map +1 -1
  302. package/dist/utils/prismaWrapper.d.ts +1 -0
  303. package/dist/utils/prismaWrapper.d.ts.map +1 -1
  304. package/dist/utils/prismaWrapper.js +6 -2
  305. package/dist/utils/prismaWrapper.js.map +1 -1
  306. package/docker-compose.yml +5 -0
  307. package/package.json +4 -3
  308. package/src/index.ts +119 -12
  309. package/src/lib/config/env.ts +6 -0
  310. package/src/lib/fileUpload.ts +0 -1
  311. package/src/lib/googleCloudStorage.ts +17 -0
  312. package/src/lib/pusher.ts +5 -1
  313. package/src/lib/redis.ts +56 -0
  314. package/src/lib/thumbnailGenerator.ts +170 -168
  315. package/src/middleware/auth.ts +80 -137
  316. package/src/models/agenda.ts +46 -0
  317. package/src/models/announcement.ts +134 -0
  318. package/src/models/assignment.ts +322 -0
  319. package/src/models/attendance.ts +208 -0
  320. package/src/models/auth.ts +247 -0
  321. package/src/models/class.ts +598 -0
  322. package/src/models/comment.ts +152 -0
  323. package/src/models/conversation.ts +200 -0
  324. package/src/models/event.ts +177 -0
  325. package/src/models/file.ts +129 -0
  326. package/src/models/folder.ts +225 -0
  327. package/src/models/labChat.ts +213 -0
  328. package/src/models/marketing.ts +45 -0
  329. package/src/models/message.ts +153 -0
  330. package/src/models/newtonChat.ts +70 -0
  331. package/src/models/notification.ts +54 -0
  332. package/src/models/section.ts +98 -0
  333. package/src/models/user.ts +47 -0
  334. package/src/models/worksheet.ts +294 -0
  335. package/src/{server/pipelines → pipelines}/aiLabChat.ts +11 -7
  336. package/src/{server/pipelines → pipelines}/aiNewtonChat.ts +9 -5
  337. package/src/{server/pipelines → pipelines}/gradeWorksheet.ts +25 -14
  338. package/src/routers/agenda.ts +3 -66
  339. package/src/routers/announcement.ts +54 -495
  340. package/src/routers/assignment.ts +126 -2018
  341. package/src/routers/attendance.ts +15 -276
  342. package/src/routers/auth.ts +79 -442
  343. package/src/routers/class.ts +263 -1187
  344. package/src/routers/comment.ts +61 -288
  345. package/src/routers/conversation.ts +51 -360
  346. package/src/routers/event.ts +50 -481
  347. package/src/routers/file.ts +45 -368
  348. package/src/routers/folder.ts +107 -836
  349. package/src/routers/labChat.ts +29 -605
  350. package/src/routers/marketing.ts +35 -77
  351. package/src/routers/message.ts +45 -571
  352. package/src/routers/newtonChat.ts +17 -278
  353. package/src/routers/notifications.ts +32 -82
  354. package/src/routers/section.ts +46 -330
  355. package/src/routers/user.ts +49 -227
  356. package/src/routers/worksheet.ts +215 -503
  357. package/src/services/agenda.ts +21 -0
  358. package/src/services/announcement.ts +290 -0
  359. package/src/services/assignment.ts +1198 -0
  360. package/src/services/attendance.ts +85 -0
  361. package/src/services/auth.ts +277 -0
  362. package/src/services/class.ts +622 -0
  363. package/src/services/comment.ts +106 -0
  364. package/src/services/conversation.ts +213 -0
  365. package/src/services/event.ts +231 -0
  366. package/src/services/file.ts +167 -0
  367. package/src/services/folder.ts +316 -0
  368. package/src/services/labChat.ts +352 -0
  369. package/src/services/marketing.ts +57 -0
  370. package/src/services/message.ts +461 -0
  371. package/src/services/newtonChat.ts +222 -0
  372. package/src/services/notification.ts +50 -0
  373. package/src/services/section.ts +283 -0
  374. package/src/services/user.ts +172 -0
  375. package/src/services/worksheet.ts +358 -0
  376. package/src/utils/aiUser.ts +4 -3
  377. package/src/utils/email.ts +5 -3
  378. package/src/utils/generateInviteCode.ts +1 -3
  379. package/src/utils/inference.ts +5 -2
  380. package/src/utils/logger.ts +3 -1
  381. package/src/utils/prismaErrorHandler.ts +3 -0
  382. package/src/utils/prismaWrapper.ts +4 -0
  383. package/tests/globalSetup.ts +62 -0
  384. package/tests/helpers.ts +22 -0
  385. package/tests/middleware/security.test.ts +42 -0
  386. package/tests/routers/agenda.test.ts +138 -0
  387. package/tests/routers/announcement.test.ts +490 -0
  388. package/tests/routers/assignment.test.ts +837 -0
  389. package/tests/{attendance.test.ts → routers/attendance.test.ts} +6 -14
  390. package/tests/routers/auth.test.ts +171 -0
  391. package/tests/{class.test.ts → routers/class.test.ts} +131 -85
  392. package/tests/routers/comment.test.ts +126 -0
  393. package/tests/routers/conversation.test.ts +145 -0
  394. package/tests/{event.test.ts → routers/event.test.ts} +93 -32
  395. package/tests/routers/folder.test.ts +178 -0
  396. package/tests/routers/labChat.test.ts +115 -0
  397. package/tests/routers/marketing.test.ts +59 -0
  398. package/tests/routers/message.test.ts +123 -0
  399. package/tests/routers/notification.test.ts +69 -0
  400. package/tests/{section.test.ts → routers/section.test.ts} +5 -13
  401. package/tests/server/rateLimit.test.ts +73 -0
  402. package/tests/setup.ts +18 -92
  403. package/tests/user.test.ts +9 -31
  404. package/tests/utils/aiUser.test.ts +22 -0
  405. package/tests/utils/generateInviteCode.test.ts +24 -0
  406. package/tests/utils/logger.test.ts +74 -0
  407. package/tests/utils/prismaErrorHandler.test.ts +101 -0
  408. package/tests/utils/prismaWrapper.test.ts +82 -0
  409. package/tests/worksheet.test.ts +181 -0
  410. package/vitest.config.ts +6 -3
  411. package/vitest.unit.config.ts +21 -0
  412. package/TODO.md +0 -2
  413. package/coverage/base.css +0 -224
  414. package/coverage/block-navigation.js +0 -87
  415. package/coverage/clover.xml +0 -12110
  416. package/coverage/coverage-final.json +0 -44
  417. package/coverage/favicon.png +0 -0
  418. package/coverage/index.html +0 -221
  419. package/coverage/prettify.css +0 -1
  420. package/coverage/prettify.js +0 -2
  421. package/coverage/server/index.html +0 -116
  422. package/coverage/server/src/exportType.ts.html +0 -109
  423. package/coverage/server/src/index.html +0 -161
  424. package/coverage/server/src/index.ts.html +0 -1702
  425. package/coverage/server/src/instrument.ts.html +0 -130
  426. package/coverage/server/src/lib/config/env.ts.html +0 -448
  427. package/coverage/server/src/lib/config/index.html +0 -116
  428. package/coverage/server/src/lib/fileUpload.ts.html +0 -1138
  429. package/coverage/server/src/lib/googleCloudStorage.ts.html +0 -334
  430. package/coverage/server/src/lib/index.html +0 -206
  431. package/coverage/server/src/lib/jsonConversion.ts.html +0 -2323
  432. package/coverage/server/src/lib/jsonStyles.ts.html +0 -193
  433. package/coverage/server/src/lib/notificationHandler.ts.html +0 -193
  434. package/coverage/server/src/lib/pusher.ts.html +0 -121
  435. package/coverage/server/src/lib/thumbnailGenerator.ts.html +0 -592
  436. package/coverage/server/src/middleware/auth.ts.html +0 -646
  437. package/coverage/server/src/middleware/index.html +0 -146
  438. package/coverage/server/src/middleware/logging.ts.html +0 -244
  439. package/coverage/server/src/middleware/security.ts.html +0 -271
  440. package/coverage/server/src/routers/_app.ts.html +0 -232
  441. package/coverage/server/src/routers/agenda.ts.html +0 -319
  442. package/coverage/server/src/routers/announcement.ts.html +0 -3481
  443. package/coverage/server/src/routers/assignment.ts.html +0 -7633
  444. package/coverage/server/src/routers/attendance.ts.html +0 -1030
  445. package/coverage/server/src/routers/auth.ts.html +0 -1081
  446. package/coverage/server/src/routers/class.ts.html +0 -3535
  447. package/coverage/server/src/routers/comment.ts.html +0 -991
  448. package/coverage/server/src/routers/conversation.ts.html +0 -982
  449. package/coverage/server/src/routers/event.ts.html +0 -1609
  450. package/coverage/server/src/routers/file.ts.html +0 -1144
  451. package/coverage/server/src/routers/folder.ts.html +0 -2797
  452. package/coverage/server/src/routers/index.html +0 -386
  453. package/coverage/server/src/routers/labChat.ts.html +0 -3073
  454. package/coverage/server/src/routers/marketing.ts.html +0 -340
  455. package/coverage/server/src/routers/message.ts.html +0 -1912
  456. package/coverage/server/src/routers/notifications.ts.html +0 -364
  457. package/coverage/server/src/routers/section.ts.html +0 -1120
  458. package/coverage/server/src/routers/user.ts.html +0 -862
  459. package/coverage/server/src/routers/worksheet.ts.html +0 -1729
  460. package/coverage/server/src/trpc.ts.html +0 -397
  461. package/coverage/server/src/types/index.html +0 -116
  462. package/coverage/server/src/types/trpc.ts.html +0 -127
  463. package/coverage/server/src/utils/aiUser.ts.html +0 -280
  464. package/coverage/server/src/utils/email.ts.html +0 -121
  465. package/coverage/server/src/utils/generateInviteCode.ts.html +0 -106
  466. package/coverage/server/src/utils/index.html +0 -206
  467. package/coverage/server/src/utils/inference.ts.html +0 -709
  468. package/coverage/server/src/utils/logger.ts.html +0 -664
  469. package/coverage/server/src/utils/prismaErrorHandler.ts.html +0 -907
  470. package/coverage/server/src/utils/prismaWrapper.ts.html +0 -355
  471. package/coverage/server/vitest.config.ts.html +0 -196
  472. package/coverage/sort-arrow-sprite.png +0 -0
  473. package/coverage/sorter.js +0 -210
  474. package/src/lib/notificationHandler.ts +0 -36
  475. package/tests/announcement.test.ts +0 -164
  476. package/tests/assignment.test.ts +0 -296
  477. package/tests/auth.test.ts +0 -48
@@ -1,302 +1,13 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4de0a549-5566-5b60-aa1d-acdb528cce7a")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="43c06b92-74d9-5f52-a500-f14b511e48a2")}catch(e){}}();
3
3
  import { z } from "zod";
4
- import { createTRPCRouter, protectedProcedure, protectedTeacherProcedure, protectedClassMemberProcedure } from "../trpc.js";
5
- import { prisma } from "../lib/prisma.js";
6
- import { TRPCError } from "@trpc/server";
7
- import { generateInviteCode } from "../utils/generateInviteCode.js";
4
+ import { createTRPCRouter, protectedProcedure, protectedTeacherProcedure, protectedClassMemberProcedure, } from "../trpc.js";
5
+ import { getAllClasses, getClass, updateClass, createClass, deleteClass, addStudent, changeRole, removeMember, leaveClass, joinClass, getInviteCode, createInviteCode, getGrades, updateGrade, getEvents, listMarkSchemes, createMarkScheme, updateMarkScheme, deleteMarkScheme, listGradingBoundaries, createGradingBoundary, updateGradingBoundary, deleteGradingBoundary, getSyllabus, updateSyllabus, listLabDrafts, createLabDraft, updateLabDraft, deleteLabDraft, publishLabDraft, getFiles, exportClass, importClass, } from "../services/class.js";
8
6
  export const classRouter = createTRPCRouter({
9
- getAll: protectedProcedure
10
- .query(async ({ ctx }) => {
11
- const [teacherClasses, studentClasses] = await Promise.all([
12
- prisma.class.findMany({
13
- where: {
14
- teachers: {
15
- some: {
16
- id: ctx.user?.id,
17
- },
18
- },
19
- },
20
- include: {
21
- assignments: {
22
- where: {
23
- dueDate: {
24
- lte: new Date(new Date().setHours(23, 59, 59, 999)),
25
- },
26
- template: false,
27
- },
28
- select: {
29
- id: true,
30
- title: true,
31
- type: true,
32
- dueDate: true,
33
- },
34
- },
35
- students: {
36
- select: {
37
- id: true,
38
- username: true,
39
- profile: {
40
- select: {
41
- displayName: true,
42
- profilePicture: true,
43
- profilePictureThumbnail: true,
44
- },
45
- },
46
- },
47
- },
48
- teachers: {
49
- select: {
50
- id: true,
51
- username: true,
52
- profile: {
53
- select: {
54
- displayName: true,
55
- profilePicture: true,
56
- profilePictureThumbnail: true,
57
- },
58
- },
59
- },
60
- },
61
- },
62
- }),
63
- prisma.class.findMany({
64
- where: {
65
- students: {
66
- some: {
67
- id: ctx.user?.id,
68
- },
69
- },
70
- },
71
- include: {
72
- assignments: {
73
- where: {
74
- dueDate: {
75
- lte: new Date(new Date().setHours(23, 59, 59, 999)),
76
- },
77
- template: false,
78
- },
79
- select: {
80
- id: true,
81
- title: true,
82
- type: true,
83
- dueDate: true,
84
- },
85
- },
86
- students: {
87
- select: {
88
- id: true,
89
- username: true,
90
- profile: {
91
- select: {
92
- displayName: true,
93
- profilePicture: true,
94
- profilePictureThumbnail: true,
95
- },
96
- },
97
- },
98
- },
99
- teachers: {
100
- select: {
101
- id: true,
102
- username: true,
103
- profile: {
104
- select: {
105
- displayName: true,
106
- profilePicture: true,
107
- profilePictureThumbnail: true,
108
- },
109
- },
110
- },
111
- },
112
- },
113
- }),
114
- ]);
115
- return {
116
- teacherInClass: teacherClasses.map(cls => ({
117
- id: cls.id,
118
- name: cls.name,
119
- section: cls.section,
120
- subject: cls.subject,
121
- dueToday: cls.assignments,
122
- assignments: cls.assignments,
123
- members: [...cls.students, ...cls.teachers],
124
- color: cls.color,
125
- })),
126
- studentInClass: studentClasses.map(cls => ({
127
- id: cls.id,
128
- name: cls.name,
129
- section: cls.section,
130
- subject: cls.subject,
131
- dueToday: cls.assignments,
132
- assignments: cls.assignments,
133
- members: [...cls.students, ...cls.teachers],
134
- color: cls.color,
135
- })),
136
- };
137
- }),
7
+ getAll: protectedProcedure.query(({ ctx }) => getAllClasses(ctx.user?.id ?? "")),
138
8
  get: protectedProcedure
139
- .input(z.object({
140
- classId: z.string(),
141
- }))
142
- .query(async ({ ctx, input }) => {
143
- const { classId } = input;
144
- const isTeacher = await prisma.class.findFirst({
145
- where: {
146
- id: classId,
147
- teachers: {
148
- some: { id: ctx.user?.id },
149
- },
150
- },
151
- });
152
- const classData = await prisma.class.findUnique({
153
- where: {
154
- id: classId,
155
- },
156
- include: {
157
- teachers: {
158
- select: {
159
- id: true,
160
- username: true,
161
- profile: {
162
- select: {
163
- displayName: true,
164
- profilePicture: true,
165
- profilePictureThumbnail: true,
166
- }
167
- }
168
- },
169
- },
170
- students: {
171
- select: {
172
- id: true,
173
- username: true,
174
- profile: {
175
- select: {
176
- displayName: true,
177
- profilePicture: true,
178
- profilePictureThumbnail: true,
179
- },
180
- },
181
- },
182
- },
183
- announcements: {
184
- orderBy: {
185
- createdAt: 'desc',
186
- },
187
- select: {
188
- id: true,
189
- remarks: true,
190
- createdAt: true,
191
- modifiedAt: true,
192
- teacher: {
193
- select: {
194
- id: true,
195
- username: true,
196
- profile: {
197
- select: {
198
- displayName: true,
199
- profilePicture: true,
200
- profilePictureThumbnail: true,
201
- },
202
- },
203
- },
204
- },
205
- },
206
- },
207
- assignments: {
208
- ...(!isTeacher && {
209
- where: { OR: [
210
- {
211
- assignedTo: {
212
- some: {
213
- id: ctx.user?.id,
214
- },
215
- },
216
- },
217
- {
218
- assignedTo: {
219
- none: {},
220
- },
221
- },
222
- ], }
223
- }),
224
- select: {
225
- type: true,
226
- id: true,
227
- title: true,
228
- dueDate: true,
229
- createdAt: true,
230
- weight: true,
231
- order: true,
232
- graded: true,
233
- maxGrade: true,
234
- instructions: true,
235
- inProgress: true,
236
- template: false,
237
- section: {
238
- select: {
239
- id: true,
240
- name: true,
241
- },
242
- },
243
- markScheme: {
244
- select: {
245
- id: true,
246
- structured: true,
247
- },
248
- },
249
- gradingBoundary: {
250
- select: {
251
- id: true,
252
- structured: true,
253
- },
254
- },
255
- submissions: {
256
- ...(!isTeacher && {
257
- where: {
258
- studentId: ctx.user?.id,
259
- },
260
- }),
261
- select: {
262
- studentId: true,
263
- id: true,
264
- submitted: true,
265
- gradeReceived: true,
266
- rubricState: true,
267
- teacherComments: true,
268
- returned: true,
269
- submittedAt: true,
270
- },
271
- },
272
- },
273
- },
274
- },
275
- });
276
- if (!classData) {
277
- throw new Error('Class not found');
278
- }
279
- const formattedClassData = {
280
- ...classData,
281
- assignments: classData.assignments.map(assignment => ({
282
- ...assignment,
283
- late: assignment.dueDate < new Date(),
284
- submitted: assignment.submissions.find(submission => submission.studentId === ctx.user?.id)?.submitted,
285
- returned: assignment.submissions.find(submission => submission.studentId === ctx.user?.id)?.returned,
286
- })),
287
- };
288
- const sections = await prisma.section.findMany({
289
- where: {
290
- classId: classId,
291
- },
292
- });
293
- return {
294
- class: {
295
- ...formattedClassData,
296
- sections,
297
- },
298
- };
299
- }),
9
+ .input(z.object({ classId: z.string() }))
10
+ .query(({ ctx, input }) => getClass(ctx.user?.id ?? "", input.classId)),
300
11
  update: protectedTeacherProcedure
301
12
  .input(z.object({
302
13
  classId: z.string(),
@@ -304,23 +15,9 @@ export const classRouter = createTRPCRouter({
304
15
  section: z.string().optional(),
305
16
  subject: z.string().optional(),
306
17
  }))
307
- .mutation(async ({ ctx, input }) => {
18
+ .mutation(({ input }) => {
308
19
  const { classId, ...updateData } = input;
309
- const updatedClass = await prisma.class.update({
310
- where: {
311
- id: classId,
312
- },
313
- data: updateData,
314
- select: {
315
- id: true,
316
- name: true,
317
- section: true,
318
- subject: true,
319
- }
320
- });
321
- return {
322
- updatedClass,
323
- };
20
+ return updateClass(classId, updateData);
324
21
  }),
325
22
  create: protectedProcedure
326
23
  .input(z.object({
@@ -331,355 +28,43 @@ export const classRouter = createTRPCRouter({
331
28
  subject: z.string(),
332
29
  color: z.string().optional(),
333
30
  }))
334
- .mutation(async ({ ctx, input }) => {
335
- const { students, teachers, name, section, subject, color } = input;
336
- if (teachers && teachers.length > 0 && students && students.length > 0) {
337
- const newClass = await prisma.class.create({
338
- data: {
339
- name,
340
- section,
341
- subject,
342
- color,
343
- teachers: {
344
- connect: teachers.map(teacher => ({ id: teacher })),
345
- },
346
- students: {
347
- connect: students.map(student => ({ id: student })),
348
- },
349
- },
350
- include: {
351
- teachers: true,
352
- students: true,
353
- },
354
- });
355
- return newClass;
356
- }
357
- const newClass = await prisma.class.create({
358
- data: {
359
- name,
360
- section,
361
- subject,
362
- color,
363
- teachers: {
364
- connect: {
365
- id: ctx.user?.id,
366
- },
367
- },
368
- },
369
- });
370
- return newClass;
371
- }),
31
+ .mutation(({ ctx, input }) => createClass(ctx.user?.id ?? "", input)),
372
32
  delete: protectedTeacherProcedure
373
- .input(z.object({
374
- classId: z.string(),
375
- id: z.string(),
376
- }))
377
- .mutation(async ({ ctx, input }) => {
378
- // Verify user is the teacher of this class
379
- const classToDelete = await prisma.class.findFirst({
380
- where: {
381
- id: input.id,
382
- },
383
- });
384
- if (!classToDelete) {
385
- throw new Error("Class not found or you don't have permission to delete it");
386
- }
387
- await prisma.class.delete({
388
- where: {
389
- id: input.id,
390
- },
391
- });
392
- return {
393
- deletedClass: {
394
- id: input.id,
395
- }
396
- };
397
- }),
33
+ .input(z.object({ classId: z.string(), id: z.string() }))
34
+ .mutation(({ input }) => deleteClass(input.id)),
398
35
  addStudent: protectedTeacherProcedure
399
- .input(z.object({
400
- classId: z.string(),
401
- studentId: z.string(),
402
- }))
403
- .mutation(async ({ ctx, input }) => {
404
- const { classId, studentId } = input;
405
- const student = await prisma.user.findUnique({
406
- where: {
407
- id: studentId,
408
- },
409
- });
410
- if (!student) {
411
- throw new Error("Student not found");
412
- }
413
- const updatedClass = await prisma.class.update({
414
- where: {
415
- id: classId,
416
- },
417
- data: {
418
- students: {
419
- connect: {
420
- id: studentId,
421
- },
422
- },
423
- },
424
- select: {
425
- id: true,
426
- name: true,
427
- section: true,
428
- subject: true,
429
- }
430
- });
431
- return {
432
- updatedClass,
433
- newStudent: student,
434
- };
435
- }),
36
+ .input(z.object({ classId: z.string(), studentId: z.string() }))
37
+ .mutation(({ input }) => addStudent(input.classId, input.studentId)),
436
38
  changeRole: protectedTeacherProcedure
437
39
  .input(z.object({
438
40
  classId: z.string(),
439
41
  userId: z.string(),
440
- type: z.enum(['teacher', 'student']),
42
+ type: z.enum(["teacher", "student"]),
441
43
  }))
442
- .mutation(async ({ ctx, input }) => {
443
- const { classId, userId, type } = input;
444
- const user = await prisma.user.findUnique({
445
- where: { id: userId },
446
- select: {
447
- id: true,
448
- username: true,
449
- },
450
- });
451
- if (!user) {
452
- throw new Error("User not found");
453
- }
454
- const updatedClass = await prisma.class.update({
455
- where: { id: classId },
456
- data: {
457
- [type === 'teacher' ? 'teachers' : 'students']: {
458
- connect: { id: userId },
459
- },
460
- [type === 'teacher' ? 'students' : 'teachers']: {
461
- disconnect: { id: userId },
462
- },
463
- },
464
- });
465
- return {
466
- updatedClass,
467
- user: {
468
- ...user,
469
- type,
470
- },
471
- };
472
- }),
44
+ .mutation(({ input }) => changeRole(input.classId, input.userId, input.type)),
473
45
  removeMember: protectedTeacherProcedure
474
- .input(z.object({
475
- classId: z.string(),
476
- userId: z.string(),
477
- }))
478
- .mutation(async ({ ctx, input }) => {
479
- const { classId, userId } = input;
480
- const updatedClass = await prisma.class.update({
481
- where: { id: classId },
482
- data: {
483
- teachers: {
484
- disconnect: { id: userId },
485
- },
486
- students: {
487
- disconnect: { id: userId },
488
- },
489
- },
490
- });
491
- return {
492
- updatedClass,
493
- removedUserId: userId,
494
- };
495
- }),
46
+ .input(z.object({ classId: z.string(), userId: z.string() }))
47
+ .mutation(({ input }) => removeMember(input.classId, input.userId)),
496
48
  leaveClass: protectedProcedure
497
- .input(z.object({
498
- classId: z.string(),
499
- }))
500
- .mutation(async ({ ctx, input }) => {
501
- const { classId } = input;
502
- const userId = ctx.user?.id;
503
- if (!userId) {
504
- throw new TRPCError({
505
- code: 'UNAUTHORIZED',
506
- message: 'User not authenticated',
507
- });
49
+ .input(z.object({ classId: z.string() }))
50
+ .mutation(({ ctx, input }) => {
51
+ if (!ctx.user?.id) {
52
+ throw new Error("User not authenticated");
508
53
  }
509
- const classData = await prisma.class.findFirst({
510
- where: {
511
- id: classId,
512
- students: {
513
- some: { id: userId },
514
- },
515
- },
516
- });
517
- if (!classData) {
518
- throw new TRPCError({
519
- code: 'NOT_FOUND',
520
- message: 'Class not found or you are not a student in this class',
521
- });
522
- }
523
- await prisma.class.update({
524
- where: { id: classId },
525
- data: {
526
- students: {
527
- disconnect: { id: userId },
528
- },
529
- },
530
- });
531
- return {
532
- success: true,
533
- leftClassId: classId,
534
- };
54
+ return leaveClass(ctx.user.id, input.classId);
535
55
  }),
536
56
  join: protectedProcedure
537
- .input(z.object({
538
- classCode: z.string(),
539
- }))
540
- .mutation(async ({ ctx, input }) => {
541
- const { classCode } = input;
542
- // Case-insensitive search for invite code
543
- const session = await prisma.session.findFirst({
544
- where: {
545
- id: {
546
- equals: classCode,
547
- mode: 'insensitive',
548
- },
549
- },
550
- });
551
- if (!session || !session.classId) {
552
- throw new Error("Class not found");
553
- }
554
- if (session.expiresAt && session.expiresAt < new Date()) {
555
- throw new Error("Session expired");
556
- }
557
- const updatedClass = await prisma.class.update({
558
- where: { id: session.classId },
559
- data: {
560
- students: {
561
- connect: { id: ctx.user?.id },
562
- },
563
- },
564
- select: {
565
- id: true,
566
- name: true,
567
- section: true,
568
- subject: true,
569
- },
570
- });
571
- return {
572
- joinedClass: updatedClass,
573
- };
574
- }),
57
+ .input(z.object({ classCode: z.string() }))
58
+ .mutation(({ ctx, input }) => joinClass(ctx.user?.id ?? "", input.classCode)),
575
59
  getInviteCode: protectedTeacherProcedure
576
- .input(z.object({
577
- classId: z.string(),
578
- }))
579
- .query(async ({ ctx, input }) => {
580
- const { classId } = input;
581
- const session = await prisma.session.findFirst({
582
- where: {
583
- classId,
584
- },
585
- });
586
- if ((session?.expiresAt && session.expiresAt < new Date()) || !session) {
587
- const newSession = await prisma.session.create({
588
- data: {
589
- id: generateInviteCode(),
590
- classId,
591
- expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours from now
592
- }
593
- });
594
- return {
595
- code: newSession.id,
596
- };
597
- }
598
- return {
599
- code: session?.id,
600
- };
601
- }),
60
+ .input(z.object({ classId: z.string() }))
61
+ .query(({ input }) => getInviteCode(input.classId)),
602
62
  createInviteCode: protectedTeacherProcedure
603
- .input(z.object({
604
- classId: z.string(),
605
- }))
606
- .mutation(async ({ ctx, input }) => {
607
- const { classId } = input;
608
- await prisma.session.deleteMany({
609
- where: {
610
- classId,
611
- },
612
- });
613
- // Create a new session for the invite code
614
- const session = await prisma.session.create({
615
- data: {
616
- id: generateInviteCode(),
617
- classId,
618
- expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours from now
619
- }
620
- });
621
- return {
622
- code: session.id,
623
- };
624
- }),
63
+ .input(z.object({ classId: z.string() }))
64
+ .mutation(({ input }) => createInviteCode(input.classId)),
625
65
  getGrades: protectedClassMemberProcedure
626
- .input(z.object({
627
- classId: z.string(),
628
- userId: z.string(),
629
- }))
630
- .query(async ({ ctx, input }) => {
631
- const { classId, userId } = input;
632
- const isTeacher = await prisma.class.findFirst({
633
- where: {
634
- id: classId,
635
- teachers: {
636
- some: { id: ctx.user?.id }
637
- }
638
- }
639
- });
640
- // If student, only allow viewing their own grades
641
- if (ctx.user?.id !== userId && !isTeacher) {
642
- throw new TRPCError({
643
- code: 'UNAUTHORIZED',
644
- message: 'You can only view your own grades',
645
- });
646
- }
647
- const grades = await prisma.submission.findMany({
648
- where: {
649
- studentId: userId,
650
- assignment: {
651
- classId: classId,
652
- graded: true
653
- }
654
- },
655
- include: {
656
- assignment: {
657
- select: {
658
- id: true,
659
- title: true,
660
- maxGrade: true,
661
- weight: true,
662
- markSchemeId: true,
663
- dueDate: true,
664
- markScheme: {
665
- select: {
666
- structured: true,
667
- }
668
- },
669
- gradingBoundaryId: true,
670
- gradingBoundary: {
671
- select: {
672
- structured: true,
673
- }
674
- },
675
- }
676
- },
677
- }
678
- });
679
- return {
680
- grades,
681
- };
682
- }),
66
+ .input(z.object({ classId: z.string(), userId: z.string() }))
67
+ .query(({ ctx, input }) => getGrades(ctx.user?.id ?? "", input.classId, input.userId)),
683
68
  updateGrade: protectedTeacherProcedure
684
69
  .input(z.object({
685
70
  classId: z.string(),
@@ -687,257 +72,66 @@ export const classRouter = createTRPCRouter({
687
72
  submissionId: z.string(),
688
73
  gradeReceived: z.number().nullable(),
689
74
  }))
690
- .mutation(async ({ ctx, input }) => {
691
- const { classId, assignmentId, submissionId, gradeReceived } = input;
692
- // Update the grade
693
- const updatedSubmission = await prisma.submission.update({
694
- where: {
695
- id: submissionId,
696
- assignmentId: assignmentId,
697
- },
698
- data: {
699
- gradeReceived,
700
- },
701
- include: {
702
- assignment: {
703
- select: {
704
- id: true,
705
- title: true,
706
- maxGrade: true,
707
- weight: true,
708
- }
709
- }
710
- }
711
- });
712
- return updatedSubmission;
713
- }),
75
+ .mutation(({ input }) => updateGrade(input.assignmentId, input.submissionId, input.gradeReceived)),
714
76
  getEvents: protectedTeacherProcedure
715
- .input(z.object({
716
- classId: z.string(),
717
- }))
718
- .query(async ({ ctx, input }) => {
719
- const { classId } = input;
720
- const events = await prisma.event.findMany({
721
- where: {
722
- class: {
723
- id: classId,
724
- }
725
- },
726
- select: {
727
- name: true,
728
- startTime: true,
729
- endTime: true,
730
- }
731
- });
732
- return events;
733
- }),
77
+ .input(z.object({ classId: z.string() }))
78
+ .query(({ input }) => getEvents(input.classId)),
734
79
  listMarkSchemes: protectedClassMemberProcedure
735
- .input(z.object({
736
- classId: z.string(),
737
- }))
738
- .query(async ({ ctx, input }) => {
739
- const { classId } = input;
740
- const markSchemes = await prisma.markScheme.findMany({
741
- where: {
742
- class: {
743
- id: classId,
744
- },
745
- },
746
- });
747
- return markSchemes;
748
- }),
80
+ .input(z.object({ classId: z.string() }))
81
+ .query(({ input }) => listMarkSchemes(input.classId)),
749
82
  createMarkScheme: protectedTeacherProcedure
750
- .input(z.object({
751
- classId: z.string(),
752
- structure: z.string(),
753
- }))
754
- .mutation(async ({ ctx, input }) => {
755
- const { classId, structure } = input;
756
- const validatedStructure = structure.replace(/\\n/g, '\n');
757
- const markScheme = await prisma.markScheme.create({
758
- data: {
759
- class: {
760
- connect: {
761
- id: classId,
762
- },
763
- },
764
- structured: validatedStructure,
765
- },
766
- });
767
- return markScheme;
768
- }),
83
+ .input(z.object({ classId: z.string(), structure: z.string() }))
84
+ .mutation(({ input }) => createMarkScheme(input.classId, input.structure)),
769
85
  updateMarkScheme: protectedTeacherProcedure
770
86
  .input(z.object({
771
87
  classId: z.string(),
772
88
  markSchemeId: z.string(),
773
89
  structure: z.string(),
774
90
  }))
775
- .mutation(async ({ ctx, input }) => {
776
- const { classId, markSchemeId, structure } = input;
777
- const validatedStructure = structure.replace(/\\n/g, '\n');
778
- const markScheme = await prisma.markScheme.update({
779
- where: { id: markSchemeId },
780
- data: {
781
- class: {
782
- connect: {
783
- id: classId,
784
- },
785
- },
786
- structured: validatedStructure,
787
- },
788
- });
789
- return markScheme;
790
- }),
91
+ .mutation(({ input }) => updateMarkScheme(input.markSchemeId, input.classId, input.structure)),
791
92
  deleteMarkScheme: protectedTeacherProcedure
792
- .input(z.object({
793
- classId: z.string(),
794
- markSchemeId: z.string(),
795
- }))
796
- .mutation(async ({ ctx, input }) => {
797
- const { classId, markSchemeId } = input;
798
- const markScheme = await prisma.markScheme.delete({
799
- where: { id: markSchemeId },
800
- });
801
- return markScheme;
802
- }),
93
+ .input(z.object({ classId: z.string(), markSchemeId: z.string() }))
94
+ .mutation(({ input }) => deleteMarkScheme(input.markSchemeId)),
803
95
  listGradingBoundaries: protectedClassMemberProcedure
804
- .input(z.object({
805
- classId: z.string(),
806
- }))
807
- .query(async ({ ctx, input }) => {
808
- const { classId } = input;
809
- const gradingBoundaries = await prisma.gradingBoundary.findMany({
810
- where: {
811
- class: {
812
- id: classId,
813
- },
814
- },
815
- });
816
- return gradingBoundaries;
817
- }),
96
+ .input(z.object({ classId: z.string() }))
97
+ .query(({ input }) => listGradingBoundaries(input.classId)),
818
98
  createGradingBoundary: protectedTeacherProcedure
819
- .input(z.object({
820
- classId: z.string(),
821
- structure: z.string(),
822
- }))
823
- .mutation(async ({ ctx, input }) => {
824
- const { classId, structure } = input;
825
- const validatedStructure = structure.replace(/\\n/g, '\n');
826
- const gradingBoundary = await prisma.gradingBoundary.create({
827
- data: {
828
- class: {
829
- connect: {
830
- id: classId,
831
- },
832
- },
833
- structured: validatedStructure,
834
- },
835
- });
836
- return gradingBoundary;
837
- }),
99
+ .input(z.object({ classId: z.string(), structure: z.string() }))
100
+ .mutation(({ input }) => createGradingBoundary(input.classId, input.structure)),
838
101
  updateGradingBoundary: protectedTeacherProcedure
839
102
  .input(z.object({
840
103
  classId: z.string(),
841
104
  gradingBoundaryId: z.string(),
842
105
  structure: z.string(),
843
106
  }))
844
- .mutation(async ({ ctx, input }) => {
845
- const { classId, gradingBoundaryId, structure } = input;
846
- const validatedStructure = structure.replace(/\\n/g, '\n');
847
- const gradingBoundary = await prisma.gradingBoundary.update({
848
- where: { id: gradingBoundaryId },
849
- data: {
850
- class: {
851
- connect: {
852
- id: classId,
853
- },
854
- },
855
- structured: validatedStructure,
856
- },
857
- });
858
- return gradingBoundary;
859
- }),
107
+ .mutation(({ input }) => updateGradingBoundary(input.gradingBoundaryId, input.classId, input.structure)),
860
108
  deleteGradingBoundary: protectedTeacherProcedure
861
- .input(z.object({
862
- classId: z.string(),
863
- gradingBoundaryId: z.string(),
864
- }))
865
- .mutation(async ({ ctx, input }) => {
866
- const { classId, gradingBoundaryId } = input;
867
- const gradingBoundary = await prisma.gradingBoundary.delete({
868
- where: { id: gradingBoundaryId },
869
- });
870
- return gradingBoundary;
871
- }),
109
+ .input(z.object({ classId: z.string(), gradingBoundaryId: z.string() }))
110
+ .mutation(({ input }) => deleteGradingBoundary(input.gradingBoundaryId)),
872
111
  getSyllabus: protectedClassMemberProcedure
873
- .input(z.object({
874
- classId: z.string(),
875
- }))
876
- .query(async ({ input }) => {
877
- const { classId } = input;
878
- const syllabus = (await prisma.class.findUnique({
879
- where: {
880
- id: classId,
881
- },
882
- }))?.syllabus;
883
- const markSchemes = await prisma.markScheme.findMany({
884
- where: {
885
- classId,
886
- }
887
- });
888
- const gradingBoundaries = await prisma.gradingBoundary.findMany({
889
- where: {
890
- classId,
891
- }
892
- });
893
- return { syllabus, gradingBoundaries, markSchemes };
894
- }),
112
+ .input(z.object({ classId: z.string() }))
113
+ .query(({ input }) => getSyllabus(input.classId)),
895
114
  updateSyllabus: protectedTeacherProcedure
896
- .input(z.object({
897
- classId: z.string(),
898
- contents: z.string(),
899
- }))
900
- .mutation(async ({ input }) => {
901
- const { contents, classId } = input;
902
- if (!contents)
903
- throw new TRPCError({
904
- code: 'BAD_REQUEST',
905
- message: "Missing key contents",
906
- });
907
- const updated = await prisma.class.update({
908
- where: {
909
- id: classId
910
- },
911
- data: {
912
- syllabus: contents,
913
- }
914
- });
915
- return updated;
916
- }),
917
- // Lab Management Endpoints (Assignment-based)
115
+ .input(z.object({ classId: z.string(), contents: z.string() }))
116
+ .mutation(({ input }) => updateSyllabus(input.classId, input.contents)),
918
117
  listLabDrafts: protectedTeacherProcedure
919
- .input(z.object({
920
- classId: z.string(),
921
- }))
922
- .query(async ({ ctx, input }) => {
923
- const { classId } = input;
924
- const labDrafts = await prisma.assignment.findMany({
925
- where: {
926
- classId: classId,
927
- teacherId: ctx.user?.id,
928
- inProgress: true,
929
- },
930
- orderBy: {
931
- modifiedAt: 'desc',
932
- },
933
- });
934
- return labDrafts;
935
- }),
118
+ .input(z.object({ classId: z.string() }))
119
+ .query(({ ctx, input }) => listLabDrafts(input.classId, ctx.user?.id ?? "")),
936
120
  createLabDraft: protectedTeacherProcedure
937
121
  .input(z.object({
938
122
  classId: z.string(),
939
123
  title: z.string(),
940
- type: z.enum(['LAB', 'HOMEWORK', 'QUIZ', 'TEST', 'PROJECT', 'ESSAY', 'DISCUSSION', 'PRESENTATION', 'OTHER']),
124
+ type: z.enum([
125
+ "LAB",
126
+ "HOMEWORK",
127
+ "QUIZ",
128
+ "TEST",
129
+ "PROJECT",
130
+ "ESSAY",
131
+ "DISCUSSION",
132
+ "PRESENTATION",
133
+ "OTHER",
134
+ ]),
941
135
  instructions: z.string(),
942
136
  dueDate: z.date().optional(),
943
137
  maxGrade: z.number().optional(),
@@ -947,26 +141,9 @@ export const classRouter = createTRPCRouter({
947
141
  markSchemeId: z.string().optional(),
948
142
  gradingBoundaryId: z.string().optional(),
949
143
  }))
950
- .mutation(async ({ ctx, input }) => {
144
+ .mutation(({ ctx, input }) => {
951
145
  const { classId, ...draftData } = input;
952
- const labDraft = await prisma.assignment.create({
953
- data: {
954
- classId: classId,
955
- teacherId: ctx.user?.id,
956
- inProgress: true,
957
- graded: draftData.graded ?? false,
958
- maxGrade: draftData.maxGrade ?? 0,
959
- weight: draftData.weight ?? 1,
960
- dueDate: draftData.dueDate || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // Default 1 week from now
961
- title: draftData.title,
962
- instructions: draftData.instructions,
963
- type: draftData.type,
964
- ...(draftData.sectionId && { sectionId: draftData.sectionId }),
965
- ...(draftData.markSchemeId && { markSchemeId: draftData.markSchemeId }),
966
- ...(draftData.gradingBoundaryId && { gradingBoundaryId: draftData.gradingBoundaryId }),
967
- },
968
- });
969
- return labDraft;
146
+ return createLabDraft(classId, ctx.user?.id ?? "", draftData);
970
147
  }),
971
148
  updateLabDraft: protectedTeacherProcedure
972
149
  .input(z.object({
@@ -982,47 +159,13 @@ export const classRouter = createTRPCRouter({
982
159
  markSchemeId: z.string().optional(),
983
160
  gradingBoundaryId: z.string().optional(),
984
161
  }))
985
- .mutation(async ({ ctx, input }) => {
162
+ .mutation(({ ctx, input }) => {
986
163
  const { classId, draftId, ...updateData } = input;
987
- const labDraft = await prisma.assignment.update({
988
- where: {
989
- id: draftId,
990
- classId: classId,
991
- teacherId: ctx.user?.id,
992
- inProgress: true,
993
- },
994
- data: {
995
- ...(updateData.title && { title: updateData.title }),
996
- ...(updateData.instructions && { instructions: updateData.instructions }),
997
- ...(updateData.dueDate && { dueDate: updateData.dueDate }),
998
- ...(updateData.maxGrade !== undefined && { maxGrade: updateData.maxGrade }),
999
- ...(updateData.weight !== undefined && { weight: updateData.weight }),
1000
- ...(updateData.graded !== undefined && { graded: updateData.graded }),
1001
- ...(updateData.sectionId !== undefined && { sectionId: updateData.sectionId }),
1002
- ...(updateData.markSchemeId !== undefined && { markSchemeId: updateData.markSchemeId }),
1003
- ...(updateData.gradingBoundaryId !== undefined && { gradingBoundaryId: updateData.gradingBoundaryId }),
1004
- modifiedAt: new Date(),
1005
- },
1006
- });
1007
- return labDraft;
164
+ return updateLabDraft(classId, ctx.user?.id ?? "", draftId, updateData);
1008
165
  }),
1009
166
  deleteLabDraft: protectedTeacherProcedure
1010
- .input(z.object({
1011
- classId: z.string(),
1012
- draftId: z.string(),
1013
- }))
1014
- .mutation(async ({ ctx, input }) => {
1015
- const { classId, draftId } = input;
1016
- const labDraft = await prisma.assignment.delete({
1017
- where: {
1018
- id: draftId,
1019
- classId: classId,
1020
- teacherId: ctx.user?.id,
1021
- inProgress: true,
1022
- },
1023
- });
1024
- return labDraft;
1025
- }),
167
+ .input(z.object({ classId: z.string(), draftId: z.string() }))
168
+ .mutation(({ ctx, input }) => deleteLabDraft(input.classId, ctx.user?.id ?? "", input.draftId)),
1026
169
  publishLabDraft: protectedTeacherProcedure
1027
170
  .input(z.object({
1028
171
  classId: z.string(),
@@ -1032,136 +175,23 @@ export const classRouter = createTRPCRouter({
1032
175
  weight: z.number().optional(),
1033
176
  graded: z.boolean().optional(),
1034
177
  }))
1035
- .mutation(async ({ ctx, input }) => {
178
+ .mutation(({ ctx, input }) => {
1036
179
  const { classId, draftId, ...publishData } = input;
1037
- // Get the lab draft
1038
- const labDraft = await prisma.assignment.findUnique({
1039
- where: {
1040
- id: draftId,
1041
- classId: classId,
1042
- teacherId: ctx.user?.id,
1043
- inProgress: true,
1044
- },
1045
- });
1046
- if (!labDraft) {
1047
- throw new TRPCError({
1048
- code: 'NOT_FOUND',
1049
- message: 'Lab draft not found',
1050
- });
1051
- }
1052
- // Publish the draft by updating it to not be in progress
1053
- const publishedAssignment = await prisma.assignment.update({
1054
- where: { id: draftId },
1055
- data: {
1056
- inProgress: false,
1057
- dueDate: publishData.dueDate || labDraft.dueDate,
1058
- maxGrade: publishData.maxGrade || labDraft.maxGrade || 100,
1059
- weight: publishData.weight || labDraft.weight || 1,
1060
- graded: publishData.graded !== undefined ? publishData.graded : true,
1061
- modifiedAt: new Date(),
1062
- },
1063
- });
1064
- return publishedAssignment;
180
+ return publishLabDraft(classId, ctx.user?.id ?? "", draftId, publishData);
1065
181
  }),
1066
182
  getFiles: protectedClassMemberProcedure
183
+ .input(z.object({ classId: z.string() }))
184
+ .query(({ input }) => getFiles(input.classId)),
185
+ exportClass: protectedTeacherProcedure
186
+ .input(z.object({ classId: z.string() }))
187
+ .mutation(({ ctx, input }) => exportClass(input.classId, ctx.user?.id ?? "")),
188
+ importClass: protectedTeacherProcedure
1067
189
  .input(z.object({
1068
190
  classId: z.string(),
191
+ year: z.number(),
192
+ classData: z.any(),
1069
193
  }))
1070
- .query(async ({ ctx, input }) => {
1071
- const { classId } = input;
1072
- // Get all assignments with their files and submissions
1073
- const assignments = await prisma.assignment.findMany({
1074
- where: {
1075
- classId: classId,
1076
- },
1077
- include: {
1078
- attachments: {
1079
- select: {
1080
- id: true,
1081
- name: true,
1082
- type: true,
1083
- size: true,
1084
- path: true,
1085
- thumbnailId: true,
1086
- uploadedAt: true,
1087
- user: {
1088
- select: {
1089
- id: true,
1090
- username: true,
1091
- },
1092
- },
1093
- },
1094
- },
1095
- submissions: {
1096
- include: {
1097
- attachments: {
1098
- select: {
1099
- id: true,
1100
- name: true,
1101
- type: true,
1102
- size: true,
1103
- path: true,
1104
- thumbnailId: true,
1105
- uploadedAt: true,
1106
- user: {
1107
- select: {
1108
- id: true,
1109
- username: true,
1110
- },
1111
- },
1112
- },
1113
- },
1114
- annotations: {
1115
- select: {
1116
- id: true,
1117
- name: true,
1118
- type: true,
1119
- size: true,
1120
- path: true,
1121
- thumbnailId: true,
1122
- uploadedAt: true,
1123
- user: {
1124
- select: {
1125
- id: true,
1126
- username: true,
1127
- },
1128
- },
1129
- },
1130
- },
1131
- student: {
1132
- select: {
1133
- id: true,
1134
- username: true,
1135
- },
1136
- },
1137
- },
1138
- },
1139
- teacher: {
1140
- select: {
1141
- id: true,
1142
- username: true,
1143
- },
1144
- },
1145
- },
1146
- orderBy: {
1147
- createdAt: 'desc',
1148
- },
1149
- });
1150
- // Organize files by assignment structure
1151
- const organizedFiles = assignments.map(assignment => ({
1152
- id: assignment.id,
1153
- title: assignment.title,
1154
- teacher: assignment.teacher,
1155
- teacherAttachments: assignment.attachments,
1156
- students: assignment.submissions.map(submission => ({
1157
- id: submission.student.id,
1158
- username: submission.student.username,
1159
- attachments: submission.attachments,
1160
- annotations: submission.annotations,
1161
- })),
1162
- }));
1163
- return organizedFiles;
1164
- }),
194
+ .mutation(({ ctx, input }) => importClass(input.classId, ctx.user?.id ?? "", input.year, input.classData)),
1165
195
  });
1166
196
  //# sourceMappingURL=class.js.map
1167
- //# debugId=4de0a549-5566-5b60-aa1d-acdb528cce7a
197
+ //# debugId=43c06b92-74d9-5f52-a500-f14b511e48a2