@studious-lms/server 1.2.52 → 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 (480) 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 +36 -94
  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 +1399 -1271
  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 +140 -68
  143. package/dist/routers/class.d.ts.map +1 -1
  144. package/dist/routers/class.js +82 -1051
  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/aiNewtonChat.d.ts.map +1 -1
  200. package/dist/server/pipelines/aiNewtonChat.js +8 -3
  201. package/dist/server/pipelines/aiNewtonChat.js.map +1 -1
  202. package/dist/server/pipelines/gradeWorksheet.d.ts +6 -6
  203. package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -1
  204. package/dist/server/pipelines/gradeWorksheet.js +12 -5
  205. package/dist/server/pipelines/gradeWorksheet.js.map +1 -1
  206. package/dist/services/agenda.d.ts +100 -0
  207. package/dist/services/agenda.d.ts.map +1 -0
  208. package/dist/services/agenda.js +21 -0
  209. package/dist/services/agenda.js.map +1 -0
  210. package/dist/services/announcement.d.ts +135 -0
  211. package/dist/services/announcement.d.ts.map +1 -0
  212. package/dist/services/announcement.js +223 -0
  213. package/dist/services/announcement.js.map +1 -0
  214. package/dist/services/assignment.d.ts +1462 -0
  215. package/dist/services/assignment.d.ts.map +1 -0
  216. package/dist/services/assignment.js +898 -0
  217. package/dist/services/assignment.js.map +1 -0
  218. package/dist/services/attendance.d.ts +93 -0
  219. package/dist/services/attendance.d.ts.map +1 -0
  220. package/dist/services/attendance.js +61 -0
  221. package/dist/services/attendance.js.map +1 -0
  222. package/dist/services/auth.d.ts +68 -0
  223. package/dist/services/auth.d.ts.map +1 -0
  224. package/dist/services/auth.js +218 -0
  225. package/dist/services/auth.js.map +1 -0
  226. package/dist/services/class.d.ts +621 -0
  227. package/dist/services/class.d.ts.map +1 -0
  228. package/dist/services/class.js +474 -0
  229. package/dist/services/class.js.map +1 -0
  230. package/dist/services/comment.d.ts +100 -0
  231. package/dist/services/comment.d.ts.map +1 -0
  232. package/dist/services/comment.js +83 -0
  233. package/dist/services/comment.js.map +1 -0
  234. package/dist/services/conversation.d.ts +159 -0
  235. package/dist/services/conversation.d.ts.map +1 -0
  236. package/dist/services/conversation.js +138 -0
  237. package/dist/services/conversation.js.map +1 -0
  238. package/dist/services/event.d.ts +216 -0
  239. package/dist/services/event.d.ts.map +1 -0
  240. package/dist/services/event.js +168 -0
  241. package/dist/services/event.js.map +1 -0
  242. package/dist/services/file.d.ts +74 -0
  243. package/dist/services/file.d.ts.map +1 -0
  244. package/dist/services/file.js +133 -0
  245. package/dist/services/file.js.map +1 -0
  246. package/dist/services/folder.d.ts +239 -0
  247. package/dist/services/folder.d.ts.map +1 -0
  248. package/dist/services/folder.js +248 -0
  249. package/dist/services/folder.js.map +1 -0
  250. package/dist/services/labChat.d.ts +165 -0
  251. package/dist/services/labChat.d.ts.map +1 -0
  252. package/dist/services/labChat.js +289 -0
  253. package/dist/services/labChat.js.map +1 -0
  254. package/dist/services/marketing.d.ts +50 -0
  255. package/dist/services/marketing.d.ts.map +1 -0
  256. package/dist/services/marketing.js +32 -0
  257. package/dist/services/marketing.js.map +1 -0
  258. package/dist/services/message.d.ts +95 -0
  259. package/dist/services/message.d.ts.map +1 -0
  260. package/dist/services/message.js +350 -0
  261. package/dist/services/message.js.map +1 -0
  262. package/dist/services/newtonChat.d.ts +22 -0
  263. package/dist/services/newtonChat.d.ts.map +1 -0
  264. package/dist/services/newtonChat.js +174 -0
  265. package/dist/services/newtonChat.js.map +1 -0
  266. package/dist/services/notification.d.ts +65 -0
  267. package/dist/services/notification.d.ts.map +1 -0
  268. package/dist/services/notification.js +33 -0
  269. package/dist/services/notification.js.map +1 -0
  270. package/dist/services/section.d.ts +53 -0
  271. package/dist/services/section.d.ts.map +1 -0
  272. package/dist/services/section.js +199 -0
  273. package/dist/services/section.js.map +1 -0
  274. package/dist/services/user.d.ts +48 -0
  275. package/dist/services/user.d.ts.map +1 -0
  276. package/dist/services/user.js +141 -0
  277. package/dist/services/user.js.map +1 -0
  278. package/dist/services/worksheet.d.ts +239 -0
  279. package/dist/services/worksheet.d.ts.map +1 -0
  280. package/dist/services/worksheet.js +235 -0
  281. package/dist/services/worksheet.js.map +1 -0
  282. package/dist/utils/aiUser.d.ts +1 -3
  283. package/dist/utils/aiUser.d.ts.map +1 -1
  284. package/dist/utils/aiUser.js +6 -5
  285. package/dist/utils/aiUser.js.map +1 -1
  286. package/dist/utils/email.d.ts +3 -0
  287. package/dist/utils/email.d.ts.map +1 -1
  288. package/dist/utils/email.js +7 -4
  289. package/dist/utils/email.js.map +1 -1
  290. package/dist/utils/generateInviteCode.d.ts +1 -2
  291. package/dist/utils/generateInviteCode.d.ts.map +1 -1
  292. package/dist/utils/generateInviteCode.js +3 -4
  293. package/dist/utils/generateInviteCode.js.map +1 -1
  294. package/dist/utils/inference.d.ts +3 -0
  295. package/dist/utils/inference.d.ts.map +1 -1
  296. package/dist/utils/inference.js +7 -4
  297. package/dist/utils/inference.js.map +1 -1
  298. package/dist/utils/logger.d.ts +3 -0
  299. package/dist/utils/logger.d.ts.map +1 -1
  300. package/dist/utils/logger.js +5 -2
  301. package/dist/utils/logger.js.map +1 -1
  302. package/dist/utils/prismaErrorHandler.d.ts.map +1 -1
  303. package/dist/utils/prismaErrorHandler.js +5 -2
  304. package/dist/utils/prismaErrorHandler.js.map +1 -1
  305. package/dist/utils/prismaWrapper.d.ts +1 -0
  306. package/dist/utils/prismaWrapper.d.ts.map +1 -1
  307. package/dist/utils/prismaWrapper.js +6 -2
  308. package/dist/utils/prismaWrapper.js.map +1 -1
  309. package/docker-compose.yml +5 -0
  310. package/package.json +4 -3
  311. package/src/index.ts +119 -12
  312. package/src/lib/config/env.ts +6 -0
  313. package/src/lib/fileUpload.ts +0 -1
  314. package/src/lib/googleCloudStorage.ts +17 -0
  315. package/src/lib/pusher.ts +5 -1
  316. package/src/lib/redis.ts +56 -0
  317. package/src/lib/thumbnailGenerator.ts +170 -168
  318. package/src/middleware/auth.ts +83 -136
  319. package/src/models/agenda.ts +46 -0
  320. package/src/models/announcement.ts +134 -0
  321. package/src/models/assignment.ts +322 -0
  322. package/src/models/attendance.ts +208 -0
  323. package/src/models/auth.ts +247 -0
  324. package/src/models/class.ts +598 -0
  325. package/src/models/comment.ts +152 -0
  326. package/src/models/conversation.ts +200 -0
  327. package/src/models/event.ts +177 -0
  328. package/src/models/file.ts +129 -0
  329. package/src/models/folder.ts +225 -0
  330. package/src/models/labChat.ts +213 -0
  331. package/src/models/marketing.ts +45 -0
  332. package/src/models/message.ts +153 -0
  333. package/src/models/newtonChat.ts +70 -0
  334. package/src/models/notification.ts +54 -0
  335. package/src/models/section.ts +98 -0
  336. package/src/models/user.ts +47 -0
  337. package/src/models/worksheet.ts +294 -0
  338. package/src/{server/pipelines → pipelines}/aiLabChat.ts +11 -7
  339. package/src/{server/pipelines → pipelines}/aiNewtonChat.ts +15 -6
  340. package/src/{server/pipelines → pipelines}/gradeWorksheet.ts +25 -14
  341. package/src/routers/agenda.ts +3 -66
  342. package/src/routers/announcement.ts +54 -495
  343. package/src/routers/assignment.ts +126 -2018
  344. package/src/routers/attendance.ts +15 -276
  345. package/src/routers/auth.ts +79 -442
  346. package/src/routers/class.ts +263 -1186
  347. package/src/routers/comment.ts +61 -288
  348. package/src/routers/conversation.ts +51 -360
  349. package/src/routers/event.ts +50 -481
  350. package/src/routers/file.ts +45 -368
  351. package/src/routers/folder.ts +107 -836
  352. package/src/routers/labChat.ts +29 -605
  353. package/src/routers/marketing.ts +35 -77
  354. package/src/routers/message.ts +45 -571
  355. package/src/routers/newtonChat.ts +17 -278
  356. package/src/routers/notifications.ts +32 -82
  357. package/src/routers/section.ts +46 -330
  358. package/src/routers/user.ts +49 -227
  359. package/src/routers/worksheet.ts +215 -503
  360. package/src/services/agenda.ts +21 -0
  361. package/src/services/announcement.ts +290 -0
  362. package/src/services/assignment.ts +1198 -0
  363. package/src/services/attendance.ts +85 -0
  364. package/src/services/auth.ts +277 -0
  365. package/src/services/class.ts +622 -0
  366. package/src/services/comment.ts +106 -0
  367. package/src/services/conversation.ts +213 -0
  368. package/src/services/event.ts +231 -0
  369. package/src/services/file.ts +167 -0
  370. package/src/services/folder.ts +316 -0
  371. package/src/services/labChat.ts +352 -0
  372. package/src/services/marketing.ts +57 -0
  373. package/src/services/message.ts +461 -0
  374. package/src/services/newtonChat.ts +222 -0
  375. package/src/services/notification.ts +50 -0
  376. package/src/services/section.ts +283 -0
  377. package/src/services/user.ts +172 -0
  378. package/src/services/worksheet.ts +358 -0
  379. package/src/utils/aiUser.ts +4 -3
  380. package/src/utils/email.ts +5 -3
  381. package/src/utils/generateInviteCode.ts +1 -3
  382. package/src/utils/inference.ts +5 -2
  383. package/src/utils/logger.ts +3 -1
  384. package/src/utils/prismaErrorHandler.ts +3 -0
  385. package/src/utils/prismaWrapper.ts +4 -0
  386. package/tests/globalSetup.ts +62 -0
  387. package/tests/helpers.ts +22 -0
  388. package/tests/middleware/security.test.ts +42 -0
  389. package/tests/routers/agenda.test.ts +138 -0
  390. package/tests/routers/announcement.test.ts +490 -0
  391. package/tests/routers/assignment.test.ts +837 -0
  392. package/tests/{attendance.test.ts → routers/attendance.test.ts} +6 -14
  393. package/tests/routers/auth.test.ts +171 -0
  394. package/tests/{class.test.ts → routers/class.test.ts} +131 -85
  395. package/tests/routers/comment.test.ts +126 -0
  396. package/tests/routers/conversation.test.ts +145 -0
  397. package/tests/{event.test.ts → routers/event.test.ts} +93 -32
  398. package/tests/routers/folder.test.ts +178 -0
  399. package/tests/routers/labChat.test.ts +115 -0
  400. package/tests/routers/marketing.test.ts +59 -0
  401. package/tests/routers/message.test.ts +123 -0
  402. package/tests/routers/notification.test.ts +69 -0
  403. package/tests/{section.test.ts → routers/section.test.ts} +5 -13
  404. package/tests/server/rateLimit.test.ts +73 -0
  405. package/tests/setup.ts +18 -92
  406. package/tests/user.test.ts +9 -31
  407. package/tests/utils/aiUser.test.ts +22 -0
  408. package/tests/utils/generateInviteCode.test.ts +24 -0
  409. package/tests/utils/logger.test.ts +74 -0
  410. package/tests/utils/prismaErrorHandler.test.ts +101 -0
  411. package/tests/utils/prismaWrapper.test.ts +82 -0
  412. package/tests/worksheet.test.ts +181 -0
  413. package/vitest.config.ts +6 -3
  414. package/vitest.unit.config.ts +21 -0
  415. package/TODO.md +0 -2
  416. package/coverage/base.css +0 -224
  417. package/coverage/block-navigation.js +0 -87
  418. package/coverage/clover.xml +0 -12110
  419. package/coverage/coverage-final.json +0 -44
  420. package/coverage/favicon.png +0 -0
  421. package/coverage/index.html +0 -221
  422. package/coverage/prettify.css +0 -1
  423. package/coverage/prettify.js +0 -2
  424. package/coverage/server/index.html +0 -116
  425. package/coverage/server/src/exportType.ts.html +0 -109
  426. package/coverage/server/src/index.html +0 -161
  427. package/coverage/server/src/index.ts.html +0 -1702
  428. package/coverage/server/src/instrument.ts.html +0 -130
  429. package/coverage/server/src/lib/config/env.ts.html +0 -448
  430. package/coverage/server/src/lib/config/index.html +0 -116
  431. package/coverage/server/src/lib/fileUpload.ts.html +0 -1138
  432. package/coverage/server/src/lib/googleCloudStorage.ts.html +0 -334
  433. package/coverage/server/src/lib/index.html +0 -206
  434. package/coverage/server/src/lib/jsonConversion.ts.html +0 -2323
  435. package/coverage/server/src/lib/jsonStyles.ts.html +0 -193
  436. package/coverage/server/src/lib/notificationHandler.ts.html +0 -193
  437. package/coverage/server/src/lib/pusher.ts.html +0 -121
  438. package/coverage/server/src/lib/thumbnailGenerator.ts.html +0 -592
  439. package/coverage/server/src/middleware/auth.ts.html +0 -646
  440. package/coverage/server/src/middleware/index.html +0 -146
  441. package/coverage/server/src/middleware/logging.ts.html +0 -244
  442. package/coverage/server/src/middleware/security.ts.html +0 -271
  443. package/coverage/server/src/routers/_app.ts.html +0 -232
  444. package/coverage/server/src/routers/agenda.ts.html +0 -319
  445. package/coverage/server/src/routers/announcement.ts.html +0 -3481
  446. package/coverage/server/src/routers/assignment.ts.html +0 -7633
  447. package/coverage/server/src/routers/attendance.ts.html +0 -1030
  448. package/coverage/server/src/routers/auth.ts.html +0 -1081
  449. package/coverage/server/src/routers/class.ts.html +0 -3535
  450. package/coverage/server/src/routers/comment.ts.html +0 -991
  451. package/coverage/server/src/routers/conversation.ts.html +0 -982
  452. package/coverage/server/src/routers/event.ts.html +0 -1609
  453. package/coverage/server/src/routers/file.ts.html +0 -1144
  454. package/coverage/server/src/routers/folder.ts.html +0 -2797
  455. package/coverage/server/src/routers/index.html +0 -386
  456. package/coverage/server/src/routers/labChat.ts.html +0 -3073
  457. package/coverage/server/src/routers/marketing.ts.html +0 -340
  458. package/coverage/server/src/routers/message.ts.html +0 -1912
  459. package/coverage/server/src/routers/notifications.ts.html +0 -364
  460. package/coverage/server/src/routers/section.ts.html +0 -1120
  461. package/coverage/server/src/routers/user.ts.html +0 -862
  462. package/coverage/server/src/routers/worksheet.ts.html +0 -1729
  463. package/coverage/server/src/trpc.ts.html +0 -397
  464. package/coverage/server/src/types/index.html +0 -116
  465. package/coverage/server/src/types/trpc.ts.html +0 -127
  466. package/coverage/server/src/utils/aiUser.ts.html +0 -280
  467. package/coverage/server/src/utils/email.ts.html +0 -121
  468. package/coverage/server/src/utils/generateInviteCode.ts.html +0 -106
  469. package/coverage/server/src/utils/index.html +0 -206
  470. package/coverage/server/src/utils/inference.ts.html +0 -709
  471. package/coverage/server/src/utils/logger.ts.html +0 -664
  472. package/coverage/server/src/utils/prismaErrorHandler.ts.html +0 -907
  473. package/coverage/server/src/utils/prismaWrapper.ts.html +0 -355
  474. package/coverage/server/vitest.config.ts.html +0 -196
  475. package/coverage/sort-arrow-sprite.png +0 -0
  476. package/coverage/sorter.js +0 -210
  477. package/src/lib/notificationHandler.ts +0 -36
  478. package/tests/announcement.test.ts +0 -164
  479. package/tests/assignment.test.ts +0 -296
  480. 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]="767877f8-1e76-552f-92f2-c3b39f1302ec")}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,354 +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
- markScheme: {
664
- select: {
665
- structured: true,
666
- }
667
- },
668
- gradingBoundaryId: true,
669
- gradingBoundary: {
670
- select: {
671
- structured: true,
672
- }
673
- },
674
- }
675
- },
676
- }
677
- });
678
- return {
679
- grades,
680
- };
681
- }),
66
+ .input(z.object({ classId: z.string(), userId: z.string() }))
67
+ .query(({ ctx, input }) => getGrades(ctx.user?.id ?? "", input.classId, input.userId)),
682
68
  updateGrade: protectedTeacherProcedure
683
69
  .input(z.object({
684
70
  classId: z.string(),
@@ -686,257 +72,66 @@ export const classRouter = createTRPCRouter({
686
72
  submissionId: z.string(),
687
73
  gradeReceived: z.number().nullable(),
688
74
  }))
689
- .mutation(async ({ ctx, input }) => {
690
- const { classId, assignmentId, submissionId, gradeReceived } = input;
691
- // Update the grade
692
- const updatedSubmission = await prisma.submission.update({
693
- where: {
694
- id: submissionId,
695
- assignmentId: assignmentId,
696
- },
697
- data: {
698
- gradeReceived,
699
- },
700
- include: {
701
- assignment: {
702
- select: {
703
- id: true,
704
- title: true,
705
- maxGrade: true,
706
- weight: true,
707
- }
708
- }
709
- }
710
- });
711
- return updatedSubmission;
712
- }),
75
+ .mutation(({ input }) => updateGrade(input.assignmentId, input.submissionId, input.gradeReceived)),
713
76
  getEvents: protectedTeacherProcedure
714
- .input(z.object({
715
- classId: z.string(),
716
- }))
717
- .query(async ({ ctx, input }) => {
718
- const { classId } = input;
719
- const events = await prisma.event.findMany({
720
- where: {
721
- class: {
722
- id: classId,
723
- }
724
- },
725
- select: {
726
- name: true,
727
- startTime: true,
728
- endTime: true,
729
- }
730
- });
731
- return events;
732
- }),
77
+ .input(z.object({ classId: z.string() }))
78
+ .query(({ input }) => getEvents(input.classId)),
733
79
  listMarkSchemes: protectedClassMemberProcedure
734
- .input(z.object({
735
- classId: z.string(),
736
- }))
737
- .query(async ({ ctx, input }) => {
738
- const { classId } = input;
739
- const markSchemes = await prisma.markScheme.findMany({
740
- where: {
741
- class: {
742
- id: classId,
743
- },
744
- },
745
- });
746
- return markSchemes;
747
- }),
80
+ .input(z.object({ classId: z.string() }))
81
+ .query(({ input }) => listMarkSchemes(input.classId)),
748
82
  createMarkScheme: protectedTeacherProcedure
749
- .input(z.object({
750
- classId: z.string(),
751
- structure: z.string(),
752
- }))
753
- .mutation(async ({ ctx, input }) => {
754
- const { classId, structure } = input;
755
- const validatedStructure = structure.replace(/\\n/g, '\n');
756
- const markScheme = await prisma.markScheme.create({
757
- data: {
758
- class: {
759
- connect: {
760
- id: classId,
761
- },
762
- },
763
- structured: validatedStructure,
764
- },
765
- });
766
- return markScheme;
767
- }),
83
+ .input(z.object({ classId: z.string(), structure: z.string() }))
84
+ .mutation(({ input }) => createMarkScheme(input.classId, input.structure)),
768
85
  updateMarkScheme: protectedTeacherProcedure
769
86
  .input(z.object({
770
87
  classId: z.string(),
771
88
  markSchemeId: z.string(),
772
89
  structure: z.string(),
773
90
  }))
774
- .mutation(async ({ ctx, input }) => {
775
- const { classId, markSchemeId, structure } = input;
776
- const validatedStructure = structure.replace(/\\n/g, '\n');
777
- const markScheme = await prisma.markScheme.update({
778
- where: { id: markSchemeId },
779
- data: {
780
- class: {
781
- connect: {
782
- id: classId,
783
- },
784
- },
785
- structured: validatedStructure,
786
- },
787
- });
788
- return markScheme;
789
- }),
91
+ .mutation(({ input }) => updateMarkScheme(input.markSchemeId, input.classId, input.structure)),
790
92
  deleteMarkScheme: protectedTeacherProcedure
791
- .input(z.object({
792
- classId: z.string(),
793
- markSchemeId: z.string(),
794
- }))
795
- .mutation(async ({ ctx, input }) => {
796
- const { classId, markSchemeId } = input;
797
- const markScheme = await prisma.markScheme.delete({
798
- where: { id: markSchemeId },
799
- });
800
- return markScheme;
801
- }),
93
+ .input(z.object({ classId: z.string(), markSchemeId: z.string() }))
94
+ .mutation(({ input }) => deleteMarkScheme(input.markSchemeId)),
802
95
  listGradingBoundaries: protectedClassMemberProcedure
803
- .input(z.object({
804
- classId: z.string(),
805
- }))
806
- .query(async ({ ctx, input }) => {
807
- const { classId } = input;
808
- const gradingBoundaries = await prisma.gradingBoundary.findMany({
809
- where: {
810
- class: {
811
- id: classId,
812
- },
813
- },
814
- });
815
- return gradingBoundaries;
816
- }),
96
+ .input(z.object({ classId: z.string() }))
97
+ .query(({ input }) => listGradingBoundaries(input.classId)),
817
98
  createGradingBoundary: protectedTeacherProcedure
818
- .input(z.object({
819
- classId: z.string(),
820
- structure: z.string(),
821
- }))
822
- .mutation(async ({ ctx, input }) => {
823
- const { classId, structure } = input;
824
- const validatedStructure = structure.replace(/\\n/g, '\n');
825
- const gradingBoundary = await prisma.gradingBoundary.create({
826
- data: {
827
- class: {
828
- connect: {
829
- id: classId,
830
- },
831
- },
832
- structured: validatedStructure,
833
- },
834
- });
835
- return gradingBoundary;
836
- }),
99
+ .input(z.object({ classId: z.string(), structure: z.string() }))
100
+ .mutation(({ input }) => createGradingBoundary(input.classId, input.structure)),
837
101
  updateGradingBoundary: protectedTeacherProcedure
838
102
  .input(z.object({
839
103
  classId: z.string(),
840
104
  gradingBoundaryId: z.string(),
841
105
  structure: z.string(),
842
106
  }))
843
- .mutation(async ({ ctx, input }) => {
844
- const { classId, gradingBoundaryId, structure } = input;
845
- const validatedStructure = structure.replace(/\\n/g, '\n');
846
- const gradingBoundary = await prisma.gradingBoundary.update({
847
- where: { id: gradingBoundaryId },
848
- data: {
849
- class: {
850
- connect: {
851
- id: classId,
852
- },
853
- },
854
- structured: validatedStructure,
855
- },
856
- });
857
- return gradingBoundary;
858
- }),
107
+ .mutation(({ input }) => updateGradingBoundary(input.gradingBoundaryId, input.classId, input.structure)),
859
108
  deleteGradingBoundary: protectedTeacherProcedure
860
- .input(z.object({
861
- classId: z.string(),
862
- gradingBoundaryId: z.string(),
863
- }))
864
- .mutation(async ({ ctx, input }) => {
865
- const { classId, gradingBoundaryId } = input;
866
- const gradingBoundary = await prisma.gradingBoundary.delete({
867
- where: { id: gradingBoundaryId },
868
- });
869
- return gradingBoundary;
870
- }),
109
+ .input(z.object({ classId: z.string(), gradingBoundaryId: z.string() }))
110
+ .mutation(({ input }) => deleteGradingBoundary(input.gradingBoundaryId)),
871
111
  getSyllabus: protectedClassMemberProcedure
872
- .input(z.object({
873
- classId: z.string(),
874
- }))
875
- .query(async ({ input }) => {
876
- const { classId } = input;
877
- const syllabus = (await prisma.class.findUnique({
878
- where: {
879
- id: classId,
880
- },
881
- }))?.syllabus;
882
- const markSchemes = await prisma.markScheme.findMany({
883
- where: {
884
- classId,
885
- }
886
- });
887
- const gradingBoundaries = await prisma.gradingBoundary.findMany({
888
- where: {
889
- classId,
890
- }
891
- });
892
- return { syllabus, gradingBoundaries, markSchemes };
893
- }),
112
+ .input(z.object({ classId: z.string() }))
113
+ .query(({ input }) => getSyllabus(input.classId)),
894
114
  updateSyllabus: protectedTeacherProcedure
895
- .input(z.object({
896
- classId: z.string(),
897
- contents: z.string(),
898
- }))
899
- .mutation(async ({ input }) => {
900
- const { contents, classId } = input;
901
- if (!contents)
902
- throw new TRPCError({
903
- code: 'BAD_REQUEST',
904
- message: "Missing key contents",
905
- });
906
- const updated = await prisma.class.update({
907
- where: {
908
- id: classId
909
- },
910
- data: {
911
- syllabus: contents,
912
- }
913
- });
914
- return updated;
915
- }),
916
- // Lab Management Endpoints (Assignment-based)
115
+ .input(z.object({ classId: z.string(), contents: z.string() }))
116
+ .mutation(({ input }) => updateSyllabus(input.classId, input.contents)),
917
117
  listLabDrafts: protectedTeacherProcedure
918
- .input(z.object({
919
- classId: z.string(),
920
- }))
921
- .query(async ({ ctx, input }) => {
922
- const { classId } = input;
923
- const labDrafts = await prisma.assignment.findMany({
924
- where: {
925
- classId: classId,
926
- teacherId: ctx.user?.id,
927
- inProgress: true,
928
- },
929
- orderBy: {
930
- modifiedAt: 'desc',
931
- },
932
- });
933
- return labDrafts;
934
- }),
118
+ .input(z.object({ classId: z.string() }))
119
+ .query(({ ctx, input }) => listLabDrafts(input.classId, ctx.user?.id ?? "")),
935
120
  createLabDraft: protectedTeacherProcedure
936
121
  .input(z.object({
937
122
  classId: z.string(),
938
123
  title: z.string(),
939
- 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
+ ]),
940
135
  instructions: z.string(),
941
136
  dueDate: z.date().optional(),
942
137
  maxGrade: z.number().optional(),
@@ -946,26 +141,9 @@ export const classRouter = createTRPCRouter({
946
141
  markSchemeId: z.string().optional(),
947
142
  gradingBoundaryId: z.string().optional(),
948
143
  }))
949
- .mutation(async ({ ctx, input }) => {
144
+ .mutation(({ ctx, input }) => {
950
145
  const { classId, ...draftData } = input;
951
- const labDraft = await prisma.assignment.create({
952
- data: {
953
- classId: classId,
954
- teacherId: ctx.user?.id,
955
- inProgress: true,
956
- graded: draftData.graded ?? false,
957
- maxGrade: draftData.maxGrade ?? 0,
958
- weight: draftData.weight ?? 1,
959
- dueDate: draftData.dueDate || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // Default 1 week from now
960
- title: draftData.title,
961
- instructions: draftData.instructions,
962
- type: draftData.type,
963
- ...(draftData.sectionId && { sectionId: draftData.sectionId }),
964
- ...(draftData.markSchemeId && { markSchemeId: draftData.markSchemeId }),
965
- ...(draftData.gradingBoundaryId && { gradingBoundaryId: draftData.gradingBoundaryId }),
966
- },
967
- });
968
- return labDraft;
146
+ return createLabDraft(classId, ctx.user?.id ?? "", draftData);
969
147
  }),
970
148
  updateLabDraft: protectedTeacherProcedure
971
149
  .input(z.object({
@@ -981,47 +159,13 @@ export const classRouter = createTRPCRouter({
981
159
  markSchemeId: z.string().optional(),
982
160
  gradingBoundaryId: z.string().optional(),
983
161
  }))
984
- .mutation(async ({ ctx, input }) => {
162
+ .mutation(({ ctx, input }) => {
985
163
  const { classId, draftId, ...updateData } = input;
986
- const labDraft = await prisma.assignment.update({
987
- where: {
988
- id: draftId,
989
- classId: classId,
990
- teacherId: ctx.user?.id,
991
- inProgress: true,
992
- },
993
- data: {
994
- ...(updateData.title && { title: updateData.title }),
995
- ...(updateData.instructions && { instructions: updateData.instructions }),
996
- ...(updateData.dueDate && { dueDate: updateData.dueDate }),
997
- ...(updateData.maxGrade !== undefined && { maxGrade: updateData.maxGrade }),
998
- ...(updateData.weight !== undefined && { weight: updateData.weight }),
999
- ...(updateData.graded !== undefined && { graded: updateData.graded }),
1000
- ...(updateData.sectionId !== undefined && { sectionId: updateData.sectionId }),
1001
- ...(updateData.markSchemeId !== undefined && { markSchemeId: updateData.markSchemeId }),
1002
- ...(updateData.gradingBoundaryId !== undefined && { gradingBoundaryId: updateData.gradingBoundaryId }),
1003
- modifiedAt: new Date(),
1004
- },
1005
- });
1006
- return labDraft;
164
+ return updateLabDraft(classId, ctx.user?.id ?? "", draftId, updateData);
1007
165
  }),
1008
166
  deleteLabDraft: protectedTeacherProcedure
1009
- .input(z.object({
1010
- classId: z.string(),
1011
- draftId: z.string(),
1012
- }))
1013
- .mutation(async ({ ctx, input }) => {
1014
- const { classId, draftId } = input;
1015
- const labDraft = await prisma.assignment.delete({
1016
- where: {
1017
- id: draftId,
1018
- classId: classId,
1019
- teacherId: ctx.user?.id,
1020
- inProgress: true,
1021
- },
1022
- });
1023
- return labDraft;
1024
- }),
167
+ .input(z.object({ classId: z.string(), draftId: z.string() }))
168
+ .mutation(({ ctx, input }) => deleteLabDraft(input.classId, ctx.user?.id ?? "", input.draftId)),
1025
169
  publishLabDraft: protectedTeacherProcedure
1026
170
  .input(z.object({
1027
171
  classId: z.string(),
@@ -1031,136 +175,23 @@ export const classRouter = createTRPCRouter({
1031
175
  weight: z.number().optional(),
1032
176
  graded: z.boolean().optional(),
1033
177
  }))
1034
- .mutation(async ({ ctx, input }) => {
178
+ .mutation(({ ctx, input }) => {
1035
179
  const { classId, draftId, ...publishData } = input;
1036
- // Get the lab draft
1037
- const labDraft = await prisma.assignment.findUnique({
1038
- where: {
1039
- id: draftId,
1040
- classId: classId,
1041
- teacherId: ctx.user?.id,
1042
- inProgress: true,
1043
- },
1044
- });
1045
- if (!labDraft) {
1046
- throw new TRPCError({
1047
- code: 'NOT_FOUND',
1048
- message: 'Lab draft not found',
1049
- });
1050
- }
1051
- // Publish the draft by updating it to not be in progress
1052
- const publishedAssignment = await prisma.assignment.update({
1053
- where: { id: draftId },
1054
- data: {
1055
- inProgress: false,
1056
- dueDate: publishData.dueDate || labDraft.dueDate,
1057
- maxGrade: publishData.maxGrade || labDraft.maxGrade || 100,
1058
- weight: publishData.weight || labDraft.weight || 1,
1059
- graded: publishData.graded !== undefined ? publishData.graded : true,
1060
- modifiedAt: new Date(),
1061
- },
1062
- });
1063
- return publishedAssignment;
180
+ return publishLabDraft(classId, ctx.user?.id ?? "", draftId, publishData);
1064
181
  }),
1065
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
1066
189
  .input(z.object({
1067
190
  classId: z.string(),
191
+ year: z.number(),
192
+ classData: z.any(),
1068
193
  }))
1069
- .query(async ({ ctx, input }) => {
1070
- const { classId } = input;
1071
- // Get all assignments with their files and submissions
1072
- const assignments = await prisma.assignment.findMany({
1073
- where: {
1074
- classId: classId,
1075
- },
1076
- include: {
1077
- attachments: {
1078
- select: {
1079
- id: true,
1080
- name: true,
1081
- type: true,
1082
- size: true,
1083
- path: true,
1084
- thumbnailId: true,
1085
- uploadedAt: true,
1086
- user: {
1087
- select: {
1088
- id: true,
1089
- username: true,
1090
- },
1091
- },
1092
- },
1093
- },
1094
- submissions: {
1095
- include: {
1096
- attachments: {
1097
- select: {
1098
- id: true,
1099
- name: true,
1100
- type: true,
1101
- size: true,
1102
- path: true,
1103
- thumbnailId: true,
1104
- uploadedAt: true,
1105
- user: {
1106
- select: {
1107
- id: true,
1108
- username: true,
1109
- },
1110
- },
1111
- },
1112
- },
1113
- annotations: {
1114
- select: {
1115
- id: true,
1116
- name: true,
1117
- type: true,
1118
- size: true,
1119
- path: true,
1120
- thumbnailId: true,
1121
- uploadedAt: true,
1122
- user: {
1123
- select: {
1124
- id: true,
1125
- username: true,
1126
- },
1127
- },
1128
- },
1129
- },
1130
- student: {
1131
- select: {
1132
- id: true,
1133
- username: true,
1134
- },
1135
- },
1136
- },
1137
- },
1138
- teacher: {
1139
- select: {
1140
- id: true,
1141
- username: true,
1142
- },
1143
- },
1144
- },
1145
- orderBy: {
1146
- createdAt: 'desc',
1147
- },
1148
- });
1149
- // Organize files by assignment structure
1150
- const organizedFiles = assignments.map(assignment => ({
1151
- id: assignment.id,
1152
- title: assignment.title,
1153
- teacher: assignment.teacher,
1154
- teacherAttachments: assignment.attachments,
1155
- students: assignment.submissions.map(submission => ({
1156
- id: submission.student.id,
1157
- username: submission.student.username,
1158
- attachments: submission.attachments,
1159
- annotations: submission.annotations,
1160
- })),
1161
- }));
1162
- return organizedFiles;
1163
- }),
194
+ .mutation(({ ctx, input }) => importClass(input.classId, ctx.user?.id ?? "", input.year, input.classData)),
1164
195
  });
1165
196
  //# sourceMappingURL=class.js.map
1166
- //# debugId=767877f8-1e76-552f-92f2-c3b39f1302ec
197
+ //# debugId=43c06b92-74d9-5f52-a500-f14b511e48a2