@studious-lms/server 1.1.26 → 1.2.6

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