@studious-lms/server 1.2.53 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (479) hide show
  1. package/.coderabbit.yaml +9 -0
  2. package/.env.example +9 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +102 -8
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/config/env.d.ts +21 -0
  7. package/dist/lib/config/env.d.ts.map +1 -1
  8. package/dist/lib/config/env.js +8 -2
  9. package/dist/lib/config/env.js.map +1 -1
  10. package/dist/lib/fileUpload.d.ts.map +1 -1
  11. package/dist/lib/fileUpload.js +2 -2
  12. package/dist/lib/fileUpload.js.map +1 -1
  13. package/dist/lib/googleCloudStorage.d.ts +6 -0
  14. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  15. package/dist/lib/googleCloudStorage.js +19 -2
  16. package/dist/lib/googleCloudStorage.js.map +1 -1
  17. package/dist/lib/pusher.d.ts +4 -1
  18. package/dist/lib/pusher.d.ts.map +1 -1
  19. package/dist/lib/pusher.js +6 -3
  20. package/dist/lib/pusher.js.map +1 -1
  21. package/dist/lib/redis.d.ts +5 -0
  22. package/dist/lib/redis.d.ts.map +1 -0
  23. package/dist/lib/redis.js +53 -0
  24. package/dist/lib/redis.js.map +1 -0
  25. package/dist/lib/thumbnailGenerator.d.ts +0 -21
  26. package/dist/lib/thumbnailGenerator.d.ts.map +1 -1
  27. package/dist/lib/thumbnailGenerator.js +157 -160
  28. package/dist/lib/thumbnailGenerator.js.map +1 -1
  29. package/dist/middleware/auth.d.ts.map +1 -1
  30. package/dist/middleware/auth.js +33 -95
  31. package/dist/middleware/auth.js.map +1 -1
  32. package/dist/models/agenda.d.ts +97 -0
  33. package/dist/models/agenda.d.ts.map +1 -0
  34. package/dist/models/agenda.js +40 -0
  35. package/dist/models/agenda.js.map +1 -0
  36. package/dist/models/announcement.d.ts +223 -0
  37. package/dist/models/announcement.d.ts.map +1 -0
  38. package/dist/models/announcement.js +120 -0
  39. package/dist/models/announcement.js.map +1 -0
  40. package/dist/models/assignment.d.ts +1292 -0
  41. package/dist/models/assignment.d.ts.map +1 -0
  42. package/dist/models/assignment.js +309 -0
  43. package/dist/models/assignment.js.map +1 -0
  44. package/dist/models/attendance.d.ts +180 -0
  45. package/dist/models/attendance.d.ts.map +1 -0
  46. package/dist/models/attendance.js +188 -0
  47. package/dist/models/attendance.js.map +1 -0
  48. package/dist/models/auth.d.ts +153 -0
  49. package/dist/models/auth.d.ts.map +1 -0
  50. package/dist/models/auth.js +217 -0
  51. package/dist/models/auth.js.map +1 -0
  52. package/dist/models/class.d.ts +461 -0
  53. package/dist/models/class.d.ts.map +1 -0
  54. package/dist/models/class.js +645 -0
  55. package/dist/models/class.js.map +1 -0
  56. package/dist/models/comment.d.ts +171 -0
  57. package/dist/models/comment.d.ts.map +1 -0
  58. package/dist/models/comment.js +138 -0
  59. package/dist/models/comment.js.map +1 -0
  60. package/dist/models/conversation.d.ts +164 -0
  61. package/dist/models/conversation.d.ts.map +1 -0
  62. package/dist/models/conversation.js +175 -0
  63. package/dist/models/conversation.js.map +1 -0
  64. package/dist/models/event.d.ts +295 -0
  65. package/dist/models/event.d.ts.map +1 -0
  66. package/dist/models/event.js +145 -0
  67. package/dist/models/event.js.map +1 -0
  68. package/dist/models/file.d.ts +536 -0
  69. package/dist/models/file.d.ts.map +1 -0
  70. package/dist/models/file.js +126 -0
  71. package/dist/models/file.js.map +1 -0
  72. package/dist/models/folder.d.ts +295 -0
  73. package/dist/models/folder.d.ts.map +1 -0
  74. package/dist/models/folder.js +202 -0
  75. package/dist/models/folder.js.map +1 -0
  76. package/dist/models/labChat.d.ts +243 -0
  77. package/dist/models/labChat.d.ts.map +1 -0
  78. package/dist/models/labChat.js +204 -0
  79. package/dist/models/labChat.js.map +1 -0
  80. package/dist/models/marketing.d.ts +72 -0
  81. package/dist/models/marketing.d.ts.map +1 -0
  82. package/dist/models/marketing.js +26 -0
  83. package/dist/models/marketing.js.map +1 -0
  84. package/dist/models/message.d.ts +100 -0
  85. package/dist/models/message.d.ts.map +1 -0
  86. package/dist/models/message.js +131 -0
  87. package/dist/models/message.js.map +1 -0
  88. package/dist/models/newtonChat.d.ts +72 -0
  89. package/dist/models/newtonChat.d.ts.map +1 -0
  90. package/dist/models/newtonChat.js +61 -0
  91. package/dist/models/newtonChat.js.map +1 -0
  92. package/dist/models/notification.d.ts +65 -0
  93. package/dist/models/notification.d.ts.map +1 -0
  94. package/dist/models/notification.js +46 -0
  95. package/dist/models/notification.js.map +1 -0
  96. package/dist/models/section.d.ts +102 -0
  97. package/dist/models/section.d.ts.map +1 -0
  98. package/dist/models/section.js +83 -0
  99. package/dist/models/section.js.map +1 -0
  100. package/dist/models/user.d.ts +39 -0
  101. package/dist/models/user.d.ts.map +1 -0
  102. package/dist/models/user.js +38 -0
  103. package/dist/models/user.js.map +1 -0
  104. package/dist/models/worksheet.d.ts +460 -0
  105. package/dist/models/worksheet.d.ts.map +1 -0
  106. package/dist/models/worksheet.js +200 -0
  107. package/dist/models/worksheet.js.map +1 -0
  108. package/dist/pipelines/aiLabChat.d.ts +76 -0
  109. package/dist/pipelines/aiLabChat.d.ts.map +1 -0
  110. package/dist/pipelines/aiLabChat.js +599 -0
  111. package/dist/pipelines/aiLabChat.js.map +1 -0
  112. package/dist/pipelines/aiNewtonChat.d.ts +30 -0
  113. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -0
  114. package/dist/pipelines/aiNewtonChat.js +289 -0
  115. package/dist/pipelines/aiNewtonChat.js.map +1 -0
  116. package/dist/pipelines/gradeWorksheet.d.ts +30 -0
  117. package/dist/pipelines/gradeWorksheet.d.ts.map +1 -0
  118. package/dist/pipelines/gradeWorksheet.js +252 -0
  119. package/dist/pipelines/gradeWorksheet.js.map +1 -0
  120. package/dist/routers/_app.d.ts +1523 -1315
  121. package/dist/routers/_app.d.ts.map +1 -1
  122. package/dist/routers/agenda.d.ts +22 -22
  123. package/dist/routers/agenda.d.ts.map +1 -1
  124. package/dist/routers/agenda.js +4 -65
  125. package/dist/routers/agenda.js.map +1 -1
  126. package/dist/routers/announcement.d.ts +16 -16
  127. package/dist/routers/announcement.d.ts.map +1 -1
  128. package/dist/routers/announcement.js +37 -446
  129. package/dist/routers/announcement.js.map +1 -1
  130. package/dist/routers/assignment.d.ts +300 -378
  131. package/dist/routers/assignment.d.ts.map +1 -1
  132. package/dist/routers/assignment.js +78 -1868
  133. package/dist/routers/assignment.js.map +1 -1
  134. package/dist/routers/attendance.d.ts +19 -9
  135. package/dist/routers/attendance.d.ts.map +1 -1
  136. package/dist/routers/attendance.js +7 -264
  137. package/dist/routers/attendance.js.map +1 -1
  138. package/dist/routers/auth.d.ts +2 -2
  139. package/dist/routers/auth.d.ts.map +1 -1
  140. package/dist/routers/auth.js +29 -354
  141. package/dist/routers/auth.js.map +1 -1
  142. package/dist/routers/class.d.ts +160 -68
  143. package/dist/routers/class.d.ts.map +1 -1
  144. package/dist/routers/class.js +82 -1052
  145. package/dist/routers/class.js.map +1 -1
  146. package/dist/routers/comment.d.ts +6 -42
  147. package/dist/routers/comment.d.ts.map +1 -1
  148. package/dist/routers/comment.js +24 -244
  149. package/dist/routers/comment.js.map +1 -1
  150. package/dist/routers/conversation.d.ts +45 -7
  151. package/dist/routers/conversation.d.ts.map +1 -1
  152. package/dist/routers/conversation.js +19 -327
  153. package/dist/routers/conversation.js.map +1 -1
  154. package/dist/routers/event.d.ts +36 -36
  155. package/dist/routers/event.d.ts.map +1 -1
  156. package/dist/routers/event.js +13 -433
  157. package/dist/routers/event.js.map +1 -1
  158. package/dist/routers/file.d.ts +2 -2
  159. package/dist/routers/file.d.ts.map +1 -1
  160. package/dist/routers/file.js +9 -323
  161. package/dist/routers/file.js.map +1 -1
  162. package/dist/routers/folder.d.ts +21 -14
  163. package/dist/routers/folder.d.ts.map +1 -1
  164. package/dist/routers/folder.js +34 -745
  165. package/dist/routers/folder.js.map +1 -1
  166. package/dist/routers/labChat.d.ts +21 -11
  167. package/dist/routers/labChat.d.ts.map +1 -1
  168. package/dist/routers/labChat.js +22 -570
  169. package/dist/routers/labChat.js.map +1 -1
  170. package/dist/routers/marketing.d.ts +1 -1
  171. package/dist/routers/marketing.d.ts.map +1 -1
  172. package/dist/routers/marketing.js +7 -56
  173. package/dist/routers/marketing.js.map +1 -1
  174. package/dist/routers/message.d.ts +13 -2
  175. package/dist/routers/message.d.ts.map +1 -1
  176. package/dist/routers/message.js +32 -520
  177. package/dist/routers/message.js.map +1 -1
  178. package/dist/routers/newtonChat.d.ts +1 -1
  179. package/dist/routers/newtonChat.d.ts.map +1 -1
  180. package/dist/routers/newtonChat.js +7 -246
  181. package/dist/routers/newtonChat.js.map +1 -1
  182. package/dist/routers/notifications.d.ts +4 -4
  183. package/dist/routers/notifications.d.ts.map +1 -1
  184. package/dist/routers/notifications.js +18 -83
  185. package/dist/routers/notifications.js.map +1 -1
  186. package/dist/routers/section.d.ts +4 -4
  187. package/dist/routers/section.d.ts.map +1 -1
  188. package/dist/routers/section.js +14 -286
  189. package/dist/routers/section.js.map +1 -1
  190. package/dist/routers/user.d.ts +1 -1
  191. package/dist/routers/user.d.ts.map +1 -1
  192. package/dist/routers/user.js +32 -207
  193. package/dist/routers/user.js.map +1 -1
  194. package/dist/routers/worksheet.d.ts +68 -55
  195. package/dist/routers/worksheet.d.ts.map +1 -1
  196. package/dist/routers/worksheet.js +79 -394
  197. package/dist/routers/worksheet.js.map +1 -1
  198. package/dist/seedDatabase.d.ts +1 -1
  199. package/dist/server/pipelines/gradeWorksheet.d.ts +6 -6
  200. package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -1
  201. package/dist/server/pipelines/gradeWorksheet.js +12 -5
  202. package/dist/server/pipelines/gradeWorksheet.js.map +1 -1
  203. package/dist/services/agenda.d.ts +100 -0
  204. package/dist/services/agenda.d.ts.map +1 -0
  205. package/dist/services/agenda.js +21 -0
  206. package/dist/services/agenda.js.map +1 -0
  207. package/dist/services/announcement.d.ts +135 -0
  208. package/dist/services/announcement.d.ts.map +1 -0
  209. package/dist/services/announcement.js +223 -0
  210. package/dist/services/announcement.js.map +1 -0
  211. package/dist/services/assignment.d.ts +1462 -0
  212. package/dist/services/assignment.d.ts.map +1 -0
  213. package/dist/services/assignment.js +898 -0
  214. package/dist/services/assignment.js.map +1 -0
  215. package/dist/services/attendance.d.ts +93 -0
  216. package/dist/services/attendance.d.ts.map +1 -0
  217. package/dist/services/attendance.js +61 -0
  218. package/dist/services/attendance.js.map +1 -0
  219. package/dist/services/auth.d.ts +68 -0
  220. package/dist/services/auth.d.ts.map +1 -0
  221. package/dist/services/auth.js +218 -0
  222. package/dist/services/auth.js.map +1 -0
  223. package/dist/services/class.d.ts +643 -0
  224. package/dist/services/class.d.ts.map +1 -0
  225. package/dist/services/class.js +486 -0
  226. package/dist/services/class.js.map +1 -0
  227. package/dist/services/comment.d.ts +100 -0
  228. package/dist/services/comment.d.ts.map +1 -0
  229. package/dist/services/comment.js +83 -0
  230. package/dist/services/comment.js.map +1 -0
  231. package/dist/services/conversation.d.ts +159 -0
  232. package/dist/services/conversation.d.ts.map +1 -0
  233. package/dist/services/conversation.js +138 -0
  234. package/dist/services/conversation.js.map +1 -0
  235. package/dist/services/event.d.ts +216 -0
  236. package/dist/services/event.d.ts.map +1 -0
  237. package/dist/services/event.js +168 -0
  238. package/dist/services/event.js.map +1 -0
  239. package/dist/services/file.d.ts +74 -0
  240. package/dist/services/file.d.ts.map +1 -0
  241. package/dist/services/file.js +133 -0
  242. package/dist/services/file.js.map +1 -0
  243. package/dist/services/folder.d.ts +239 -0
  244. package/dist/services/folder.d.ts.map +1 -0
  245. package/dist/services/folder.js +248 -0
  246. package/dist/services/folder.js.map +1 -0
  247. package/dist/services/labChat.d.ts +169 -0
  248. package/dist/services/labChat.d.ts.map +1 -0
  249. package/dist/services/labChat.js +381 -0
  250. package/dist/services/labChat.js.map +1 -0
  251. package/dist/services/marketing.d.ts +50 -0
  252. package/dist/services/marketing.d.ts.map +1 -0
  253. package/dist/services/marketing.js +32 -0
  254. package/dist/services/marketing.js.map +1 -0
  255. package/dist/services/message.d.ts +103 -0
  256. package/dist/services/message.d.ts.map +1 -0
  257. package/dist/services/message.js +422 -0
  258. package/dist/services/message.js.map +1 -0
  259. package/dist/services/newtonChat.d.ts +22 -0
  260. package/dist/services/newtonChat.d.ts.map +1 -0
  261. package/dist/services/newtonChat.js +174 -0
  262. package/dist/services/newtonChat.js.map +1 -0
  263. package/dist/services/notification.d.ts +65 -0
  264. package/dist/services/notification.d.ts.map +1 -0
  265. package/dist/services/notification.js +33 -0
  266. package/dist/services/notification.js.map +1 -0
  267. package/dist/services/section.d.ts +53 -0
  268. package/dist/services/section.d.ts.map +1 -0
  269. package/dist/services/section.js +199 -0
  270. package/dist/services/section.js.map +1 -0
  271. package/dist/services/user.d.ts +48 -0
  272. package/dist/services/user.d.ts.map +1 -0
  273. package/dist/services/user.js +141 -0
  274. package/dist/services/user.js.map +1 -0
  275. package/dist/services/worksheet.d.ts +239 -0
  276. package/dist/services/worksheet.d.ts.map +1 -0
  277. package/dist/services/worksheet.js +235 -0
  278. package/dist/services/worksheet.js.map +1 -0
  279. package/dist/utils/aiUser.d.ts +1 -3
  280. package/dist/utils/aiUser.d.ts.map +1 -1
  281. package/dist/utils/aiUser.js +6 -5
  282. package/dist/utils/aiUser.js.map +1 -1
  283. package/dist/utils/email.d.ts +3 -0
  284. package/dist/utils/email.d.ts.map +1 -1
  285. package/dist/utils/email.js +7 -4
  286. package/dist/utils/email.js.map +1 -1
  287. package/dist/utils/generateInviteCode.d.ts +1 -2
  288. package/dist/utils/generateInviteCode.d.ts.map +1 -1
  289. package/dist/utils/generateInviteCode.js +3 -4
  290. package/dist/utils/generateInviteCode.js.map +1 -1
  291. package/dist/utils/inference.d.ts +3 -0
  292. package/dist/utils/inference.d.ts.map +1 -1
  293. package/dist/utils/inference.js +7 -4
  294. package/dist/utils/inference.js.map +1 -1
  295. package/dist/utils/logger.d.ts +3 -0
  296. package/dist/utils/logger.d.ts.map +1 -1
  297. package/dist/utils/logger.js +5 -2
  298. package/dist/utils/logger.js.map +1 -1
  299. package/dist/utils/prismaErrorHandler.d.ts.map +1 -1
  300. package/dist/utils/prismaErrorHandler.js +5 -2
  301. package/dist/utils/prismaErrorHandler.js.map +1 -1
  302. package/dist/utils/prismaWrapper.d.ts +1 -0
  303. package/dist/utils/prismaWrapper.d.ts.map +1 -1
  304. package/dist/utils/prismaWrapper.js +6 -2
  305. package/dist/utils/prismaWrapper.js.map +1 -1
  306. package/docker-compose.yml +5 -0
  307. package/package.json +4 -3
  308. package/prisma/schema.prisma +1 -1
  309. package/src/index.ts +119 -12
  310. package/src/lib/config/env.ts +6 -0
  311. package/src/lib/fileUpload.ts +0 -1
  312. package/src/lib/googleCloudStorage.ts +17 -0
  313. package/src/lib/pusher.ts +5 -1
  314. package/src/lib/redis.ts +56 -0
  315. package/src/lib/thumbnailGenerator.ts +170 -168
  316. package/src/middleware/auth.ts +80 -137
  317. package/src/models/agenda.ts +46 -0
  318. package/src/models/announcement.ts +134 -0
  319. package/src/models/assignment.ts +322 -0
  320. package/src/models/attendance.ts +208 -0
  321. package/src/models/auth.ts +247 -0
  322. package/src/models/class.ts +703 -0
  323. package/src/models/comment.ts +152 -0
  324. package/src/models/conversation.ts +200 -0
  325. package/src/models/event.ts +177 -0
  326. package/src/models/file.ts +129 -0
  327. package/src/models/folder.ts +225 -0
  328. package/src/models/labChat.ts +213 -0
  329. package/src/models/marketing.ts +45 -0
  330. package/src/models/message.ts +153 -0
  331. package/src/models/newtonChat.ts +70 -0
  332. package/src/models/notification.ts +54 -0
  333. package/src/models/section.ts +98 -0
  334. package/src/models/user.ts +47 -0
  335. package/src/models/worksheet.ts +294 -0
  336. package/src/pipelines/aiLabChat.ts +684 -0
  337. package/src/{server/pipelines → pipelines}/aiNewtonChat.ts +9 -5
  338. package/src/{server/pipelines → pipelines}/gradeWorksheet.ts +25 -14
  339. package/src/routers/agenda.ts +3 -66
  340. package/src/routers/announcement.ts +54 -495
  341. package/src/routers/assignment.ts +126 -2018
  342. package/src/routers/attendance.ts +15 -276
  343. package/src/routers/auth.ts +79 -442
  344. package/src/routers/class.ts +263 -1187
  345. package/src/routers/comment.ts +61 -288
  346. package/src/routers/conversation.ts +51 -360
  347. package/src/routers/event.ts +50 -481
  348. package/src/routers/file.ts +45 -368
  349. package/src/routers/folder.ts +107 -836
  350. package/src/routers/labChat.ts +35 -604
  351. package/src/routers/marketing.ts +35 -77
  352. package/src/routers/message.ts +54 -567
  353. package/src/routers/newtonChat.ts +17 -278
  354. package/src/routers/notifications.ts +32 -82
  355. package/src/routers/section.ts +46 -330
  356. package/src/routers/user.ts +49 -227
  357. package/src/routers/worksheet.ts +215 -503
  358. package/src/services/agenda.ts +21 -0
  359. package/src/services/announcement.ts +290 -0
  360. package/src/services/assignment.ts +1198 -0
  361. package/src/services/attendance.ts +85 -0
  362. package/src/services/auth.ts +277 -0
  363. package/src/services/class.ts +629 -0
  364. package/src/services/comment.ts +106 -0
  365. package/src/services/conversation.ts +213 -0
  366. package/src/services/event.ts +231 -0
  367. package/src/services/file.ts +167 -0
  368. package/src/services/folder.ts +316 -0
  369. package/src/services/labChat.ts +458 -0
  370. package/src/services/marketing.ts +57 -0
  371. package/src/services/message.ts +554 -0
  372. package/src/services/newtonChat.ts +222 -0
  373. package/src/services/notification.ts +50 -0
  374. package/src/services/section.ts +283 -0
  375. package/src/services/user.ts +172 -0
  376. package/src/services/worksheet.ts +358 -0
  377. package/src/utils/aiUser.ts +4 -3
  378. package/src/utils/email.ts +5 -3
  379. package/src/utils/generateInviteCode.ts +1 -3
  380. package/src/utils/inference.ts +5 -2
  381. package/src/utils/logger.ts +3 -1
  382. package/src/utils/prismaErrorHandler.ts +3 -0
  383. package/src/utils/prismaWrapper.ts +4 -0
  384. package/tests/globalSetup.ts +62 -0
  385. package/tests/helpers.ts +22 -0
  386. package/tests/middleware/security.test.ts +42 -0
  387. package/tests/routers/agenda.test.ts +138 -0
  388. package/tests/routers/announcement.test.ts +490 -0
  389. package/tests/routers/assignment.test.ts +837 -0
  390. package/tests/{attendance.test.ts → routers/attendance.test.ts} +6 -14
  391. package/tests/routers/auth.test.ts +171 -0
  392. package/tests/{class.test.ts → routers/class.test.ts} +131 -85
  393. package/tests/routers/comment.test.ts +126 -0
  394. package/tests/routers/conversation.test.ts +145 -0
  395. package/tests/{event.test.ts → routers/event.test.ts} +93 -32
  396. package/tests/routers/folder.test.ts +178 -0
  397. package/tests/routers/labChat.test.ts +115 -0
  398. package/tests/routers/marketing.test.ts +59 -0
  399. package/tests/routers/message.test.ts +123 -0
  400. package/tests/routers/notification.test.ts +69 -0
  401. package/tests/{section.test.ts → routers/section.test.ts} +5 -13
  402. package/tests/server/rateLimit.test.ts +73 -0
  403. package/tests/setup.ts +18 -92
  404. package/tests/user.test.ts +9 -31
  405. package/tests/utils/aiUser.test.ts +22 -0
  406. package/tests/utils/generateInviteCode.test.ts +24 -0
  407. package/tests/utils/logger.test.ts +74 -0
  408. package/tests/utils/prismaErrorHandler.test.ts +101 -0
  409. package/tests/utils/prismaWrapper.test.ts +82 -0
  410. package/tests/worksheet.test.ts +181 -0
  411. package/vitest.config.ts +6 -3
  412. package/vitest.unit.config.ts +21 -0
  413. package/TODO.md +0 -2
  414. package/coverage/base.css +0 -224
  415. package/coverage/block-navigation.js +0 -87
  416. package/coverage/clover.xml +0 -12110
  417. package/coverage/coverage-final.json +0 -44
  418. package/coverage/favicon.png +0 -0
  419. package/coverage/index.html +0 -221
  420. package/coverage/prettify.css +0 -1
  421. package/coverage/prettify.js +0 -2
  422. package/coverage/server/index.html +0 -116
  423. package/coverage/server/src/exportType.ts.html +0 -109
  424. package/coverage/server/src/index.html +0 -161
  425. package/coverage/server/src/index.ts.html +0 -1702
  426. package/coverage/server/src/instrument.ts.html +0 -130
  427. package/coverage/server/src/lib/config/env.ts.html +0 -448
  428. package/coverage/server/src/lib/config/index.html +0 -116
  429. package/coverage/server/src/lib/fileUpload.ts.html +0 -1138
  430. package/coverage/server/src/lib/googleCloudStorage.ts.html +0 -334
  431. package/coverage/server/src/lib/index.html +0 -206
  432. package/coverage/server/src/lib/jsonConversion.ts.html +0 -2323
  433. package/coverage/server/src/lib/jsonStyles.ts.html +0 -193
  434. package/coverage/server/src/lib/notificationHandler.ts.html +0 -193
  435. package/coverage/server/src/lib/pusher.ts.html +0 -121
  436. package/coverage/server/src/lib/thumbnailGenerator.ts.html +0 -592
  437. package/coverage/server/src/middleware/auth.ts.html +0 -646
  438. package/coverage/server/src/middleware/index.html +0 -146
  439. package/coverage/server/src/middleware/logging.ts.html +0 -244
  440. package/coverage/server/src/middleware/security.ts.html +0 -271
  441. package/coverage/server/src/routers/_app.ts.html +0 -232
  442. package/coverage/server/src/routers/agenda.ts.html +0 -319
  443. package/coverage/server/src/routers/announcement.ts.html +0 -3481
  444. package/coverage/server/src/routers/assignment.ts.html +0 -7633
  445. package/coverage/server/src/routers/attendance.ts.html +0 -1030
  446. package/coverage/server/src/routers/auth.ts.html +0 -1081
  447. package/coverage/server/src/routers/class.ts.html +0 -3535
  448. package/coverage/server/src/routers/comment.ts.html +0 -991
  449. package/coverage/server/src/routers/conversation.ts.html +0 -982
  450. package/coverage/server/src/routers/event.ts.html +0 -1609
  451. package/coverage/server/src/routers/file.ts.html +0 -1144
  452. package/coverage/server/src/routers/folder.ts.html +0 -2797
  453. package/coverage/server/src/routers/index.html +0 -386
  454. package/coverage/server/src/routers/labChat.ts.html +0 -3073
  455. package/coverage/server/src/routers/marketing.ts.html +0 -340
  456. package/coverage/server/src/routers/message.ts.html +0 -1912
  457. package/coverage/server/src/routers/notifications.ts.html +0 -364
  458. package/coverage/server/src/routers/section.ts.html +0 -1120
  459. package/coverage/server/src/routers/user.ts.html +0 -862
  460. package/coverage/server/src/routers/worksheet.ts.html +0 -1729
  461. package/coverage/server/src/trpc.ts.html +0 -397
  462. package/coverage/server/src/types/index.html +0 -116
  463. package/coverage/server/src/types/trpc.ts.html +0 -127
  464. package/coverage/server/src/utils/aiUser.ts.html +0 -280
  465. package/coverage/server/src/utils/email.ts.html +0 -121
  466. package/coverage/server/src/utils/generateInviteCode.ts.html +0 -106
  467. package/coverage/server/src/utils/index.html +0 -206
  468. package/coverage/server/src/utils/inference.ts.html +0 -709
  469. package/coverage/server/src/utils/logger.ts.html +0 -664
  470. package/coverage/server/src/utils/prismaErrorHandler.ts.html +0 -907
  471. package/coverage/server/src/utils/prismaWrapper.ts.html +0 -355
  472. package/coverage/server/vitest.config.ts.html +0 -196
  473. package/coverage/sort-arrow-sprite.png +0 -0
  474. package/coverage/sorter.js +0 -210
  475. package/src/lib/notificationHandler.ts +0 -36
  476. package/src/server/pipelines/aiLabChat.ts +0 -507
  477. package/tests/announcement.test.ts +0 -164
  478. package/tests/assignment.test.ts +0 -296
  479. package/tests/auth.test.ts +0 -48
@@ -1,162 +1,159 @@
1
+ "use strict";
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]="8a494bec-8974-5f11-ae01-d96a89e7d69b")}catch(e){}}();
1
3
 
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]="a93ef014-63a9-5a8d-815a-01d914751573")}catch(e){}}();
3
- import sharp from 'sharp';
4
- import { getSignedUrl } from './googleCloudStorage.js';
5
- // Thumbnail size configuration
6
- const THUMBNAIL_WIDTH = 200;
7
- const THUMBNAIL_HEIGHT = 200;
8
- // File type configurations
9
- const SUPPORTED_IMAGE_TYPES = [
10
- 'image/jpeg',
11
- 'image/png',
12
- 'image/gif',
13
- 'image/webp',
14
- 'image/tiff',
15
- 'image/bmp',
16
- 'image/avif'
17
- ];
18
- const DOCUMENT_TYPES = [
19
- 'application/pdf',
20
- 'application/msword',
21
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
22
- 'application/vnd.ms-excel',
23
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
24
- 'application/vnd.ms-powerpoint',
25
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx
26
- 'text/plain',
27
- 'text/csv',
28
- 'application/json',
29
- 'text/html',
30
- 'text/javascript',
31
- 'text/css'
32
- ];
33
- const VIDEO_TYPES = [
34
- 'video/mp4',
35
- 'video/webm',
36
- 'video/ogg',
37
- 'video/quicktime'
38
- ];
39
- const AUDIO_TYPES = [
40
- 'audio/mpeg',
41
- 'audio/ogg',
42
- 'audio/wav',
43
- 'audio/webm'
44
- ];
45
- /**
46
- * Generates a thumbnail for an image or PDF file
47
- * @param fileBuffer The file buffer
48
- * @param fileType The MIME type of the file
49
- * @returns Thumbnail buffer
50
- */
51
- export async function generateMediaThumbnail(fileBuffer, fileType) {
52
- if (fileType === 'application/pdf') {
53
- // For PDFs, we need to use a different approach
54
- try {
55
- return await sharp(fileBuffer, {
56
- density: 300, // Higher density for better quality
57
- page: 0 // First page only
58
- })
59
- .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {
60
- fit: 'inside',
61
- withoutEnlargement: true,
62
- })
63
- .jpeg({ quality: 80 })
64
- .toBuffer();
65
- }
66
- catch (error) {
67
- console.warn('Failed to generate PDF thumbnail:', error);
68
- return generateGenericThumbnail(fileType);
69
- }
70
- }
71
- // For regular images
72
- return sharp(fileBuffer)
73
- .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {
74
- fit: 'inside',
75
- withoutEnlargement: true,
76
- })
77
- .jpeg({ quality: 80 })
78
- .toBuffer();
79
- }
80
- /**
81
- * Generates a generic icon-based thumbnail for a file type
82
- * @param fileType The MIME type of the file
83
- * @returns Thumbnail buffer
84
- */
85
- async function generateGenericThumbnail(fileType) {
86
- // Create a blank canvas with a colored background based on file type
87
- const canvas = sharp({
88
- create: {
89
- width: THUMBNAIL_WIDTH,
90
- height: THUMBNAIL_HEIGHT,
91
- channels: 4,
92
- background: { r: 245, g: 245, b: 245, alpha: 1 }
93
- }
94
- });
95
- // Add a colored overlay based on file type
96
- let color = { r: 200, g: 200, b: 200, alpha: 0.5 }; // Default gray
97
- if (DOCUMENT_TYPES.includes(fileType)) {
98
- color = { r: 52, g: 152, b: 219, alpha: 0.5 }; // Blue for documents
99
- }
100
- else if (VIDEO_TYPES.includes(fileType)) {
101
- color = { r: 231, g: 76, b: 60, alpha: 0.5 }; // Red for videos
102
- }
103
- else if (AUDIO_TYPES.includes(fileType)) {
104
- color = { r: 46, g: 204, b: 113, alpha: 0.5 }; // Green for audio
105
- }
106
- return canvas
107
- .composite([{
108
- input: Buffer.from([color.r, color.g, color.b, Math.floor(color.alpha * 255)]),
109
- raw: {
110
- width: 1,
111
- height: 1,
112
- channels: 4
113
- },
114
- tile: true,
115
- blend: 'overlay'
116
- }])
117
- .jpeg({ quality: 80 })
118
- .toBuffer();
119
- }
120
- /**
121
- * Generates a thumbnail for a file
122
- * @param fileName The name of the file in Google Cloud Storage
123
- * @param fileType The MIME type of the file
124
- * @returns The thumbnail buffer or null if thumbnail generation is not supported
125
- */
126
- export async function generateThumbnail(fileName, fileType) {
127
- try {
128
- const signedUrl = await getSignedUrl(fileName);
129
- const response = await fetch(signedUrl);
130
- if (!response.ok) {
131
- throw new Error(`Failed to download file from storage: ${response.status} ${response.statusText}`);
132
- }
133
- const fileBuffer = await response.arrayBuffer();
134
- if (SUPPORTED_IMAGE_TYPES.includes(fileType) || fileType === 'application/pdf') {
135
- try {
136
- const thumbnail = await generateMediaThumbnail(Buffer.from(fileBuffer), fileType);
137
- return thumbnail;
138
- }
139
- catch (error) {
140
- return generateGenericThumbnail(fileType);
141
- }
142
- }
143
- else if ([...DOCUMENT_TYPES, ...VIDEO_TYPES, ...AUDIO_TYPES].includes(fileType)) {
144
- return generateGenericThumbnail(fileType);
145
- }
146
- return null; // Unsupported file type
147
- }
148
- catch (error) {
149
- return null;
150
- }
151
- }
152
- /**
153
- * Stores a thumbnail in Google Cloud Storage and creates a File entry
154
- * @param thumbnailBuffer The thumbnail buffer to store
155
- * @param originalFileName The original file name
156
- * @param userId The user ID who owns the file
157
- * @returns The ID of the created thumbnail File
158
- */
159
- // DEPRECATED: This function is no longer used - thumbnails are generated during direct uploads
160
- // Thumbnail generation is now handled in the direct upload flow
4
+ // @deprecated: this is not used anymore
5
+ // import sharp from 'sharp';
6
+ // import { prisma } from './prisma.js';
7
+ // import { deleteFile, getSignedUrl } from './googleCloudStorage.js';
8
+ // // Thumbnail size configuration
9
+ // const THUMBNAIL_WIDTH = 200;
10
+ // const THUMBNAIL_HEIGHT = 200;
11
+ // // File type configurations
12
+ // const SUPPORTED_IMAGE_TYPES = [
13
+ // 'image/jpeg',
14
+ // 'image/png',
15
+ // 'image/gif',
16
+ // 'image/webp',
17
+ // 'image/tiff',
18
+ // 'image/bmp',
19
+ // 'image/avif'
20
+ // ];
21
+ // const DOCUMENT_TYPES = [
22
+ // 'application/pdf',
23
+ // 'application/msword',
24
+ // 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
25
+ // 'application/vnd.ms-excel',
26
+ // 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
27
+ // 'application/vnd.ms-powerpoint',
28
+ // 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx
29
+ // 'text/plain',
30
+ // 'text/csv',
31
+ // 'application/json',
32
+ // 'text/html',
33
+ // 'text/javascript',
34
+ // 'text/css'
35
+ // ];
36
+ // const VIDEO_TYPES = [
37
+ // 'video/mp4',
38
+ // 'video/webm',
39
+ // 'video/ogg',
40
+ // 'video/quicktime'
41
+ // ];
42
+ // const AUDIO_TYPES = [
43
+ // 'audio/mpeg',
44
+ // 'audio/ogg',
45
+ // 'audio/wav',
46
+ // 'audio/webm'
47
+ // ];
48
+ // /**
49
+ // * Generates a thumbnail for an image or PDF file
50
+ // * @param fileBuffer The file buffer
51
+ // * @param fileType The MIME type of the file
52
+ // * @returns Thumbnail buffer
53
+ // */
54
+ // export async function generateMediaThumbnail(fileBuffer: Buffer, fileType: string): Promise<Buffer> {
55
+ // if (fileType === 'application/pdf') {
56
+ // // For PDFs, we need to use a different approach
57
+ // try {
58
+ // return await sharp(fileBuffer, {
59
+ // density: 300, // Higher density for better quality
60
+ // page: 0 // First page only
61
+ // })
62
+ // .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {
63
+ // fit: 'inside',
64
+ // withoutEnlargement: true,
65
+ // })
66
+ // .jpeg({ quality: 80 })
67
+ // .toBuffer();
68
+ // } catch (error) {
69
+ // console.warn('Failed to generate PDF thumbnail:', error);
70
+ // return generateGenericThumbnail(fileType);
71
+ // }
72
+ // }
73
+ // // For regular images
74
+ // return sharp(fileBuffer)
75
+ // .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {
76
+ // fit: 'inside',
77
+ // withoutEnlargement: true,
78
+ // })
79
+ // .jpeg({ quality: 80 })
80
+ // .toBuffer();
81
+ // }
82
+ // /**
83
+ // * Generates a generic icon-based thumbnail for a file type
84
+ // * @param fileType The MIME type of the file
85
+ // * @returns Thumbnail buffer
86
+ // */
87
+ // async function generateGenericThumbnail(fileType: string): Promise<Buffer> {
88
+ // // Create a blank canvas with a colored background based on file type
89
+ // const canvas = sharp({
90
+ // create: {
91
+ // width: THUMBNAIL_WIDTH,
92
+ // height: THUMBNAIL_HEIGHT,
93
+ // channels: 4,
94
+ // background: { r: 245, g: 245, b: 245, alpha: 1 }
95
+ // }
96
+ // });
97
+ // // Add a colored overlay based on file type
98
+ // let color = { r: 200, g: 200, b: 200, alpha: 0.5 }; // Default gray
99
+ // if (DOCUMENT_TYPES.includes(fileType)) {
100
+ // color = { r: 52, g: 152, b: 219, alpha: 0.5 }; // Blue for documents
101
+ // } else if (VIDEO_TYPES.includes(fileType)) {
102
+ // color = { r: 231, g: 76, b: 60, alpha: 0.5 }; // Red for videos
103
+ // } else if (AUDIO_TYPES.includes(fileType)) {
104
+ // color = { r: 46, g: 204, b: 113, alpha: 0.5 }; // Green for audio
105
+ // }
106
+ // return canvas
107
+ // .composite([{
108
+ // input: Buffer.from([color.r, color.g, color.b, Math.floor(color.alpha * 255)]),
109
+ // raw: {
110
+ // width: 1,
111
+ // height: 1,
112
+ // channels: 4
113
+ // },
114
+ // tile: true,
115
+ // blend: 'overlay'
116
+ // }])
117
+ // .jpeg({ quality: 80 })
118
+ // .toBuffer();
119
+ // }
120
+ // /**
121
+ // * Generates a thumbnail for a file
122
+ // * @param fileName The name of the file in Google Cloud Storage
123
+ // * @param fileType The MIME type of the file
124
+ // * @returns The thumbnail buffer or null if thumbnail generation is not supported
125
+ // */
126
+ // export async function generateThumbnail(fileName: string, fileType: string): Promise<Buffer | null> {
127
+ // try {
128
+ // const signedUrl = await getSignedUrl(fileName);
129
+ // const response = await fetch(signedUrl);
130
+ // if (!response.ok) {
131
+ // throw new Error(`Failed to download file from storage: ${response.status} ${response.statusText}`);
132
+ // }
133
+ // const fileBuffer = await response.arrayBuffer();
134
+ // if (SUPPORTED_IMAGE_TYPES.includes(fileType) || fileType === 'application/pdf') {
135
+ // try {
136
+ // const thumbnail = await generateMediaThumbnail(Buffer.from(fileBuffer), fileType);
137
+ // return thumbnail;
138
+ // } catch (error) {
139
+ // return generateGenericThumbnail(fileType);
140
+ // }
141
+ // } else if ([...DOCUMENT_TYPES, ...VIDEO_TYPES, ...AUDIO_TYPES].includes(fileType)) {
142
+ // return generateGenericThumbnail(fileType);
143
+ // }
144
+ // return null; // Unsupported file type
145
+ // } catch (error) {
146
+ // return null;
147
+ // }
148
+ // }
149
+ // /**
150
+ // * Stores a thumbnail in Google Cloud Storage and creates a File entry
151
+ // * @param thumbnailBuffer The thumbnail buffer to store
152
+ // * @param originalFileName The original file name
153
+ // * @param userId The user ID who owns the file
154
+ // * @returns The ID of the created thumbnail File
155
+ // */
156
+ // // DEPRECATED: This function is no longer used - thumbnails are generated during direct uploads
157
+ // // Thumbnail generation is now handled in the direct upload flow
161
158
  //# sourceMappingURL=thumbnailGenerator.js.map
162
- //# debugId=a93ef014-63a9-5a8d-815a-01d914751573
159
+ //# debugId=8a494bec-8974-5f11-ae01-d96a89e7d69b
@@ -1 +1 @@
1
- {"version":3,"file":"thumbnailGenerator.js","sources":["lib/thumbnailGenerator.ts"],"sourceRoot":"/","sourcesContent":["import sharp from 'sharp';\nimport { prisma } from './prisma.js';\nimport { deleteFile, getSignedUrl } from './googleCloudStorage.js';\n\n// Thumbnail size configuration\nconst THUMBNAIL_WIDTH = 200;\nconst THUMBNAIL_HEIGHT = 200;\n\n// File type configurations\nconst SUPPORTED_IMAGE_TYPES = [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/tiff',\n 'image/bmp',\n 'image/avif'\n];\n\nconst DOCUMENT_TYPES = [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx\n 'application/vnd.ms-powerpoint',\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx\n 'text/plain',\n 'text/csv',\n 'application/json',\n 'text/html',\n 'text/javascript',\n 'text/css'\n];\n\nconst VIDEO_TYPES = [\n 'video/mp4',\n 'video/webm',\n 'video/ogg',\n 'video/quicktime'\n];\n\nconst AUDIO_TYPES = [\n 'audio/mpeg',\n 'audio/ogg',\n 'audio/wav',\n 'audio/webm'\n];\n\n/**\n * Generates a thumbnail for an image or PDF file\n * @param fileBuffer The file buffer\n * @param fileType The MIME type of the file\n * @returns Thumbnail buffer\n */\nexport async function generateMediaThumbnail(fileBuffer: Buffer, fileType: string): Promise<Buffer> {\n if (fileType === 'application/pdf') {\n // For PDFs, we need to use a different approach\n try {\n return await sharp(fileBuffer, { \n density: 300, // Higher density for better quality\n page: 0 // First page only\n })\n .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {\n fit: 'inside',\n withoutEnlargement: true,\n })\n .jpeg({ quality: 80 })\n .toBuffer();\n } catch (error) {\n console.warn('Failed to generate PDF thumbnail:', error);\n return generateGenericThumbnail(fileType);\n }\n }\n \n // For regular images\n return sharp(fileBuffer)\n .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {\n fit: 'inside',\n withoutEnlargement: true,\n })\n .jpeg({ quality: 80 })\n .toBuffer();\n}\n\n/**\n * Generates a generic icon-based thumbnail for a file type\n * @param fileType The MIME type of the file\n * @returns Thumbnail buffer\n */\nasync function generateGenericThumbnail(fileType: string): Promise<Buffer> {\n // Create a blank canvas with a colored background based on file type\n const canvas = sharp({\n create: {\n width: THUMBNAIL_WIDTH,\n height: THUMBNAIL_HEIGHT,\n channels: 4,\n background: { r: 245, g: 245, b: 245, alpha: 1 }\n }\n });\n\n // Add a colored overlay based on file type\n let color = { r: 200, g: 200, b: 200, alpha: 0.5 }; // Default gray\n\n if (DOCUMENT_TYPES.includes(fileType)) {\n color = { r: 52, g: 152, b: 219, alpha: 0.5 }; // Blue for documents\n } else if (VIDEO_TYPES.includes(fileType)) {\n color = { r: 231, g: 76, b: 60, alpha: 0.5 }; // Red for videos\n } else if (AUDIO_TYPES.includes(fileType)) {\n color = { r: 46, g: 204, b: 113, alpha: 0.5 }; // Green for audio\n }\n\n return canvas\n .composite([{\n input: Buffer.from([color.r, color.g, color.b, Math.floor(color.alpha * 255)]),\n raw: {\n width: 1,\n height: 1,\n channels: 4\n },\n tile: true,\n blend: 'overlay'\n }])\n .jpeg({ quality: 80 })\n .toBuffer();\n}\n\n/**\n * Generates a thumbnail for a file\n * @param fileName The name of the file in Google Cloud Storage\n * @param fileType The MIME type of the file\n * @returns The thumbnail buffer or null if thumbnail generation is not supported\n */\nexport async function generateThumbnail(fileName: string, fileType: string): Promise<Buffer | null> {\n try {\n const signedUrl = await getSignedUrl(fileName);\n const response = await fetch(signedUrl);\n \n if (!response.ok) {\n throw new Error(`Failed to download file from storage: ${response.status} ${response.statusText}`);\n }\n\n const fileBuffer = await response.arrayBuffer();\n\n if (SUPPORTED_IMAGE_TYPES.includes(fileType) || fileType === 'application/pdf') {\n try {\n const thumbnail = await generateMediaThumbnail(Buffer.from(fileBuffer), fileType);\n return thumbnail;\n } catch (error) {\n return generateGenericThumbnail(fileType);\n }\n } else if ([...DOCUMENT_TYPES, ...VIDEO_TYPES, ...AUDIO_TYPES].includes(fileType)) {\n return generateGenericThumbnail(fileType);\n }\n\n return null; // Unsupported file type\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Stores a thumbnail in Google Cloud Storage and creates a File entry\n * @param thumbnailBuffer The thumbnail buffer to store\n * @param originalFileName The original file name\n * @param userId The user ID who owns the file\n * @returns The ID of the created thumbnail File\n */\n// DEPRECATED: This function is no longer used - thumbnails are generated during direct uploads\n// Thumbnail generation is now handled in the direct upload flow "],"names":[],"mappings":"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","debug_id":"a93ef014-63a9-5a8d-815a-01d914751573"}
1
+ {"version":3,"file":"thumbnailGenerator.js","sources":["lib/thumbnailGenerator.ts"],"sourceRoot":"/","sourcesContent":["// @deprecated: this is not used anymore\n\n// import sharp from 'sharp';\n// import { prisma } from './prisma.js';\n// import { deleteFile, getSignedUrl } from './googleCloudStorage.js';\n\n// // Thumbnail size configuration\n// const THUMBNAIL_WIDTH = 200;\n// const THUMBNAIL_HEIGHT = 200;\n\n// // File type configurations\n// const SUPPORTED_IMAGE_TYPES = [\n// 'image/jpeg',\n// 'image/png',\n// 'image/gif',\n// 'image/webp',\n// 'image/tiff',\n// 'image/bmp',\n// 'image/avif'\n// ];\n\n// const DOCUMENT_TYPES = [\n// 'application/pdf',\n// 'application/msword',\n// 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx\n// 'application/vnd.ms-excel',\n// 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx\n// 'application/vnd.ms-powerpoint',\n// 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx\n// 'text/plain',\n// 'text/csv',\n// 'application/json',\n// 'text/html',\n// 'text/javascript',\n// 'text/css'\n// ];\n\n// const VIDEO_TYPES = [\n// 'video/mp4',\n// 'video/webm',\n// 'video/ogg',\n// 'video/quicktime'\n// ];\n\n// const AUDIO_TYPES = [\n// 'audio/mpeg',\n// 'audio/ogg',\n// 'audio/wav',\n// 'audio/webm'\n// ];\n\n// /**\n// * Generates a thumbnail for an image or PDF file\n// * @param fileBuffer The file buffer\n// * @param fileType The MIME type of the file\n// * @returns Thumbnail buffer\n// */\n// export async function generateMediaThumbnail(fileBuffer: Buffer, fileType: string): Promise<Buffer> {\n// if (fileType === 'application/pdf') {\n// // For PDFs, we need to use a different approach\n// try {\n// return await sharp(fileBuffer, { \n// density: 300, // Higher density for better quality\n// page: 0 // First page only\n// })\n// .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {\n// fit: 'inside',\n// withoutEnlargement: true,\n// })\n// .jpeg({ quality: 80 })\n// .toBuffer();\n// } catch (error) {\n// console.warn('Failed to generate PDF thumbnail:', error);\n// return generateGenericThumbnail(fileType);\n// }\n// }\n \n// // For regular images\n// return sharp(fileBuffer)\n// .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {\n// fit: 'inside',\n// withoutEnlargement: true,\n// })\n// .jpeg({ quality: 80 })\n// .toBuffer();\n// }\n\n// /**\n// * Generates a generic icon-based thumbnail for a file type\n// * @param fileType The MIME type of the file\n// * @returns Thumbnail buffer\n// */\n// async function generateGenericThumbnail(fileType: string): Promise<Buffer> {\n// // Create a blank canvas with a colored background based on file type\n// const canvas = sharp({\n// create: {\n// width: THUMBNAIL_WIDTH,\n// height: THUMBNAIL_HEIGHT,\n// channels: 4,\n// background: { r: 245, g: 245, b: 245, alpha: 1 }\n// }\n// });\n\n// // Add a colored overlay based on file type\n// let color = { r: 200, g: 200, b: 200, alpha: 0.5 }; // Default gray\n\n// if (DOCUMENT_TYPES.includes(fileType)) {\n// color = { r: 52, g: 152, b: 219, alpha: 0.5 }; // Blue for documents\n// } else if (VIDEO_TYPES.includes(fileType)) {\n// color = { r: 231, g: 76, b: 60, alpha: 0.5 }; // Red for videos\n// } else if (AUDIO_TYPES.includes(fileType)) {\n// color = { r: 46, g: 204, b: 113, alpha: 0.5 }; // Green for audio\n// }\n\n// return canvas\n// .composite([{\n// input: Buffer.from([color.r, color.g, color.b, Math.floor(color.alpha * 255)]),\n// raw: {\n// width: 1,\n// height: 1,\n// channels: 4\n// },\n// tile: true,\n// blend: 'overlay'\n// }])\n// .jpeg({ quality: 80 })\n// .toBuffer();\n// }\n\n// /**\n// * Generates a thumbnail for a file\n// * @param fileName The name of the file in Google Cloud Storage\n// * @param fileType The MIME type of the file\n// * @returns The thumbnail buffer or null if thumbnail generation is not supported\n// */\n// export async function generateThumbnail(fileName: string, fileType: string): Promise<Buffer | null> {\n// try {\n// const signedUrl = await getSignedUrl(fileName);\n// const response = await fetch(signedUrl);\n \n// if (!response.ok) {\n// throw new Error(`Failed to download file from storage: ${response.status} ${response.statusText}`);\n// }\n\n// const fileBuffer = await response.arrayBuffer();\n\n// if (SUPPORTED_IMAGE_TYPES.includes(fileType) || fileType === 'application/pdf') {\n// try {\n// const thumbnail = await generateMediaThumbnail(Buffer.from(fileBuffer), fileType);\n// return thumbnail;\n// } catch (error) {\n// return generateGenericThumbnail(fileType);\n// }\n// } else if ([...DOCUMENT_TYPES, ...VIDEO_TYPES, ...AUDIO_TYPES].includes(fileType)) {\n// return generateGenericThumbnail(fileType);\n// }\n\n// return null; // Unsupported file type\n// } catch (error) {\n// return null;\n// }\n// }\n\n// /**\n// * Stores a thumbnail in Google Cloud Storage and creates a File entry\n// * @param thumbnailBuffer The thumbnail buffer to store\n// * @param originalFileName The original file name\n// * @param userId The user ID who owns the file\n// * @returns The ID of the created thumbnail File\n// */\n// // DEPRECATED: This function is no longer used - thumbnails are generated during direct uploads\n// // Thumbnail generation is now handled in the direct upload flow "],"names":[],"mappings":";;;AAAA,wCAAwC;AAExC,6BAA6B;AAC7B,wCAAwC;AACxC,sEAAsE;AAEtE,kCAAkC;AAClC,+BAA+B;AAC/B,gCAAgC;AAEhC,8BAA8B;AAC9B,kCAAkC;AAClC,oBAAoB;AACpB,mBAAmB;AACnB,mBAAmB;AACnB,oBAAoB;AACpB,oBAAoB;AACpB,mBAAmB;AACnB,mBAAmB;AACnB,KAAK;AAEL,2BAA2B;AAC3B,yBAAyB;AACzB,4BAA4B;AAC5B,0FAA0F;AAC1F,kCAAkC;AAClC,oFAAoF;AACpF,uCAAuC;AACvC,4FAA4F;AAC5F,oBAAoB;AACpB,kBAAkB;AAClB,0BAA0B;AAC1B,mBAAmB;AACnB,yBAAyB;AACzB,iBAAiB;AACjB,KAAK;AAEL,wBAAwB;AACxB,mBAAmB;AACnB,oBAAoB;AACpB,mBAAmB;AACnB,wBAAwB;AACxB,KAAK;AAEL,wBAAwB;AACxB,oBAAoB;AACpB,mBAAmB;AACnB,mBAAmB;AACnB,mBAAmB;AACnB,KAAK;AAEL,MAAM;AACN,oDAAoD;AACpD,uCAAuC;AACvC,+CAA+C;AAC/C,+BAA+B;AAC/B,MAAM;AACN,wGAAwG;AACxG,4CAA4C;AAC5C,2DAA2D;AAC3D,gBAAgB;AAChB,gDAAgD;AAChD,qEAAqE;AACrE,6CAA6C;AAC7C,iBAAiB;AACjB,2DAA2D;AAC3D,iCAAiC;AACjC,4CAA4C;AAC5C,iBAAiB;AACjB,qCAAqC;AACrC,2BAA2B;AAC3B,4BAA4B;AAC5B,wEAAwE;AACxE,yDAAyD;AACzD,YAAY;AACZ,QAAQ;AAER,4BAA4B;AAC5B,+BAA+B;AAC/B,uDAAuD;AACvD,6BAA6B;AAC7B,wCAAwC;AACxC,aAAa;AACb,iCAAiC;AACjC,uBAAuB;AACvB,IAAI;AAEJ,MAAM;AACN,8DAA8D;AAC9D,+CAA+C;AAC/C,+BAA+B;AAC/B,MAAM;AACN,+EAA+E;AAC/E,4EAA4E;AAC5E,6BAA6B;AAC7B,oBAAoB;AACpB,sCAAsC;AACtC,wCAAwC;AACxC,2BAA2B;AAC3B,+DAA+D;AAC/D,YAAY;AACZ,UAAU;AAEV,kDAAkD;AAClD,0EAA0E;AAE1E,+CAA+C;AAC/C,+EAA+E;AAC/E,mDAAmD;AACnD,0EAA0E;AAC1E,mDAAmD;AACnD,4EAA4E;AAC5E,QAAQ;AAER,oBAAoB;AACpB,wBAAwB;AACxB,8FAA8F;AAC9F,qBAAqB;AACrB,4BAA4B;AAC5B,6BAA6B;AAC7B,8BAA8B;AAC9B,iBAAiB;AACjB,0BAA0B;AAC1B,+BAA+B;AAC/B,cAAc;AACd,iCAAiC;AACjC,uBAAuB;AACvB,IAAI;AAEJ,MAAM;AACN,sCAAsC;AACtC,kEAAkE;AAClE,+CAA+C;AAC/C,oFAAoF;AACpF,MAAM;AACN,wGAAwG;AACxG,YAAY;AACZ,0DAA0D;AAC1D,mDAAmD;AAEnD,8BAA8B;AAC9B,kHAAkH;AAClH,YAAY;AAEZ,2DAA2D;AAE3D,4FAA4F;AAC5F,oBAAoB;AACpB,qGAAqG;AACrG,oCAAoC;AACpC,gCAAgC;AAChC,6DAA6D;AAC7D,gBAAgB;AAChB,+FAA+F;AAC/F,yDAAyD;AACzD,YAAY;AAEZ,gDAAgD;AAChD,wBAAwB;AACxB,uBAAuB;AACvB,QAAQ;AACR,IAAI;AAEJ,MAAM;AACN,yEAAyE;AACzE,0DAA0D;AAC1D,oDAAoD;AACpD,iDAAiD;AACjD,mDAAmD;AACnD,MAAM;AACN,kGAAkG;AAClG,oEAAoE","debug_id":"8a494bec-8974-5f11-ae01-d96a89e7d69b"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"/","sources":["middleware/auth.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,oBAAoB,GAAI,GAAG,GAAG;;;;;CA6L1C,CAAC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"/","sources":["middleware/auth.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,oBAAoB,GAAI,GAAG,GAAG;;;;;CA+H1C,CAAC"}
@@ -1,41 +1,24 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9eb5ec2d-8ec2-5ced-9e9c-1d8e0c80f6f7")}catch(e){}}();
3
- import { TRPCError } from '@trpc/server';
4
- import { prisma } from '../lib/prisma.js';
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]="f1f0bcb4-fc6b-5b13-92c1-e2fedb706ef2")}catch(e){}}();
3
+ import { TRPCError } from "@trpc/server";
5
4
  import * as Sentry from "@sentry/node";
5
+ import { findUserBySessionToken, findTeacherClassesByUserId, findClassWithMember, findClassWithTeacher, } from "../models/auth.js";
6
6
  export const createAuthMiddleware = (t) => {
7
- // Auth middleware
8
7
  const isAuthed = t.middleware(async ({ next, ctx }) => {
9
- const startTime = Date.now();
10
- // Get user from request headers
11
- const userHeader = ctx.req.headers['x-user'];
8
+ const userHeader = ctx.req.headers["x-user"];
12
9
  if (!userHeader) {
13
10
  throw new TRPCError({
14
- code: 'UNAUTHORIZED',
15
- message: 'Not authenticated - no token found',
11
+ code: "UNAUTHORIZED",
12
+ message: "Not authenticated - no token found",
16
13
  });
17
14
  }
18
15
  try {
19
- const token = typeof userHeader === 'string' ? userHeader : userHeader[0];
20
- // Find user by session token
21
- const user = await prisma.user.findFirst({
22
- where: {
23
- sessions: {
24
- some: {
25
- id: token
26
- }
27
- }
28
- },
29
- select: {
30
- id: true,
31
- username: true,
32
- // institutionId: true,
33
- }
34
- });
16
+ const token = typeof userHeader === "string" ? userHeader : userHeader[0];
17
+ const user = await findUserBySessionToken(token);
35
18
  if (!user) {
36
19
  throw new TRPCError({
37
- code: 'UNAUTHORIZED',
38
- message: 'Invalid or expired session',
20
+ code: "UNAUTHORIZED",
21
+ message: "Invalid or expired session",
39
22
  });
40
23
  }
41
24
  return next({
@@ -46,120 +29,75 @@ export const createAuthMiddleware = (t) => {
46
29
  });
47
30
  }
48
31
  catch (error) {
49
- // Re-throw TRPCErrors as-is (e.g., UNAUTHORIZED from invalid session)
50
32
  if (error instanceof TRPCError) {
51
33
  throw error;
52
34
  }
53
35
  Sentry.captureException(error);
54
36
  console.error(error);
55
37
  throw new TRPCError({
56
- code: 'INTERNAL_SERVER_ERROR',
57
- message: 'Internal server error',
38
+ code: "INTERNAL_SERVER_ERROR",
39
+ message: "Internal server error",
58
40
  });
59
41
  }
60
42
  });
61
- // Add computed flags middleware
62
43
  const addComputedFlags = t.middleware(async ({ next, ctx }) => {
63
44
  if (!ctx.user) {
64
45
  throw new TRPCError({
65
- code: 'UNAUTHORIZED',
66
- message: 'Not authenticated',
46
+ code: "UNAUTHORIZED",
47
+ message: "Not authenticated",
67
48
  });
68
49
  }
69
- // Get all classes where user is a teacher
70
- const teacherClasses = await prisma.class.findMany({
71
- where: {
72
- teachers: {
73
- some: {
74
- id: ctx.user.id
75
- }
76
- }
77
- },
78
- select: {
79
- id: true
80
- }
81
- });
50
+ const teacherClasses = await findTeacherClassesByUserId(ctx.user.id);
82
51
  return next({
83
52
  ctx: {
84
53
  ...ctx,
85
54
  isTeacher: teacherClasses.length > 0,
86
- teacherClassIds: teacherClasses.map((c) => c.id)
87
- }
55
+ teacherClassIds: teacherClasses.map((c) => c.id),
56
+ },
88
57
  });
89
58
  });
90
- // Student middleware
91
59
  const isMemberInClass = t.middleware(async ({ next, ctx, input }) => {
92
60
  if (!ctx.user) {
93
61
  throw new TRPCError({
94
- code: 'UNAUTHORIZED',
95
- message: 'Not authenticated',
62
+ code: "UNAUTHORIZED",
63
+ message: "Not authenticated",
96
64
  });
97
65
  }
98
66
  const classId = input?.classId;
99
67
  if (!classId) {
100
68
  throw new TRPCError({
101
- code: 'BAD_REQUEST',
102
- message: 'classId is required',
69
+ code: "BAD_REQUEST",
70
+ message: "classId is required",
103
71
  });
104
72
  }
105
- const isMember = await prisma.class.findFirst({
106
- where: {
107
- id: classId,
108
- OR: [
109
- {
110
- students: {
111
- some: {
112
- id: ctx.user.id
113
- }
114
- }
115
- },
116
- {
117
- teachers: {
118
- some: {
119
- id: ctx.user.id
120
- }
121
- }
122
- }
123
- ]
124
- }
125
- });
73
+ const isMember = await findClassWithMember(classId, ctx.user.id);
126
74
  if (!isMember) {
127
75
  throw new TRPCError({
128
- code: 'FORBIDDEN',
129
- message: 'Not a member in this class',
76
+ code: "FORBIDDEN",
77
+ message: "Not a member in this class",
130
78
  });
131
79
  }
132
80
  return next();
133
81
  });
134
- // Teacher middleware
135
82
  const isTeacherInClass = t.middleware(async ({ next, ctx, input }) => {
136
83
  if (!ctx.user) {
137
84
  throw new TRPCError({
138
- code: 'UNAUTHORIZED',
139
- message: 'Not authenticated',
85
+ code: "UNAUTHORIZED",
86
+ message: "Not authenticated",
140
87
  });
141
88
  }
142
- const classId = input.classId;
89
+ const classId = input?.classId;
143
90
  if (!classId) {
144
91
  throw new TRPCError({
145
- code: 'BAD_REQUEST',
146
- message: 'classId is required',
92
+ code: "BAD_REQUEST",
93
+ message: "classId is required",
147
94
  });
148
95
  }
149
- const isTeacher = await prisma.class.findFirst({
150
- where: {
151
- id: classId,
152
- teachers: {
153
- some: {
154
- id: ctx.user.id
155
- }
156
- }
157
- }
158
- });
96
+ const isTeacher = await findClassWithTeacher(classId, ctx.user.id);
159
97
  if (!isTeacher) {
160
98
  throw new TRPCError({
161
- code: 'FORBIDDEN',
162
- message: 'Not a teacher in this class',
99
+ code: "FORBIDDEN",
100
+ message: "Not a teacher in this class",
163
101
  });
164
102
  }
165
103
  return next();
@@ -172,4 +110,4 @@ export const createAuthMiddleware = (t) => {
172
110
  };
173
111
  };
174
112
  //# sourceMappingURL=auth.js.map
175
- //# debugId=9eb5ec2d-8ec2-5ced-9e9c-1d8e0c80f6f7
113
+ //# debugId=f1f0bcb4-fc6b-5b13-92c1-e2fedb706ef2