@studious-lms/server 1.1.24 → 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 (485) 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 +82 -15
  23. package/dist/lib/fileUpload.js.map +1 -0
  24. package/dist/lib/googleCloudStorage.d.ts +13 -0
  25. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  26. package/dist/lib/googleCloudStorage.js +45 -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 +25 -0
  35. package/dist/lib/notificationHandler.d.ts.map +1 -0
  36. package/dist/lib/notificationHandler.js +32 -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 +6403 -3741
  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 +547 -57
  163. package/dist/routers/announcement.js.map +1 -0
  164. package/dist/routers/assignment.d.ts +431 -318
  165. package/dist/routers/assignment.d.ts.map +1 -1
  166. package/dist/routers/assignment.js +104 -1559
  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 -295
  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 -877
  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 +37 -6
  221. package/dist/routers/section.d.ts.map +1 -1
  222. package/dist/routers/section.js +26 -167
  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 +311 -289
  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 +4 -0
  350. package/dist/utils/logger.d.ts.map +1 -1
  351. package/dist/utils/logger.js +35 -3
  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 +81 -16
  370. package/src/lib/googleCloudStorage.ts +42 -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 +622 -57
  403. package/src/routers/assignment.ts +157 -1688
  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 -341
  411. package/src/routers/folder.ts +107 -836
  412. package/src/routers/labChat.ts +29 -960
  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 -200
  418. package/src/routers/user.ts +49 -226
  419. package/src/routers/worksheet.ts +252 -0
  420. package/src/seedDatabase.ts +330 -290
  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 +33 -3
  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 -65
  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/tests/auth.test.ts +0 -25
@@ -0,0 +1,239 @@
1
+ import { type WorksheetQuestionType } from "@prisma/client";
2
+ /** Get worksheet with questions and mark schemes. */
3
+ export declare function getWorksheet(worksheetId: string): Promise<{
4
+ class: {
5
+ id: string;
6
+ schoolId: string | null;
7
+ name: string;
8
+ subject: string;
9
+ color: string | null;
10
+ section: string;
11
+ syllabus: string | null;
12
+ } | null;
13
+ questions: {
14
+ options: import("@prisma/client/runtime/library.js").JsonValue | null;
15
+ type: import(".prisma/client").$Enums.WorksheetQuestionType;
16
+ id: string;
17
+ createdAt: Date;
18
+ updatedAt: Date;
19
+ order: number | null;
20
+ markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
21
+ question: string;
22
+ points: number;
23
+ worksheetId: string;
24
+ answer: string;
25
+ }[];
26
+ } & {
27
+ id: string;
28
+ createdAt: Date;
29
+ updatedAt: Date;
30
+ classId: string;
31
+ name: string;
32
+ }>;
33
+ /** Check if worksheet exists. */
34
+ export declare function worksheetExists(id: string): Promise<boolean>;
35
+ export declare function listWorksheets(classId: string): Promise<{
36
+ questionCount: number;
37
+ questions: {
38
+ id: string;
39
+ }[];
40
+ id: string;
41
+ createdAt: Date;
42
+ updatedAt: Date;
43
+ classId: string;
44
+ name: string;
45
+ }[]>;
46
+ export declare function updateWorksheetRecord(worksheetId: string, data: {
47
+ name?: string;
48
+ }): Promise<{
49
+ id: string;
50
+ createdAt: Date;
51
+ updatedAt: Date;
52
+ classId: string;
53
+ name: string;
54
+ }>;
55
+ export declare function deleteWorksheetRecord(worksheetId: string): Promise<{
56
+ id: string;
57
+ createdAt: Date;
58
+ updatedAt: Date;
59
+ classId: string;
60
+ name: string;
61
+ }>;
62
+ export declare function createWorksheetRecord(classId: string, name: string): Promise<{
63
+ id: string;
64
+ createdAt: Date;
65
+ updatedAt: Date;
66
+ classId: string;
67
+ name: string;
68
+ }>;
69
+ export declare function addQuestionToWorksheet(worksheetId: string, data: {
70
+ question: string;
71
+ answer: string;
72
+ points?: number;
73
+ options?: object;
74
+ markScheme?: object;
75
+ type: WorksheetQuestionType;
76
+ }): Promise<{
77
+ options: import("@prisma/client/runtime/library.js").JsonValue | null;
78
+ type: import(".prisma/client").$Enums.WorksheetQuestionType;
79
+ id: string;
80
+ createdAt: Date;
81
+ updatedAt: Date;
82
+ order: number | null;
83
+ markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
84
+ question: string;
85
+ points: number;
86
+ worksheetId: string;
87
+ answer: string;
88
+ }>;
89
+ export declare function reorderWorksheetQuestions(worksheetId: string, movedId: string, position: "before" | "after", targetId: string): Promise<{
90
+ id: string;
91
+ }[]>;
92
+ export declare function updateWorksheetQuestionRecord(worksheetId: string, questionId: string, data: {
93
+ question?: string;
94
+ answer?: string;
95
+ points?: number;
96
+ options?: object;
97
+ markScheme?: object;
98
+ type?: WorksheetQuestionType;
99
+ }): Promise<{
100
+ options: import("@prisma/client/runtime/library.js").JsonValue | null;
101
+ type: import(".prisma/client").$Enums.WorksheetQuestionType;
102
+ id: string;
103
+ createdAt: Date;
104
+ updatedAt: Date;
105
+ order: number | null;
106
+ markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
107
+ question: string;
108
+ points: number;
109
+ worksheetId: string;
110
+ answer: string;
111
+ }>;
112
+ export declare function deleteWorksheetQuestionRecord(worksheetId: string, questionId: string): Promise<{
113
+ options: import("@prisma/client/runtime/library.js").JsonValue | null;
114
+ type: import(".prisma/client").$Enums.WorksheetQuestionType;
115
+ id: string;
116
+ createdAt: Date;
117
+ updatedAt: Date;
118
+ order: number | null;
119
+ markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
120
+ question: string;
121
+ points: number;
122
+ worksheetId: string;
123
+ answer: string;
124
+ }>;
125
+ export declare function getWorksheetSubmission(worksheetId: string, submissionId: string): Promise<{
126
+ responses: ({
127
+ comments: {
128
+ id: string;
129
+ }[];
130
+ } & {
131
+ status: import(".prisma/client").$Enums.GenerationStatus | null;
132
+ id: string;
133
+ createdAt: Date;
134
+ updatedAt: Date | null;
135
+ feedback: string | null;
136
+ studentId: string;
137
+ response: string;
138
+ isCorrect: boolean;
139
+ markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
140
+ points: number;
141
+ questionId: string;
142
+ studentWorksheetResponseId: string | null;
143
+ })[];
144
+ } & {
145
+ id: string;
146
+ createdAt: Date;
147
+ updatedAt: Date;
148
+ submissionId: string | null;
149
+ studentId: string;
150
+ submittedAt: Date | null;
151
+ submitted: boolean;
152
+ worksheetId: string;
153
+ }>;
154
+ export declare function answerWorksheetQuestion(worksheetResponseId: string, questionId: string, response: string, userId: string): Promise<{
155
+ responses: {
156
+ status: import(".prisma/client").$Enums.GenerationStatus | null;
157
+ id: string;
158
+ createdAt: Date;
159
+ updatedAt: Date | null;
160
+ feedback: string | null;
161
+ studentId: string;
162
+ response: string;
163
+ isCorrect: boolean;
164
+ markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
165
+ points: number;
166
+ questionId: string;
167
+ studentWorksheetResponseId: string | null;
168
+ }[];
169
+ } & {
170
+ id: string;
171
+ createdAt: Date;
172
+ updatedAt: Date;
173
+ submissionId: string | null;
174
+ studentId: string;
175
+ submittedAt: Date | null;
176
+ submitted: boolean;
177
+ worksheetId: string;
178
+ }>;
179
+ export declare function cancelGrading(worksheetResponseId: string, progressId: string): Promise<{
180
+ status: import(".prisma/client").$Enums.GenerationStatus | null;
181
+ id: string;
182
+ createdAt: Date;
183
+ updatedAt: Date | null;
184
+ feedback: string | null;
185
+ studentId: string;
186
+ response: string;
187
+ isCorrect: boolean;
188
+ markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
189
+ points: number;
190
+ questionId: string;
191
+ studentWorksheetResponseId: string | null;
192
+ }>;
193
+ export declare function regradeQuestion(worksheetResponseId: string, progressId: string): Promise<{
194
+ status: import(".prisma/client").$Enums.GenerationStatus | null;
195
+ id: string;
196
+ createdAt: Date;
197
+ updatedAt: Date | null;
198
+ feedback: string | null;
199
+ studentId: string;
200
+ response: string;
201
+ isCorrect: boolean;
202
+ markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
203
+ points: number;
204
+ questionId: string;
205
+ studentWorksheetResponseId: string | null;
206
+ }>;
207
+ export declare function gradeAnswer(questionId: string, studentWorksheetResponseId: string, data: {
208
+ responseId?: string;
209
+ response?: string;
210
+ isCorrect: boolean;
211
+ feedback?: string;
212
+ markschemeState?: object;
213
+ points?: number;
214
+ }): Promise<{
215
+ status: import(".prisma/client").$Enums.GenerationStatus | null;
216
+ id: string;
217
+ createdAt: Date;
218
+ updatedAt: Date | null;
219
+ feedback: string | null;
220
+ studentId: string;
221
+ response: string;
222
+ isCorrect: boolean;
223
+ markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
224
+ points: number;
225
+ questionId: string;
226
+ studentWorksheetResponseId: string | null;
227
+ }>;
228
+ export declare function addCommentToResponse(responseId: string, comment: string, authorId: string): Promise<{
229
+ status: import(".prisma/client").$Enums.GenerationStatus | null;
230
+ id: string;
231
+ createdAt: Date;
232
+ content: string;
233
+ modifiedAt: Date | null;
234
+ announcementId: string | null;
235
+ authorId: string;
236
+ parentCommentId: string | null;
237
+ studentQuestionProgressId: string | null;
238
+ }>;
239
+ //# sourceMappingURL=worksheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worksheet.d.ts","sourceRoot":"/","sources":["services/worksheet.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AA4B9E,qDAAqD;AACrD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GASrD;AAED,iCAAiC;AACjC,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,oBAG/C;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM;;;;;;;;;;KAMnD;AAED,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;GAGxB;AAED,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM;;;;;;GAE9D;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;;;;;;GAExE;AAED,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,qBAAqB,CAAC;CAC7B;;;;;;;;;;;;GAaF;AAED,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GAAG,OAAO,EAC5B,QAAQ,EAAE,MAAM;;KAqDjB;AAED,wBAAsB,6BAA6B,CACjD,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE;IACJ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,qBAAqB,CAAC;CAC9B;;;;;;;;;;;;GAUF;AAED,wBAAsB,6BAA6B,CACjD,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM;;;;;;;;;;;;GAUnB;AAED,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAcrB;AAED,wBAAsB,uBAAuB,CAC3C,mBAAmB,EAAE,MAAM,EAC3B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;GAwDf;AAED,wBAAsB,aAAa,CACjC,mBAAmB,EAAE,MAAM,EAC3B,UAAU,EAAE,MAAM;;;;;;;;;;;;;GAGnB;AAED,wBAAsB,eAAe,CACnC,mBAAmB,EAAE,MAAM,EAC3B,UAAU,EAAE,MAAM;;;;;;;;;;;;;GAGnB;AAED,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,0BAA0B,EAAE,MAAM,EAClC,IAAI,EAAE;IACJ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;;;;;;;;;;;;GAgDF;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM;;;;;;;;;;GAOjB"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Worksheet service – CRUD for worksheets, questions, submissions, and AI grading.
3
+ * Integrates with gradeWorksheet pipeline for auto-grading.
4
+ */
5
+
6
+ !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]="cffbcf20-cef6-5fd4-979f-670d50592d0a")}catch(e){}}();
7
+ import { TRPCError } from "@trpc/server";
8
+ import { GenerationStatus } from "@prisma/client";
9
+ import { prisma } from "../lib/prisma.js";
10
+ import { cancelGradePipeline, regradeWorksheetPipeline } from "../pipelines/gradeWorksheet.js";
11
+ import { findWorksheetById, findWorksheetByIdMinimal, findWorksheetsByClassId, createWorksheet, updateWorksheet, deleteWorksheet, findQuestionsByWorksheetId, createWorksheetQuestion, updateWorksheetQuestion, deleteWorksheetQuestion, findSubmissionById, findOrCreateWorksheetResponse, findWorksheetResponseWithResponses, findWorksheetQuestionById, updateStudentQuestionProgress, createStudentQuestionProgress, findStudentQuestionProgress, updateStudentQuestionProgressForGrading, createStudentQuestionProgressForGrading, createComment, } from "../models/worksheet.js";
12
+ /** Get worksheet with questions and mark schemes. */
13
+ export async function getWorksheet(worksheetId) {
14
+ const worksheet = await findWorksheetById(worksheetId);
15
+ if (!worksheet) {
16
+ throw new TRPCError({
17
+ code: "NOT_FOUND",
18
+ message: "Worksheet not found",
19
+ });
20
+ }
21
+ return worksheet;
22
+ }
23
+ /** Check if worksheet exists. */
24
+ export async function worksheetExists(id) {
25
+ const worksheet = await findWorksheetByIdMinimal(id);
26
+ return !!worksheet;
27
+ }
28
+ export async function listWorksheets(classId) {
29
+ const worksheets = await findWorksheetsByClassId(classId);
30
+ return worksheets.map((w) => ({
31
+ ...w,
32
+ questionCount: w.questions.length,
33
+ }));
34
+ }
35
+ export async function updateWorksheetRecord(worksheetId, data) {
36
+ return updateWorksheet(worksheetId, data);
37
+ }
38
+ export async function deleteWorksheetRecord(worksheetId) {
39
+ return deleteWorksheet(worksheetId);
40
+ }
41
+ export async function createWorksheetRecord(classId, name) {
42
+ return createWorksheet({ classId, name });
43
+ }
44
+ export async function addQuestionToWorksheet(worksheetId, data) {
45
+ const worksheet = await findWorksheetByIdMinimal(worksheetId);
46
+ if (!worksheet) {
47
+ throw new TRPCError({
48
+ code: "NOT_FOUND",
49
+ message: "Worksheet not found",
50
+ });
51
+ }
52
+ return createWorksheetQuestion({
53
+ worksheetId,
54
+ ...data,
55
+ });
56
+ }
57
+ export async function reorderWorksheetQuestions(worksheetId, movedId, position, targetId) {
58
+ const worksheet = await findWorksheetByIdMinimal(worksheetId);
59
+ if (!worksheet) {
60
+ throw new TRPCError({
61
+ code: "NOT_FOUND",
62
+ message: "Worksheet not found",
63
+ });
64
+ }
65
+ const questions = await findQuestionsByWorksheetId(worksheetId);
66
+ const movedIdx = questions.findIndex((q) => q.id === movedId);
67
+ if (movedIdx === -1) {
68
+ throw new TRPCError({
69
+ code: "NOT_FOUND",
70
+ message: "Moved question not found",
71
+ });
72
+ }
73
+ const targetIdx = questions.findIndex((q) => q.id === targetId);
74
+ if (targetIdx === -1) {
75
+ throw new TRPCError({
76
+ code: "NOT_FOUND",
77
+ message: "Target question not found",
78
+ });
79
+ }
80
+ const withoutMoved = questions.filter((q) => q.id !== movedId);
81
+ const next = position === "before"
82
+ ? [
83
+ ...withoutMoved.slice(0, targetIdx).map((item) => ({ id: item.id })),
84
+ { id: movedId },
85
+ ...withoutMoved.slice(targetIdx).map((item) => ({ id: item.id })),
86
+ ]
87
+ : [
88
+ ...withoutMoved
89
+ .slice(0, targetIdx + 1)
90
+ .map((item) => ({ id: item.id })),
91
+ { id: movedId },
92
+ ...withoutMoved
93
+ .slice(targetIdx + 1)
94
+ .map((item) => ({ id: item.id })),
95
+ ];
96
+ await prisma.$transaction(next.map((item, index) => prisma.worksheetQuestion.update({
97
+ where: { id: item.id },
98
+ data: { order: index },
99
+ })));
100
+ return next;
101
+ }
102
+ export async function updateWorksheetQuestionRecord(worksheetId, questionId, data) {
103
+ const worksheet = await findWorksheetByIdMinimal(worksheetId);
104
+ if (!worksheet) {
105
+ throw new TRPCError({
106
+ code: "NOT_FOUND",
107
+ message: "Worksheet not found",
108
+ });
109
+ }
110
+ return updateWorksheetQuestion(questionId, data);
111
+ }
112
+ export async function deleteWorksheetQuestionRecord(worksheetId, questionId) {
113
+ const worksheet = await findWorksheetByIdMinimal(worksheetId);
114
+ if (!worksheet) {
115
+ throw new TRPCError({
116
+ code: "NOT_FOUND",
117
+ message: "Worksheet not found",
118
+ });
119
+ }
120
+ return deleteWorksheetQuestion(questionId);
121
+ }
122
+ export async function getWorksheetSubmission(worksheetId, submissionId) {
123
+ const submission = await findSubmissionById(submissionId);
124
+ if (!submission) {
125
+ throw new TRPCError({
126
+ code: "NOT_FOUND",
127
+ message: "Submission not found",
128
+ });
129
+ }
130
+ return findOrCreateWorksheetResponse(submissionId, worksheetId, submission.studentId);
131
+ }
132
+ export async function answerWorksheetQuestion(worksheetResponseId, questionId, response, userId) {
133
+ const worksheetResponse = await findWorksheetResponseWithResponses(worksheetResponseId, questionId);
134
+ if (!worksheetResponse) {
135
+ throw new TRPCError({
136
+ code: "NOT_FOUND",
137
+ message: "Worksheet response not found",
138
+ });
139
+ }
140
+ const question = await findWorksheetQuestionById(questionId);
141
+ const isMarkableByAlgo = question?.type === "MULTIPLE_CHOICE" || question?.type === "TRUE_FALSE";
142
+ const marksAwardedIfCorrect = question?.points || 0;
143
+ const correctAnswer = isMarkableByAlgo
144
+ ? question?.type === "MULTIPLE_CHOICE"
145
+ ? question?.options?.find((o) => o.isCorrect)?.id
146
+ : question?.answer?.toString()
147
+ : null;
148
+ const existingResponse = worksheetResponse.responses[0];
149
+ if (existingResponse) {
150
+ await updateStudentQuestionProgress(existingResponse.id, {
151
+ response,
152
+ ...(isMarkableByAlgo && {
153
+ isCorrect: response === correctAnswer,
154
+ }),
155
+ ...(isMarkableByAlgo && {
156
+ points: response === correctAnswer ? marksAwardedIfCorrect : 0,
157
+ }),
158
+ status: GenerationStatus.NOT_STARTED,
159
+ });
160
+ }
161
+ else {
162
+ await createStudentQuestionProgress({
163
+ studentId: worksheetResponse.studentId,
164
+ questionId,
165
+ response,
166
+ studentWorksheetResponseId: worksheetResponseId,
167
+ ...(isMarkableByAlgo && {
168
+ isCorrect: response === correctAnswer,
169
+ }),
170
+ ...(isMarkableByAlgo && {
171
+ points: response === correctAnswer ? marksAwardedIfCorrect : 0,
172
+ }),
173
+ });
174
+ }
175
+ const updated = await prisma.studentWorksheetResponse.findUnique({
176
+ where: { id: worksheetResponseId },
177
+ include: { responses: true },
178
+ });
179
+ return updated;
180
+ }
181
+ export async function cancelGrading(worksheetResponseId, progressId) {
182
+ return cancelGradePipeline(worksheetResponseId, progressId);
183
+ }
184
+ export async function regradeQuestion(worksheetResponseId, progressId) {
185
+ return regradeWorksheetPipeline(worksheetResponseId, progressId);
186
+ }
187
+ export async function gradeAnswer(questionId, studentWorksheetResponseId, data) {
188
+ if (data.responseId) {
189
+ return updateStudentQuestionProgressForGrading(data.responseId, {
190
+ isCorrect: data.isCorrect,
191
+ feedback: data.feedback,
192
+ markschemeState: data.markschemeState,
193
+ points: data.points,
194
+ });
195
+ }
196
+ const worksheetResponse = await prisma.studentWorksheetResponse.findUnique({
197
+ where: { id: studentWorksheetResponseId },
198
+ select: { studentId: true },
199
+ });
200
+ if (!worksheetResponse) {
201
+ throw new TRPCError({
202
+ code: "NOT_FOUND",
203
+ message: "Student worksheet response not found",
204
+ });
205
+ }
206
+ const existing = await findStudentQuestionProgress(worksheetResponse.studentId, questionId, studentWorksheetResponseId);
207
+ if (existing) {
208
+ return updateStudentQuestionProgressForGrading(existing.id, {
209
+ isCorrect: data.isCorrect,
210
+ response: data.response,
211
+ feedback: data.feedback,
212
+ markschemeState: data.markschemeState,
213
+ points: data.points,
214
+ });
215
+ }
216
+ return createStudentQuestionProgressForGrading({
217
+ studentId: worksheetResponse.studentId,
218
+ questionId,
219
+ studentWorksheetResponseId,
220
+ response: data.response || "",
221
+ isCorrect: data.isCorrect,
222
+ feedback: data.feedback,
223
+ markschemeState: data.markschemeState,
224
+ points: data.points || 0,
225
+ });
226
+ }
227
+ export async function addCommentToResponse(responseId, comment, authorId) {
228
+ return createComment({
229
+ studentQuestionProgressId: responseId,
230
+ content: comment,
231
+ authorId,
232
+ });
233
+ }
234
+ //# sourceMappingURL=worksheet.js.map
235
+ //# debugId=cffbcf20-cef6-5fd4-979f-670d50592d0a
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worksheet.js","sources":["services/worksheet.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Worksheet service – CRUD for worksheets, questions, submissions, and AI grading.\n * Integrates with gradeWorksheet pipeline for auto-grading.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport { GenerationStatus, type WorksheetQuestionType } from \"@prisma/client\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { cancelGradePipeline, regradeWorksheetPipeline } from \"../pipelines/gradeWorksheet.js\";\nimport {\n findWorksheetById,\n findWorksheetByIdMinimal,\n findWorksheetsByClassId,\n createWorksheet,\n updateWorksheet,\n deleteWorksheet,\n findQuestionsByWorksheetId,\n createWorksheetQuestion,\n updateWorksheetQuestion,\n deleteWorksheetQuestion,\n findSubmissionById,\n findOrCreateWorksheetResponse,\n findWorksheetResponseWithResponses,\n findWorksheetQuestionById,\n updateStudentQuestionProgress,\n createStudentQuestionProgress,\n findStudentQuestionProgress,\n updateStudentQuestionProgressForGrading,\n createStudentQuestionProgressForGrading,\n createComment,\n} from \"../models/worksheet.js\";\n\ntype MCQOptions = { id: string; text: string; isCorrect: boolean }[];\n\n/** Get worksheet with questions and mark schemes. */\nexport async function getWorksheet(worksheetId: string) {\n const worksheet = await findWorksheetById(worksheetId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found\",\n });\n }\n return worksheet;\n}\n\n/** Check if worksheet exists. */\nexport async function worksheetExists(id: string) {\n const worksheet = await findWorksheetByIdMinimal(id);\n return !!worksheet;\n}\n\nexport async function listWorksheets(classId: string) {\n const worksheets = await findWorksheetsByClassId(classId);\n return worksheets.map((w) => ({\n ...w,\n questionCount: w.questions.length,\n }));\n}\n\nexport async function updateWorksheetRecord(\n worksheetId: string,\n data: { name?: string }\n) {\n return updateWorksheet(worksheetId, data);\n}\n\nexport async function deleteWorksheetRecord(worksheetId: string) {\n return deleteWorksheet(worksheetId);\n}\n\nexport async function createWorksheetRecord(classId: string, name: string) {\n return createWorksheet({ classId, name });\n}\n\nexport async function addQuestionToWorksheet(\n worksheetId: string,\n data: {\n question: string;\n answer: string;\n points?: number;\n options?: object;\n markScheme?: object;\n type: WorksheetQuestionType;\n }\n) {\n const worksheet = await findWorksheetByIdMinimal(worksheetId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found\",\n });\n }\n return createWorksheetQuestion({\n worksheetId,\n ...data,\n });\n}\n\nexport async function reorderWorksheetQuestions(\n worksheetId: string,\n movedId: string,\n position: \"before\" | \"after\",\n targetId: string\n) {\n const worksheet = await findWorksheetByIdMinimal(worksheetId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found\",\n });\n }\n\n const questions = await findQuestionsByWorksheetId(worksheetId);\n const movedIdx = questions.findIndex((q) => q.id === movedId);\n if (movedIdx === -1) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Moved question not found\",\n });\n }\n const targetIdx = questions.findIndex((q) => q.id === targetId);\n if (targetIdx === -1) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Target question not found\",\n });\n }\n\n const withoutMoved = questions.filter((q) => q.id !== movedId);\n const next =\n position === \"before\"\n ? [\n ...withoutMoved.slice(0, targetIdx).map((item) => ({ id: item.id })),\n { id: movedId },\n ...withoutMoved.slice(targetIdx).map((item) => ({ id: item.id })),\n ]\n : [\n ...withoutMoved\n .slice(0, targetIdx + 1)\n .map((item) => ({ id: item.id })),\n { id: movedId },\n ...withoutMoved\n .slice(targetIdx + 1)\n .map((item) => ({ id: item.id })),\n ];\n\n await prisma.$transaction(\n next.map((item, index) =>\n prisma.worksheetQuestion.update({\n where: { id: item.id },\n data: { order: index },\n })\n )\n );\n return next;\n}\n\nexport async function updateWorksheetQuestionRecord(\n worksheetId: string,\n questionId: string,\n data: {\n question?: string;\n answer?: string;\n points?: number;\n options?: object;\n markScheme?: object;\n type?: WorksheetQuestionType;\n }\n) {\n const worksheet = await findWorksheetByIdMinimal(worksheetId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found\",\n });\n }\n return updateWorksheetQuestion(questionId, data);\n}\n\nexport async function deleteWorksheetQuestionRecord(\n worksheetId: string,\n questionId: string\n) {\n const worksheet = await findWorksheetByIdMinimal(worksheetId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found\",\n });\n }\n return deleteWorksheetQuestion(questionId);\n}\n\nexport async function getWorksheetSubmission(\n worksheetId: string,\n submissionId: string\n) {\n const submission = await findSubmissionById(submissionId);\n if (!submission) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Submission not found\",\n });\n }\n return findOrCreateWorksheetResponse(\n submissionId,\n worksheetId,\n submission.studentId\n );\n}\n\nexport async function answerWorksheetQuestion(\n worksheetResponseId: string,\n questionId: string,\n response: string,\n userId: string\n) {\n const worksheetResponse = await findWorksheetResponseWithResponses(\n worksheetResponseId,\n questionId\n );\n if (!worksheetResponse) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet response not found\",\n });\n }\n\n const question = await findWorksheetQuestionById(questionId);\n const isMarkableByAlgo =\n question?.type === \"MULTIPLE_CHOICE\" || question?.type === \"TRUE_FALSE\";\n const marksAwardedIfCorrect = question?.points || 0;\n const correctAnswer = isMarkableByAlgo\n ? question?.type === \"MULTIPLE_CHOICE\"\n ? (question?.options as MCQOptions)?.find((o) => o.isCorrect)?.id\n : question?.answer?.toString()\n : null;\n\n const existingResponse = worksheetResponse.responses[0];\n\n if (existingResponse) {\n await updateStudentQuestionProgress(existingResponse.id, {\n response,\n ...(isMarkableByAlgo && {\n isCorrect: response === correctAnswer,\n }),\n ...(isMarkableByAlgo && {\n points: response === correctAnswer ? marksAwardedIfCorrect : 0,\n }),\n status: GenerationStatus.NOT_STARTED,\n });\n } else {\n await createStudentQuestionProgress({\n studentId: worksheetResponse.studentId,\n questionId,\n response,\n studentWorksheetResponseId: worksheetResponseId,\n ...(isMarkableByAlgo && {\n isCorrect: response === correctAnswer,\n }),\n ...(isMarkableByAlgo && {\n points: response === correctAnswer ? marksAwardedIfCorrect : 0,\n }),\n });\n }\n\n const updated = await prisma.studentWorksheetResponse.findUnique({\n where: { id: worksheetResponseId },\n include: { responses: true },\n });\n return updated!;\n}\n\nexport async function cancelGrading(\n worksheetResponseId: string,\n progressId: string\n) {\n return cancelGradePipeline(worksheetResponseId, progressId);\n}\n\nexport async function regradeQuestion(\n worksheetResponseId: string,\n progressId: string\n) {\n return regradeWorksheetPipeline(worksheetResponseId, progressId);\n}\n\nexport async function gradeAnswer(\n questionId: string,\n studentWorksheetResponseId: string,\n data: {\n responseId?: string;\n response?: string;\n isCorrect: boolean;\n feedback?: string;\n markschemeState?: object;\n points?: number;\n }\n) {\n if (data.responseId) {\n return updateStudentQuestionProgressForGrading(data.responseId, {\n isCorrect: data.isCorrect,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points,\n });\n }\n\n const worksheetResponse = await prisma.studentWorksheetResponse.findUnique({\n where: { id: studentWorksheetResponseId },\n select: { studentId: true },\n });\n if (!worksheetResponse) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Student worksheet response not found\",\n });\n }\n\n const existing = await findStudentQuestionProgress(\n worksheetResponse.studentId,\n questionId,\n studentWorksheetResponseId\n );\n\n if (existing) {\n return updateStudentQuestionProgressForGrading(existing.id, {\n isCorrect: data.isCorrect,\n response: data.response,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points,\n });\n }\n\n return createStudentQuestionProgressForGrading({\n studentId: worksheetResponse.studentId,\n questionId,\n studentWorksheetResponseId,\n response: data.response || \"\",\n isCorrect: data.isCorrect,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points || 0,\n });\n}\n\nexport async function addCommentToResponse(\n responseId: string,\n comment: string,\n authorId: string\n) {\n return createComment({\n studentQuestionProgressId: responseId,\n content: comment,\n authorId,\n });\n}\n"],"names":[],"mappings":"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","debug_id":"cffbcf20-cef6-5fd4-979f-670d50592d0a"}
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/socket/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,MAAM,EAAE,MAAM,WAAW,CAAC;AAG3C,eAAO,MAAM,mBAAmB,GAAI,IAAI,MAAM,SA2I7C,CAAC"}
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"/","sources":["socket/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,MAAM,EAAE,MAAM,WAAW,CAAC;AAG3C,eAAO,MAAM,mBAAmB,GAAI,IAAI,MAAM,SA2I7C,CAAC"}
@@ -1,3 +1,5 @@
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]="92ec20c8-1718-5296-ae42-a3a241a1dae3")}catch(e){}}();
1
3
  import { logger } from '../utils/logger.js';
2
4
  export const setupSocketHandlers = (io) => {
3
5
  io.on('connection', (socket) => {
@@ -124,3 +126,5 @@ export const setupSocketHandlers = (io) => {
124
126
  });
125
127
  });
126
128
  };
129
+ //# sourceMappingURL=handlers.js.map
130
+ //# debugId=92ec20c8-1718-5296-ae42-a3a241a1dae3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.js","sources":["socket/handlers.ts"],"sourceRoot":"/","sourcesContent":["import { Socket, Server } from 'socket.io';\nimport { logger } from '../utils/logger.js';\n\nexport const setupSocketHandlers = (io: Server) => {\n io.on('connection', (socket: Socket) => {\n logger.info('Client connected', { socketId: socket.id });\n\n socket.on('disconnect', (reason: string) => {\n logger.info('Client disconnected', { socketId: socket.id, reason });\n });\n\n socket.on('error', (error: Error) => {\n logger.error('Socket error', { socketId: socket.id, error });\n });\n\n // Class Room Management\n socket.on('create-class', (data: { class: any }) => {\n io.emit('class-created', data.class);\n logger.info('Class created', { class: data.class });\n });\n\n socket.on('delete-class', (data: { classId: string }) => {\n io.emit('class-deleted', data.classId);\n logger.info('Class deleted', { classId: data.classId });\n });\n\n socket.on('update-class', (data: { class: any }) => {\n io.emit('class-updated', data.class);\n logger.info('Class updated', { class: data.class });\n });\n\n socket.on('join-class', (classId: string, callback: (classId: string) => void) => {\n try {\n socket.join(`class-${classId}`);\n logger.info('Client joined class room', { socketId: socket.id, classId });\n \n if (callback) {\n callback(classId);\n } else {\n socket.emit('joined-class', classId);\n }\n } catch (error) {\n logger.error('Error joining class room', { socketId: socket.id, classId, error });\n if (callback) {\n callback(classId);\n }\n }\n });\n\n // Assignment Events\n socket.on('assignment-create', (data: { classId: string, assignment: any }) => {\n if (data.classId && data.assignment) {\n io.in(`class-${data.classId}`).emit('assignment-created', data.assignment);\n logger.info('Assignment created', { classId: data.classId, assignmentId: data.assignment.id });\n } else {\n logger.error('Invalid assignment data format', { data });\n }\n });\n\n socket.on('assignment-update', (data: { classId: string, assignment: any }) => {\n io.in(`class-${data.classId}`).emit('assignment-updated', data.assignment);\n logger.info('Assignment updated', { classId: data.classId, assignmentId: data.assignment.id });\n });\n\n socket.on('assignment-delete', (data: { classId: string, assignmentId: string }) => {\n io.in(`class-${data.classId}`).emit('assignment-deleted', data.assignmentId);\n logger.info('Assignment deleted', { classId: data.classId, assignmentId: data.assignmentId });\n });\n\n // Submission Events\n socket.on('submission-update', (data: { classId: string, submission: any }) => {\n io.in(`class-${data.classId}`).emit('submission-updated', data.submission);\n logger.info('Submission updated', { classId: data.classId, submissionId: data.submission.id });\n });\n\n // Announcement Events\n socket.on('new-announcement', (data: { classId: string, announcement: any }) => {\n io.in(`class-${data.classId}`).emit('announcement-created', data.announcement);\n logger.info('New announcement created', { classId: data.classId, announcementId: data.announcement.id });\n });\n\n // Section Events\n socket.on('section-create', (data: { classId: string, section: any }) => {\n io.in(`class-${data.classId}`).emit('section-created', data.section);\n logger.info('Section created', { classId: data.classId, sectionId: data.section.id });\n });\n\n socket.on('section-update', (data: { classId: string, section: any }) => {\n io.in(`class-${data.classId}`).emit('section-updated', data.section);\n logger.info('Section updated', { classId: data.classId, sectionId: data.section.id });\n });\n\n socket.on('section-delete', (data: { classId: string, sectionId: string }) => {\n io.in(`class-${data.classId}`).emit('section-deleted', data.sectionId);\n logger.info('Section deleted', { classId: data.classId, sectionId: data.sectionId });\n });\n\n // Member Events\n socket.on('member-update', (data: { classId: string, member: any }) => {\n io.in(`class-${data.classId}`).emit('member-updated', data.member);\n logger.info('Member updated', { classId: data.classId, memberId: data.member.id });\n });\n\n socket.on('member-delete', (data: { classId: string, memberId: string }) => {\n io.in(`class-${data.classId}`).emit('member-deleted', data.memberId);\n logger.info('Member deleted', { classId: data.classId, memberId: data.memberId });\n });\n\n // Attendance Events\n socket.on('attendance-update', (data: { classId: string, attendance: any }) => {\n io.in(`class-${data.classId}`).emit('attendance-updated', data.attendance);\n logger.info('Attendance updated', { classId: data.classId, attendanceId: data.attendance.id });\n });\n\n // Event Events\n socket.on('event-create', (data: { classId: string, event: any }) => {\n if (data.classId) {\n io.in(`class-${data.classId}`).emit('event-created', data.event);\n } else {\n io.emit('event-created', data.event);\n }\n logger.info('Event created', { classId: data.classId, eventId: data.event.id });\n });\n\n socket.on('event-update', (data: { classId: string, event: any }) => {\n if (data.classId) {\n io.in(`class-${data.classId}`).emit('event-updated', data.event);\n } else {\n io.emit('event-updated', data.event);\n }\n logger.info('Event updated', { classId: data.classId, eventId: data.event.id });\n });\n\n socket.on('event-delete', (data: { classId: string, eventId: string }) => {\n if (data.classId) {\n io.in(`class-${data.classId}`).emit('event-deleted', data.eventId);\n } else {\n io.emit('event-deleted', data.eventId);\n }\n logger.info('Event deleted', { classId: data.classId, eventId: data.eventId });\n });\n });\n}; "],"names":[],"mappings":"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","debug_id":"92ec20c8-1718-5296-ae42-a3a241a1dae3"}
@@ -1 +1 @@
1
- {"version":3,"file":"trpc.d.ts","sourceRoot":"","sources":["../src/trpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,SAAS,EAAE,MAAM,cAAc,CAAC;AAMnD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAqB,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEnF,UAAU,oBAAoB;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;CACf;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;IACd,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,MAAM,oBAAoB,KAAG,OAAO,CAAC,OAAO,CAwBnF,CAAC;AAEF,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BZ,CAAC;AAOH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;EAAW,CAAC;AACzC,eAAO,MAAM,eAAe,yOAAqC,CAAC;AAGlE,eAAO,MAAM,kBAAkB,yOAAgC,CAAC;AAChE,eAAO,MAAM,6BAA6B;;;;uHAEnB,CAAC;AACxB,eAAO,MAAM,yBAAyB;;;;uHAEd,CAAC;AAIzB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;EAAwB,CAAC"}
1
+ {"version":3,"file":"trpc.d.ts","sourceRoot":"/","sources":["trpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,SAAS,EAAE,MAAM,cAAc,CAAC;AAMnD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAqB,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGnF,UAAU,oBAAoB;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;CACf;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,QAAQ,CAAC;IACd,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,MAAM,oBAAoB,KAAG,OAAO,CAAC,OAAO,CAwBnF,CAAC;AAEF,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BZ,CAAC;AAOH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;EAAW,CAAC;AACzC,eAAO,MAAM,eAAe,yOAAqC,CAAC;AAIlE,eAAO,MAAM,kBAAkB,yOAAgC,CAAC;AAEhE,eAAO,MAAM,6BAA6B;;;;uHAEnB,CAAC;AAExB,eAAO,MAAM,yBAAyB;;;;uHAEd,CAAC;AAIzB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;EAAwB,CAAC"}
package/dist/trpc.js CHANGED
@@ -1,3 +1,5 @@
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]="fe8afe09-5435-5257-8a3f-ef011f89e860")}catch(e){}}();
1
3
  import { initTRPC } from '@trpc/server';
2
4
  import { ZodError } from 'zod';
3
5
  import { logger } from './utils/logger.js';
@@ -74,3 +76,5 @@ export const protectedTeacherProcedure = protectedProcedure
74
76
  .use(isTeacherInClass);
75
77
  // Create caller factory
76
78
  export const createCallerFactory = t.createCallerFactory;
79
+ //# sourceMappingURL=trpc.js.map
80
+ //# debugId=fe8afe09-5435-5257-8a3f-ef011f89e860
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trpc.js","sources":["trpc.ts"],"sourceRoot":"/","sourcesContent":["import { initTRPC, TRPCError } from '@trpc/server';\nimport { ZodError } from 'zod';\nimport { logger } from './utils/logger.js';\nimport { prisma } from './lib/prisma.js';\nimport { createLoggingMiddleware } from './middleware/logging.js';\nimport { createAuthMiddleware } from './middleware/auth.js';\nimport { Request, Response } from 'express';\nimport { z } from 'zod';\nimport { handlePrismaError, PrismaErrorInfo } from './utils/prismaErrorHandler.js';\nimport { generalLimiter } from './middleware/security.js';\n\ninterface CreateContextOptions {\n req: Request;\n res: Response;\n}\n\nexport type Context = {\n req: Request;\n res: Response;\n user: { id: string } | null;\n meta?: {\n classId?: string;\n institutionId?: string;\n };\n};\n\nexport const createTRPCContext = async (opts: CreateContextOptions): Promise<Context> => {\n const { req, res } = opts;\n \n // Get user from session/token\n const token = req.headers.authorization?.split(' ')[1];\n const user = token ? await prisma.user.findFirst({\n where: {\n sessions: {\n some: {\n id: token\n }\n },\n },\n select: {\n id: true,\n }\n }) : null;\n \n return {\n req,\n res,\n user,\n meta: {},\n };\n};\n\nexport const t = initTRPC.context<Context>().create({\n errorFormatter({ shape, error }) {\n // Handle Prisma errors specifically\n let prismaErrorInfo: PrismaErrorInfo | null = null;\n if (error.cause) {\n try {\n prismaErrorInfo = handlePrismaError(error.cause);\n } catch (e) {\n // If Prisma error handling fails, continue with normal error handling\n }\n }\n\n logger.error('tRPC Error', {\n code: shape.code,\n message: error.message,\n cause: error.cause,\n stack: error.stack,\n prismaError: prismaErrorInfo,\n });\n\n return {\n ...shape,\n data: {\n ...shape.data,\n zodError:\n error.cause instanceof ZodError ? error.cause.flatten() : null,\n prismaError: prismaErrorInfo,\n },\n };\n },\n});\n\n// Create middleware\nconst loggingMiddleware = createLoggingMiddleware(t);\nconst { isAuthed, isMemberInClass, isTeacherInClass } = createAuthMiddleware(t);\n\n// Base procedures\nexport const createTRPCRouter = t.router;\nexport const publicProcedure = t.procedure.use(loggingMiddleware);\n\n\n// Protected procedures\nexport const protectedProcedure = publicProcedure.use(isAuthed);\n\nexport const protectedClassMemberProcedure = protectedProcedure\n .input(z.object({ classId: z.string() }).passthrough())\n .use(isMemberInClass);\n\nexport const protectedTeacherProcedure = protectedProcedure\n .input(z.object({ classId: z.string() }).passthrough())\n .use(isTeacherInClass);\n\n\n// Create caller factory\nexport const createCallerFactory = t.createCallerFactory; "],"names":[],"mappings":";;AAAA,OAAO,EAAE,QAAQ,EAAa,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAmB,MAAM,+BAA+B,CAAC;AAkBnF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAA0B,EAAoB,EAAE;IACtF,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAE1B,8BAA8B;IAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QAC/C,KAAK,EAAE;YACL,QAAQ,EAAE;gBACR,IAAI,EAAE;oBACJ,EAAE,EAAE,KAAK;iBACV;aACF;SACF;QACD,MAAM,EAAE;YACN,EAAE,EAAE,IAAI;SACT;KACF,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEV,OAAO;QACL,GAAG;QACH,GAAG;QACH,IAAI;QACJ,IAAI,EAAE,EAAE;KACT,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAW,CAAC,MAAM,CAAC;IAClD,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE;QAC7B,oCAAoC;QACpC,IAAI,eAAe,GAA2B,IAAI,CAAC;QACnD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,eAAe,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,sEAAsE;YACxE,CAAC;QACH,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE;YACzB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,WAAW,EAAE,eAAe;SAC7B,CAAC,CAAC;QAEH,OAAO;YACL,GAAG,KAAK;YACR,IAAI,EAAE;gBACJ,GAAG,KAAK,CAAC,IAAI;gBACb,QAAQ,EACN,KAAK,CAAC,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI;gBAChE,WAAW,EAAE,eAAe;aAC7B;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,oBAAoB;AACpB,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,CAAC,CAAC,CAAC;AACrD,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAEhF,kBAAkB;AAClB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;AACzC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAGlE,uBAAuB;AACvB,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAEhE,MAAM,CAAC,MAAM,6BAA6B,GAAG,kBAAkB;KAC5D,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;KACtD,GAAG,CAAC,eAAe,CAAC,CAAC;AAExB,MAAM,CAAC,MAAM,yBAAyB,GAAG,kBAAkB;KACxD,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;KACtD,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAGzB,wBAAwB;AACxB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,mBAAmB,CAAC","debug_id":"fe8afe09-5435-5257-8a3f-ef011f89e860"}
@@ -1 +1 @@
1
- {"version":3,"file":"trpc.d.ts","sourceRoot":"","sources":["../../src/types/trpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG,oBAAoB,CAAC,OAAO,iBAAiB,CAAC,GAAG;IACrE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACzD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
1
+ {"version":3,"file":"trpc.d.ts","sourceRoot":"/","sources":["types/trpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG,oBAAoB,CAAC,OAAO,iBAAiB,CAAC,GAAG;IACrE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACzD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
@@ -1 +1,5 @@
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]="90f06931-895d-59bc-8f08-8fd56e271d40")}catch(e){}}();
1
3
  export {};
4
+ //# sourceMappingURL=trpc.js.map
5
+ //# debugId=90f06931-895d-59bc-8f08-8fd56e271d40
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trpc.js","sources":["types/trpc.ts"],"sourceRoot":"/","sourcesContent":["import { inferAsyncReturnType } from '@trpc/server';\nimport { createTRPCContext } from '../trpc.js';\n\nexport type Context = inferAsyncReturnType<typeof createTRPCContext> & {\n isTeacher?: boolean;\n teacherClassIds?: string[];\n};\n\nexport interface MiddlewareContext {\n ctx: Context;\n next: (opts?: { ctx: Partial<Context> }) => Promise<any>;\n input?: any;\n path?: string;\n type?: string;\n} "],"names":[],"mappings":"","debug_id":"90f06931-895d-59bc-8f08-8fd56e271d40"}
@@ -1,6 +1,4 @@
1
- /**
2
- * Ensure AI assistant user exists in the database
3
- */
1
+ /** Ensure AI assistant user exists in the database. */
4
2
  export declare function ensureAIUserExists(): Promise<void>;
5
3
  /**
6
4
  * Get the AI user ID
@@ -1 +1 @@
1
- {"version":3,"file":"aiUser.d.ts","sourceRoot":"","sources":["../../src/utils/aiUser.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0CxD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhD"}
1
+ {"version":3,"file":"aiUser.d.ts","sourceRoot":"/","sources":["utils/aiUser.ts"],"names":[],"mappings":"AAQA,uDAAuD;AACvD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0CxD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhD"}