@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,1138 +0,0 @@
1
-
2
- <!doctype html>
3
- <html lang="en">
4
-
5
- <head>
6
- <title>Code coverage report for server/src/lib/fileUpload.ts</title>
7
- <meta charset="utf-8" />
8
- <link rel="stylesheet" href="../../../prettify.css" />
9
- <link rel="stylesheet" href="../../../base.css" />
10
- <link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
11
- <meta name="viewport" content="width=device-width, initial-scale=1" />
12
- <style type='text/css'>
13
- .coverage-summary .sorter {
14
- background-image: url(../../../sort-arrow-sprite.png);
15
- }
16
- </style>
17
- </head>
18
-
19
- <body>
20
- <div class='wrapper'>
21
- <div class='pad1'>
22
- <h1><a href="../../../index.html">All files</a> / <a href="index.html">server/src/lib</a> fileUpload.ts</h1>
23
- <div class='clearfix'>
24
-
25
- <div class='fl pad1y space-right2'>
26
- <span class="strong">36.28% </span>
27
- <span class="quiet">Statements</span>
28
- <span class='fraction'>86/237</span>
29
- </div>
30
-
31
-
32
- <div class='fl pad1y space-right2'>
33
- <span class="strong">41.66% </span>
34
- <span class="quiet">Branches</span>
35
- <span class='fraction'>5/12</span>
36
- </div>
37
-
38
-
39
- <div class='fl pad1y space-right2'>
40
- <span class="strong">28.57% </span>
41
- <span class="quiet">Functions</span>
42
- <span class='fraction'>2/7</span>
43
- </div>
44
-
45
-
46
- <div class='fl pad1y space-right2'>
47
- <span class="strong">36.28% </span>
48
- <span class="quiet">Lines</span>
49
- <span class='fraction'>86/237</span>
50
- </div>
51
-
52
-
53
- </div>
54
- <p class="quiet">
55
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
- </p>
57
- <template id="filterTemplate">
58
- <div class="quiet">
59
- Filter:
60
- <input type="search" id="fileSearch">
61
- </div>
62
- </template>
63
- </div>
64
- <div class='status-line low'></div>
65
- <pre><table class="coverage">
66
- <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
- <a name='L2'></a><a href='#L2'>2</a>
68
- <a name='L3'></a><a href='#L3'>3</a>
69
- <a name='L4'></a><a href='#L4'>4</a>
70
- <a name='L5'></a><a href='#L5'>5</a>
71
- <a name='L6'></a><a href='#L6'>6</a>
72
- <a name='L7'></a><a href='#L7'>7</a>
73
- <a name='L8'></a><a href='#L8'>8</a>
74
- <a name='L9'></a><a href='#L9'>9</a>
75
- <a name='L10'></a><a href='#L10'>10</a>
76
- <a name='L11'></a><a href='#L11'>11</a>
77
- <a name='L12'></a><a href='#L12'>12</a>
78
- <a name='L13'></a><a href='#L13'>13</a>
79
- <a name='L14'></a><a href='#L14'>14</a>
80
- <a name='L15'></a><a href='#L15'>15</a>
81
- <a name='L16'></a><a href='#L16'>16</a>
82
- <a name='L17'></a><a href='#L17'>17</a>
83
- <a name='L18'></a><a href='#L18'>18</a>
84
- <a name='L19'></a><a href='#L19'>19</a>
85
- <a name='L20'></a><a href='#L20'>20</a>
86
- <a name='L21'></a><a href='#L21'>21</a>
87
- <a name='L22'></a><a href='#L22'>22</a>
88
- <a name='L23'></a><a href='#L23'>23</a>
89
- <a name='L24'></a><a href='#L24'>24</a>
90
- <a name='L25'></a><a href='#L25'>25</a>
91
- <a name='L26'></a><a href='#L26'>26</a>
92
- <a name='L27'></a><a href='#L27'>27</a>
93
- <a name='L28'></a><a href='#L28'>28</a>
94
- <a name='L29'></a><a href='#L29'>29</a>
95
- <a name='L30'></a><a href='#L30'>30</a>
96
- <a name='L31'></a><a href='#L31'>31</a>
97
- <a name='L32'></a><a href='#L32'>32</a>
98
- <a name='L33'></a><a href='#L33'>33</a>
99
- <a name='L34'></a><a href='#L34'>34</a>
100
- <a name='L35'></a><a href='#L35'>35</a>
101
- <a name='L36'></a><a href='#L36'>36</a>
102
- <a name='L37'></a><a href='#L37'>37</a>
103
- <a name='L38'></a><a href='#L38'>38</a>
104
- <a name='L39'></a><a href='#L39'>39</a>
105
- <a name='L40'></a><a href='#L40'>40</a>
106
- <a name='L41'></a><a href='#L41'>41</a>
107
- <a name='L42'></a><a href='#L42'>42</a>
108
- <a name='L43'></a><a href='#L43'>43</a>
109
- <a name='L44'></a><a href='#L44'>44</a>
110
- <a name='L45'></a><a href='#L45'>45</a>
111
- <a name='L46'></a><a href='#L46'>46</a>
112
- <a name='L47'></a><a href='#L47'>47</a>
113
- <a name='L48'></a><a href='#L48'>48</a>
114
- <a name='L49'></a><a href='#L49'>49</a>
115
- <a name='L50'></a><a href='#L50'>50</a>
116
- <a name='L51'></a><a href='#L51'>51</a>
117
- <a name='L52'></a><a href='#L52'>52</a>
118
- <a name='L53'></a><a href='#L53'>53</a>
119
- <a name='L54'></a><a href='#L54'>54</a>
120
- <a name='L55'></a><a href='#L55'>55</a>
121
- <a name='L56'></a><a href='#L56'>56</a>
122
- <a name='L57'></a><a href='#L57'>57</a>
123
- <a name='L58'></a><a href='#L58'>58</a>
124
- <a name='L59'></a><a href='#L59'>59</a>
125
- <a name='L60'></a><a href='#L60'>60</a>
126
- <a name='L61'></a><a href='#L61'>61</a>
127
- <a name='L62'></a><a href='#L62'>62</a>
128
- <a name='L63'></a><a href='#L63'>63</a>
129
- <a name='L64'></a><a href='#L64'>64</a>
130
- <a name='L65'></a><a href='#L65'>65</a>
131
- <a name='L66'></a><a href='#L66'>66</a>
132
- <a name='L67'></a><a href='#L67'>67</a>
133
- <a name='L68'></a><a href='#L68'>68</a>
134
- <a name='L69'></a><a href='#L69'>69</a>
135
- <a name='L70'></a><a href='#L70'>70</a>
136
- <a name='L71'></a><a href='#L71'>71</a>
137
- <a name='L72'></a><a href='#L72'>72</a>
138
- <a name='L73'></a><a href='#L73'>73</a>
139
- <a name='L74'></a><a href='#L74'>74</a>
140
- <a name='L75'></a><a href='#L75'>75</a>
141
- <a name='L76'></a><a href='#L76'>76</a>
142
- <a name='L77'></a><a href='#L77'>77</a>
143
- <a name='L78'></a><a href='#L78'>78</a>
144
- <a name='L79'></a><a href='#L79'>79</a>
145
- <a name='L80'></a><a href='#L80'>80</a>
146
- <a name='L81'></a><a href='#L81'>81</a>
147
- <a name='L82'></a><a href='#L82'>82</a>
148
- <a name='L83'></a><a href='#L83'>83</a>
149
- <a name='L84'></a><a href='#L84'>84</a>
150
- <a name='L85'></a><a href='#L85'>85</a>
151
- <a name='L86'></a><a href='#L86'>86</a>
152
- <a name='L87'></a><a href='#L87'>87</a>
153
- <a name='L88'></a><a href='#L88'>88</a>
154
- <a name='L89'></a><a href='#L89'>89</a>
155
- <a name='L90'></a><a href='#L90'>90</a>
156
- <a name='L91'></a><a href='#L91'>91</a>
157
- <a name='L92'></a><a href='#L92'>92</a>
158
- <a name='L93'></a><a href='#L93'>93</a>
159
- <a name='L94'></a><a href='#L94'>94</a>
160
- <a name='L95'></a><a href='#L95'>95</a>
161
- <a name='L96'></a><a href='#L96'>96</a>
162
- <a name='L97'></a><a href='#L97'>97</a>
163
- <a name='L98'></a><a href='#L98'>98</a>
164
- <a name='L99'></a><a href='#L99'>99</a>
165
- <a name='L100'></a><a href='#L100'>100</a>
166
- <a name='L101'></a><a href='#L101'>101</a>
167
- <a name='L102'></a><a href='#L102'>102</a>
168
- <a name='L103'></a><a href='#L103'>103</a>
169
- <a name='L104'></a><a href='#L104'>104</a>
170
- <a name='L105'></a><a href='#L105'>105</a>
171
- <a name='L106'></a><a href='#L106'>106</a>
172
- <a name='L107'></a><a href='#L107'>107</a>
173
- <a name='L108'></a><a href='#L108'>108</a>
174
- <a name='L109'></a><a href='#L109'>109</a>
175
- <a name='L110'></a><a href='#L110'>110</a>
176
- <a name='L111'></a><a href='#L111'>111</a>
177
- <a name='L112'></a><a href='#L112'>112</a>
178
- <a name='L113'></a><a href='#L113'>113</a>
179
- <a name='L114'></a><a href='#L114'>114</a>
180
- <a name='L115'></a><a href='#L115'>115</a>
181
- <a name='L116'></a><a href='#L116'>116</a>
182
- <a name='L117'></a><a href='#L117'>117</a>
183
- <a name='L118'></a><a href='#L118'>118</a>
184
- <a name='L119'></a><a href='#L119'>119</a>
185
- <a name='L120'></a><a href='#L120'>120</a>
186
- <a name='L121'></a><a href='#L121'>121</a>
187
- <a name='L122'></a><a href='#L122'>122</a>
188
- <a name='L123'></a><a href='#L123'>123</a>
189
- <a name='L124'></a><a href='#L124'>124</a>
190
- <a name='L125'></a><a href='#L125'>125</a>
191
- <a name='L126'></a><a href='#L126'>126</a>
192
- <a name='L127'></a><a href='#L127'>127</a>
193
- <a name='L128'></a><a href='#L128'>128</a>
194
- <a name='L129'></a><a href='#L129'>129</a>
195
- <a name='L130'></a><a href='#L130'>130</a>
196
- <a name='L131'></a><a href='#L131'>131</a>
197
- <a name='L132'></a><a href='#L132'>132</a>
198
- <a name='L133'></a><a href='#L133'>133</a>
199
- <a name='L134'></a><a href='#L134'>134</a>
200
- <a name='L135'></a><a href='#L135'>135</a>
201
- <a name='L136'></a><a href='#L136'>136</a>
202
- <a name='L137'></a><a href='#L137'>137</a>
203
- <a name='L138'></a><a href='#L138'>138</a>
204
- <a name='L139'></a><a href='#L139'>139</a>
205
- <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a>
207
- <a name='L142'></a><a href='#L142'>142</a>
208
- <a name='L143'></a><a href='#L143'>143</a>
209
- <a name='L144'></a><a href='#L144'>144</a>
210
- <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a>
212
- <a name='L147'></a><a href='#L147'>147</a>
213
- <a name='L148'></a><a href='#L148'>148</a>
214
- <a name='L149'></a><a href='#L149'>149</a>
215
- <a name='L150'></a><a href='#L150'>150</a>
216
- <a name='L151'></a><a href='#L151'>151</a>
217
- <a name='L152'></a><a href='#L152'>152</a>
218
- <a name='L153'></a><a href='#L153'>153</a>
219
- <a name='L154'></a><a href='#L154'>154</a>
220
- <a name='L155'></a><a href='#L155'>155</a>
221
- <a name='L156'></a><a href='#L156'>156</a>
222
- <a name='L157'></a><a href='#L157'>157</a>
223
- <a name='L158'></a><a href='#L158'>158</a>
224
- <a name='L159'></a><a href='#L159'>159</a>
225
- <a name='L160'></a><a href='#L160'>160</a>
226
- <a name='L161'></a><a href='#L161'>161</a>
227
- <a name='L162'></a><a href='#L162'>162</a>
228
- <a name='L163'></a><a href='#L163'>163</a>
229
- <a name='L164'></a><a href='#L164'>164</a>
230
- <a name='L165'></a><a href='#L165'>165</a>
231
- <a name='L166'></a><a href='#L166'>166</a>
232
- <a name='L167'></a><a href='#L167'>167</a>
233
- <a name='L168'></a><a href='#L168'>168</a>
234
- <a name='L169'></a><a href='#L169'>169</a>
235
- <a name='L170'></a><a href='#L170'>170</a>
236
- <a name='L171'></a><a href='#L171'>171</a>
237
- <a name='L172'></a><a href='#L172'>172</a>
238
- <a name='L173'></a><a href='#L173'>173</a>
239
- <a name='L174'></a><a href='#L174'>174</a>
240
- <a name='L175'></a><a href='#L175'>175</a>
241
- <a name='L176'></a><a href='#L176'>176</a>
242
- <a name='L177'></a><a href='#L177'>177</a>
243
- <a name='L178'></a><a href='#L178'>178</a>
244
- <a name='L179'></a><a href='#L179'>179</a>
245
- <a name='L180'></a><a href='#L180'>180</a>
246
- <a name='L181'></a><a href='#L181'>181</a>
247
- <a name='L182'></a><a href='#L182'>182</a>
248
- <a name='L183'></a><a href='#L183'>183</a>
249
- <a name='L184'></a><a href='#L184'>184</a>
250
- <a name='L185'></a><a href='#L185'>185</a>
251
- <a name='L186'></a><a href='#L186'>186</a>
252
- <a name='L187'></a><a href='#L187'>187</a>
253
- <a name='L188'></a><a href='#L188'>188</a>
254
- <a name='L189'></a><a href='#L189'>189</a>
255
- <a name='L190'></a><a href='#L190'>190</a>
256
- <a name='L191'></a><a href='#L191'>191</a>
257
- <a name='L192'></a><a href='#L192'>192</a>
258
- <a name='L193'></a><a href='#L193'>193</a>
259
- <a name='L194'></a><a href='#L194'>194</a>
260
- <a name='L195'></a><a href='#L195'>195</a>
261
- <a name='L196'></a><a href='#L196'>196</a>
262
- <a name='L197'></a><a href='#L197'>197</a>
263
- <a name='L198'></a><a href='#L198'>198</a>
264
- <a name='L199'></a><a href='#L199'>199</a>
265
- <a name='L200'></a><a href='#L200'>200</a>
266
- <a name='L201'></a><a href='#L201'>201</a>
267
- <a name='L202'></a><a href='#L202'>202</a>
268
- <a name='L203'></a><a href='#L203'>203</a>
269
- <a name='L204'></a><a href='#L204'>204</a>
270
- <a name='L205'></a><a href='#L205'>205</a>
271
- <a name='L206'></a><a href='#L206'>206</a>
272
- <a name='L207'></a><a href='#L207'>207</a>
273
- <a name='L208'></a><a href='#L208'>208</a>
274
- <a name='L209'></a><a href='#L209'>209</a>
275
- <a name='L210'></a><a href='#L210'>210</a>
276
- <a name='L211'></a><a href='#L211'>211</a>
277
- <a name='L212'></a><a href='#L212'>212</a>
278
- <a name='L213'></a><a href='#L213'>213</a>
279
- <a name='L214'></a><a href='#L214'>214</a>
280
- <a name='L215'></a><a href='#L215'>215</a>
281
- <a name='L216'></a><a href='#L216'>216</a>
282
- <a name='L217'></a><a href='#L217'>217</a>
283
- <a name='L218'></a><a href='#L218'>218</a>
284
- <a name='L219'></a><a href='#L219'>219</a>
285
- <a name='L220'></a><a href='#L220'>220</a>
286
- <a name='L221'></a><a href='#L221'>221</a>
287
- <a name='L222'></a><a href='#L222'>222</a>
288
- <a name='L223'></a><a href='#L223'>223</a>
289
- <a name='L224'></a><a href='#L224'>224</a>
290
- <a name='L225'></a><a href='#L225'>225</a>
291
- <a name='L226'></a><a href='#L226'>226</a>
292
- <a name='L227'></a><a href='#L227'>227</a>
293
- <a name='L228'></a><a href='#L228'>228</a>
294
- <a name='L229'></a><a href='#L229'>229</a>
295
- <a name='L230'></a><a href='#L230'>230</a>
296
- <a name='L231'></a><a href='#L231'>231</a>
297
- <a name='L232'></a><a href='#L232'>232</a>
298
- <a name='L233'></a><a href='#L233'>233</a>
299
- <a name='L234'></a><a href='#L234'>234</a>
300
- <a name='L235'></a><a href='#L235'>235</a>
301
- <a name='L236'></a><a href='#L236'>236</a>
302
- <a name='L237'></a><a href='#L237'>237</a>
303
- <a name='L238'></a><a href='#L238'>238</a>
304
- <a name='L239'></a><a href='#L239'>239</a>
305
- <a name='L240'></a><a href='#L240'>240</a>
306
- <a name='L241'></a><a href='#L241'>241</a>
307
- <a name='L242'></a><a href='#L242'>242</a>
308
- <a name='L243'></a><a href='#L243'>243</a>
309
- <a name='L244'></a><a href='#L244'>244</a>
310
- <a name='L245'></a><a href='#L245'>245</a>
311
- <a name='L246'></a><a href='#L246'>246</a>
312
- <a name='L247'></a><a href='#L247'>247</a>
313
- <a name='L248'></a><a href='#L248'>248</a>
314
- <a name='L249'></a><a href='#L249'>249</a>
315
- <a name='L250'></a><a href='#L250'>250</a>
316
- <a name='L251'></a><a href='#L251'>251</a>
317
- <a name='L252'></a><a href='#L252'>252</a>
318
- <a name='L253'></a><a href='#L253'>253</a>
319
- <a name='L254'></a><a href='#L254'>254</a>
320
- <a name='L255'></a><a href='#L255'>255</a>
321
- <a name='L256'></a><a href='#L256'>256</a>
322
- <a name='L257'></a><a href='#L257'>257</a>
323
- <a name='L258'></a><a href='#L258'>258</a>
324
- <a name='L259'></a><a href='#L259'>259</a>
325
- <a name='L260'></a><a href='#L260'>260</a>
326
- <a name='L261'></a><a href='#L261'>261</a>
327
- <a name='L262'></a><a href='#L262'>262</a>
328
- <a name='L263'></a><a href='#L263'>263</a>
329
- <a name='L264'></a><a href='#L264'>264</a>
330
- <a name='L265'></a><a href='#L265'>265</a>
331
- <a name='L266'></a><a href='#L266'>266</a>
332
- <a name='L267'></a><a href='#L267'>267</a>
333
- <a name='L268'></a><a href='#L268'>268</a>
334
- <a name='L269'></a><a href='#L269'>269</a>
335
- <a name='L270'></a><a href='#L270'>270</a>
336
- <a name='L271'></a><a href='#L271'>271</a>
337
- <a name='L272'></a><a href='#L272'>272</a>
338
- <a name='L273'></a><a href='#L273'>273</a>
339
- <a name='L274'></a><a href='#L274'>274</a>
340
- <a name='L275'></a><a href='#L275'>275</a>
341
- <a name='L276'></a><a href='#L276'>276</a>
342
- <a name='L277'></a><a href='#L277'>277</a>
343
- <a name='L278'></a><a href='#L278'>278</a>
344
- <a name='L279'></a><a href='#L279'>279</a>
345
- <a name='L280'></a><a href='#L280'>280</a>
346
- <a name='L281'></a><a href='#L281'>281</a>
347
- <a name='L282'></a><a href='#L282'>282</a>
348
- <a name='L283'></a><a href='#L283'>283</a>
349
- <a name='L284'></a><a href='#L284'>284</a>
350
- <a name='L285'></a><a href='#L285'>285</a>
351
- <a name='L286'></a><a href='#L286'>286</a>
352
- <a name='L287'></a><a href='#L287'>287</a>
353
- <a name='L288'></a><a href='#L288'>288</a>
354
- <a name='L289'></a><a href='#L289'>289</a>
355
- <a name='L290'></a><a href='#L290'>290</a>
356
- <a name='L291'></a><a href='#L291'>291</a>
357
- <a name='L292'></a><a href='#L292'>292</a>
358
- <a name='L293'></a><a href='#L293'>293</a>
359
- <a name='L294'></a><a href='#L294'>294</a>
360
- <a name='L295'></a><a href='#L295'>295</a>
361
- <a name='L296'></a><a href='#L296'>296</a>
362
- <a name='L297'></a><a href='#L297'>297</a>
363
- <a name='L298'></a><a href='#L298'>298</a>
364
- <a name='L299'></a><a href='#L299'>299</a>
365
- <a name='L300'></a><a href='#L300'>300</a>
366
- <a name='L301'></a><a href='#L301'>301</a>
367
- <a name='L302'></a><a href='#L302'>302</a>
368
- <a name='L303'></a><a href='#L303'>303</a>
369
- <a name='L304'></a><a href='#L304'>304</a>
370
- <a name='L305'></a><a href='#L305'>305</a>
371
- <a name='L306'></a><a href='#L306'>306</a>
372
- <a name='L307'></a><a href='#L307'>307</a>
373
- <a name='L308'></a><a href='#L308'>308</a>
374
- <a name='L309'></a><a href='#L309'>309</a>
375
- <a name='L310'></a><a href='#L310'>310</a>
376
- <a name='L311'></a><a href='#L311'>311</a>
377
- <a name='L312'></a><a href='#L312'>312</a>
378
- <a name='L313'></a><a href='#L313'>313</a>
379
- <a name='L314'></a><a href='#L314'>314</a>
380
- <a name='L315'></a><a href='#L315'>315</a>
381
- <a name='L316'></a><a href='#L316'>316</a>
382
- <a name='L317'></a><a href='#L317'>317</a>
383
- <a name='L318'></a><a href='#L318'>318</a>
384
- <a name='L319'></a><a href='#L319'>319</a>
385
- <a name='L320'></a><a href='#L320'>320</a>
386
- <a name='L321'></a><a href='#L321'>321</a>
387
- <a name='L322'></a><a href='#L322'>322</a>
388
- <a name='L323'></a><a href='#L323'>323</a>
389
- <a name='L324'></a><a href='#L324'>324</a>
390
- <a name='L325'></a><a href='#L325'>325</a>
391
- <a name='L326'></a><a href='#L326'>326</a>
392
- <a name='L327'></a><a href='#L327'>327</a>
393
- <a name='L328'></a><a href='#L328'>328</a>
394
- <a name='L329'></a><a href='#L329'>329</a>
395
- <a name='L330'></a><a href='#L330'>330</a>
396
- <a name='L331'></a><a href='#L331'>331</a>
397
- <a name='L332'></a><a href='#L332'>332</a>
398
- <a name='L333'></a><a href='#L333'>333</a>
399
- <a name='L334'></a><a href='#L334'>334</a>
400
- <a name='L335'></a><a href='#L335'>335</a>
401
- <a name='L336'></a><a href='#L336'>336</a>
402
- <a name='L337'></a><a href='#L337'>337</a>
403
- <a name='L338'></a><a href='#L338'>338</a>
404
- <a name='L339'></a><a href='#L339'>339</a>
405
- <a name='L340'></a><a href='#L340'>340</a>
406
- <a name='L341'></a><a href='#L341'>341</a>
407
- <a name='L342'></a><a href='#L342'>342</a>
408
- <a name='L343'></a><a href='#L343'>343</a>
409
- <a name='L344'></a><a href='#L344'>344</a>
410
- <a name='L345'></a><a href='#L345'>345</a>
411
- <a name='L346'></a><a href='#L346'>346</a>
412
- <a name='L347'></a><a href='#L347'>347</a>
413
- <a name='L348'></a><a href='#L348'>348</a>
414
- <a name='L349'></a><a href='#L349'>349</a>
415
- <a name='L350'></a><a href='#L350'>350</a>
416
- <a name='L351'></a><a href='#L351'>351</a>
417
- <a name='L352'></a><a href='#L352'>352</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
418
- <span class="cline-any cline-yes">1x</span>
419
- <span class="cline-any cline-yes">1x</span>
420
- <span class="cline-any cline-neutral">&nbsp;</span>
421
- <span class="cline-any cline-yes">1x</span>
422
- <span class="cline-any cline-yes">1x</span>
423
- <span class="cline-any cline-yes">1x</span>
424
- <span class="cline-any cline-neutral">&nbsp;</span>
425
- <span class="cline-any cline-neutral">&nbsp;</span>
426
- <span class="cline-any cline-neutral">&nbsp;</span>
427
- <span class="cline-any cline-neutral">&nbsp;</span>
428
- <span class="cline-any cline-neutral">&nbsp;</span>
429
- <span class="cline-any cline-neutral">&nbsp;</span>
430
- <span class="cline-any cline-neutral">&nbsp;</span>
431
- <span class="cline-any cline-neutral">&nbsp;</span>
432
- <span class="cline-any cline-neutral">&nbsp;</span>
433
- <span class="cline-any cline-neutral">&nbsp;</span>
434
- <span class="cline-any cline-neutral">&nbsp;</span>
435
- <span class="cline-any cline-neutral">&nbsp;</span>
436
- <span class="cline-any cline-neutral">&nbsp;</span>
437
- <span class="cline-any cline-neutral">&nbsp;</span>
438
- <span class="cline-any cline-neutral">&nbsp;</span>
439
- <span class="cline-any cline-neutral">&nbsp;</span>
440
- <span class="cline-any cline-neutral">&nbsp;</span>
441
- <span class="cline-any cline-neutral">&nbsp;</span>
442
- <span class="cline-any cline-neutral">&nbsp;</span>
443
- <span class="cline-any cline-neutral">&nbsp;</span>
444
- <span class="cline-any cline-neutral">&nbsp;</span>
445
- <span class="cline-any cline-neutral">&nbsp;</span>
446
- <span class="cline-any cline-neutral">&nbsp;</span>
447
- <span class="cline-any cline-neutral">&nbsp;</span>
448
- <span class="cline-any cline-neutral">&nbsp;</span>
449
- <span class="cline-any cline-neutral">&nbsp;</span>
450
- <span class="cline-any cline-neutral">&nbsp;</span>
451
- <span class="cline-any cline-neutral">&nbsp;</span>
452
- <span class="cline-any cline-neutral">&nbsp;</span>
453
- <span class="cline-any cline-neutral">&nbsp;</span>
454
- <span class="cline-any cline-neutral">&nbsp;</span>
455
- <span class="cline-any cline-neutral">&nbsp;</span>
456
- <span class="cline-any cline-neutral">&nbsp;</span>
457
- <span class="cline-any cline-neutral">&nbsp;</span>
458
- <span class="cline-any cline-neutral">&nbsp;</span>
459
- <span class="cline-any cline-neutral">&nbsp;</span>
460
- <span class="cline-any cline-neutral">&nbsp;</span>
461
- <span class="cline-any cline-neutral">&nbsp;</span>
462
- <span class="cline-any cline-neutral">&nbsp;</span>
463
- <span class="cline-any cline-neutral">&nbsp;</span>
464
- <span class="cline-any cline-neutral">&nbsp;</span>
465
- <span class="cline-any cline-no">&nbsp;</span>
466
- <span class="cline-any cline-no">&nbsp;</span>
467
- <span class="cline-any cline-no">&nbsp;</span>
468
- <span class="cline-any cline-no">&nbsp;</span>
469
- <span class="cline-any cline-no">&nbsp;</span>
470
- <span class="cline-any cline-no">&nbsp;</span>
471
- <span class="cline-any cline-no">&nbsp;</span>
472
- <span class="cline-any cline-no">&nbsp;</span>
473
- <span class="cline-any cline-no">&nbsp;</span>
474
- <span class="cline-any cline-no">&nbsp;</span>
475
- <span class="cline-any cline-no">&nbsp;</span>
476
- <span class="cline-any cline-neutral">&nbsp;</span>
477
- <span class="cline-any cline-neutral">&nbsp;</span>
478
- <span class="cline-any cline-neutral">&nbsp;</span>
479
- <span class="cline-any cline-neutral">&nbsp;</span>
480
- <span class="cline-any cline-no">&nbsp;</span>
481
- <span class="cline-any cline-no">&nbsp;</span>
482
- <span class="cline-any cline-no">&nbsp;</span>
483
- <span class="cline-any cline-no">&nbsp;</span>
484
- <span class="cline-any cline-no">&nbsp;</span>
485
- <span class="cline-any cline-no">&nbsp;</span>
486
- <span class="cline-any cline-no">&nbsp;</span>
487
- <span class="cline-any cline-no">&nbsp;</span>
488
- <span class="cline-any cline-no">&nbsp;</span>
489
- <span class="cline-any cline-no">&nbsp;</span>
490
- <span class="cline-any cline-neutral">&nbsp;</span>
491
- <span class="cline-any cline-neutral">&nbsp;</span>
492
- <span class="cline-any cline-neutral">&nbsp;</span>
493
- <span class="cline-any cline-neutral">&nbsp;</span>
494
- <span class="cline-any cline-neutral">&nbsp;</span>
495
- <span class="cline-any cline-neutral">&nbsp;</span>
496
- <span class="cline-any cline-no">&nbsp;</span>
497
- <span class="cline-any cline-no">&nbsp;</span>
498
- <span class="cline-any cline-no">&nbsp;</span>
499
- <span class="cline-any cline-no">&nbsp;</span>
500
- <span class="cline-any cline-no">&nbsp;</span>
501
- <span class="cline-any cline-no">&nbsp;</span>
502
- <span class="cline-any cline-no">&nbsp;</span>
503
- <span class="cline-any cline-no">&nbsp;</span>
504
- <span class="cline-any cline-no">&nbsp;</span>
505
- <span class="cline-any cline-no">&nbsp;</span>
506
- <span class="cline-any cline-no">&nbsp;</span>
507
- <span class="cline-any cline-neutral">&nbsp;</span>
508
- <span class="cline-any cline-neutral">&nbsp;</span>
509
- <span class="cline-any cline-neutral">&nbsp;</span>
510
- <span class="cline-any cline-neutral">&nbsp;</span>
511
- <span class="cline-any cline-neutral">&nbsp;</span>
512
- <span class="cline-any cline-neutral">&nbsp;</span>
513
- <span class="cline-any cline-neutral">&nbsp;</span>
514
- <span class="cline-any cline-neutral">&nbsp;</span>
515
- <span class="cline-any cline-neutral">&nbsp;</span>
516
- <span class="cline-any cline-neutral">&nbsp;</span>
517
- <span class="cline-any cline-yes">2x</span>
518
- <span class="cline-any cline-yes">2x</span>
519
- <span class="cline-any cline-yes">2x</span>
520
- <span class="cline-any cline-yes">2x</span>
521
- <span class="cline-any cline-yes">2x</span>
522
- <span class="cline-any cline-yes">2x</span>
523
- <span class="cline-any cline-yes">2x</span>
524
- <span class="cline-any cline-yes">2x</span>
525
- <span class="cline-any cline-yes">2x</span>
526
- <span class="cline-any cline-neutral">&nbsp;</span>
527
- <span class="cline-any cline-yes">2x</span>
528
- <span class="cline-any cline-yes">2x</span>
529
- <span class="cline-any cline-neutral">&nbsp;</span>
530
- <span class="cline-any cline-yes">2x</span>
531
- <span class="cline-any cline-yes">2x</span>
532
- <span class="cline-any cline-yes">2x</span>
533
- <span class="cline-any cline-yes">2x</span>
534
- <span class="cline-any cline-yes">2x</span>
535
- <span class="cline-any cline-yes">2x</span>
536
- <span class="cline-any cline-yes">2x</span>
537
- <span class="cline-any cline-neutral">&nbsp;</span>
538
- <span class="cline-any cline-yes">2x</span>
539
- <span class="cline-any cline-no">&nbsp;</span>
540
- <span class="cline-any cline-no">&nbsp;</span>
541
- <span class="cline-any cline-no">&nbsp;</span>
542
- <span class="cline-any cline-no">&nbsp;</span>
543
- <span class="cline-any cline-neutral">&nbsp;</span>
544
- <span class="cline-any cline-neutral">&nbsp;</span>
545
- <span class="cline-any cline-yes">2x</span>
546
- <span class="cline-any cline-neutral">&nbsp;</span>
547
- <span class="cline-any cline-neutral">&nbsp;</span>
548
- <span class="cline-any cline-yes">2x</span>
549
- <span class="cline-any cline-no">&nbsp;</span>
550
- <span class="cline-any cline-yes">2x</span>
551
- <span class="cline-any cline-neutral">&nbsp;</span>
552
- <span class="cline-any cline-neutral">&nbsp;</span>
553
- <span class="cline-any cline-yes">2x</span>
554
- <span class="cline-any cline-neutral">&nbsp;</span>
555
- <span class="cline-any cline-neutral">&nbsp;</span>
556
- <span class="cline-any cline-yes">2x</span>
557
- <span class="cline-any cline-yes">2x</span>
558
- <span class="cline-any cline-yes">2x</span>
559
- <span class="cline-any cline-neutral">&nbsp;</span>
560
- <span class="cline-any cline-neutral">&nbsp;</span>
561
- <span class="cline-any cline-yes">2x</span>
562
- <span class="cline-any cline-yes">2x</span>
563
- <span class="cline-any cline-yes">2x</span>
564
- <span class="cline-any cline-yes">2x</span>
565
- <span class="cline-any cline-yes">2x</span>
566
- <span class="cline-any cline-yes">2x</span>
567
- <span class="cline-any cline-yes">2x</span>
568
- <span class="cline-any cline-yes">2x</span>
569
- <span class="cline-any cline-yes">2x</span>
570
- <span class="cline-any cline-yes">2x</span>
571
- <span class="cline-any cline-yes">2x</span>
572
- <span class="cline-any cline-yes">2x</span>
573
- <span class="cline-any cline-yes">2x</span>
574
- <span class="cline-any cline-yes">2x</span>
575
- <span class="cline-any cline-no">&nbsp;</span>
576
- <span class="cline-any cline-no">&nbsp;</span>
577
- <span class="cline-any cline-no">&nbsp;</span>
578
- <span class="cline-any cline-no">&nbsp;</span>
579
- <span class="cline-any cline-yes">2x</span>
580
- <span class="cline-any cline-yes">1x</span>
581
- <span class="cline-any cline-yes">1x</span>
582
- <span class="cline-any cline-yes">1x</span>
583
- <span class="cline-any cline-yes">1x</span>
584
- <span class="cline-any cline-yes">2x</span>
585
- <span class="cline-any cline-no">&nbsp;</span>
586
- <span class="cline-any cline-no">&nbsp;</span>
587
- <span class="cline-any cline-no">&nbsp;</span>
588
- <span class="cline-any cline-no">&nbsp;</span>
589
- <span class="cline-any cline-yes">2x</span>
590
- <span class="cline-any cline-yes">1x</span>
591
- <span class="cline-any cline-yes">1x</span>
592
- <span class="cline-any cline-yes">1x</span>
593
- <span class="cline-any cline-yes">1x</span>
594
- <span class="cline-any cline-yes">2x</span>
595
- <span class="cline-any cline-yes">2x</span>
596
- <span class="cline-any cline-neutral">&nbsp;</span>
597
- <span class="cline-any cline-yes">2x</span>
598
- <span class="cline-any cline-yes">2x</span>
599
- <span class="cline-any cline-yes">2x</span>
600
- <span class="cline-any cline-yes">2x</span>
601
- <span class="cline-any cline-yes">2x</span>
602
- <span class="cline-any cline-yes">2x</span>
603
- <span class="cline-any cline-yes">2x</span>
604
- <span class="cline-any cline-yes">2x</span>
605
- <span class="cline-any cline-yes">2x</span>
606
- <span class="cline-any cline-yes">2x</span>
607
- <span class="cline-any cline-yes">2x</span>
608
- <span class="cline-any cline-no">&nbsp;</span>
609
- <span class="cline-any cline-no">&nbsp;</span>
610
- <span class="cline-any cline-no">&nbsp;</span>
611
- <span class="cline-any cline-no">&nbsp;</span>
612
- <span class="cline-any cline-no">&nbsp;</span>
613
- <span class="cline-any cline-no">&nbsp;</span>
614
- <span class="cline-any cline-no">&nbsp;</span>
615
- <span class="cline-any cline-no">&nbsp;</span>
616
- <span class="cline-any cline-no">&nbsp;</span>
617
- <span class="cline-any cline-no">&nbsp;</span>
618
- <span class="cline-any cline-yes">2x</span>
619
- <span class="cline-any cline-neutral">&nbsp;</span>
620
- <span class="cline-any cline-neutral">&nbsp;</span>
621
- <span class="cline-any cline-neutral">&nbsp;</span>
622
- <span class="cline-any cline-neutral">&nbsp;</span>
623
- <span class="cline-any cline-neutral">&nbsp;</span>
624
- <span class="cline-any cline-neutral">&nbsp;</span>
625
- <span class="cline-any cline-neutral">&nbsp;</span>
626
- <span class="cline-any cline-no">&nbsp;</span>
627
- <span class="cline-any cline-no">&nbsp;</span>
628
- <span class="cline-any cline-no">&nbsp;</span>
629
- <span class="cline-any cline-no">&nbsp;</span>
630
- <span class="cline-any cline-no">&nbsp;</span>
631
- <span class="cline-any cline-no">&nbsp;</span>
632
- <span class="cline-any cline-neutral">&nbsp;</span>
633
- <span class="cline-any cline-no">&nbsp;</span>
634
- <span class="cline-any cline-no">&nbsp;</span>
635
- <span class="cline-any cline-no">&nbsp;</span>
636
- <span class="cline-any cline-no">&nbsp;</span>
637
- <span class="cline-any cline-neutral">&nbsp;</span>
638
- <span class="cline-any cline-no">&nbsp;</span>
639
- <span class="cline-any cline-no">&nbsp;</span>
640
- <span class="cline-any cline-no">&nbsp;</span>
641
- <span class="cline-any cline-no">&nbsp;</span>
642
- <span class="cline-any cline-no">&nbsp;</span>
643
- <span class="cline-any cline-no">&nbsp;</span>
644
- <span class="cline-any cline-neutral">&nbsp;</span>
645
- <span class="cline-any cline-no">&nbsp;</span>
646
- <span class="cline-any cline-no">&nbsp;</span>
647
- <span class="cline-any cline-neutral">&nbsp;</span>
648
- <span class="cline-any cline-neutral">&nbsp;</span>
649
- <span class="cline-any cline-no">&nbsp;</span>
650
- <span class="cline-any cline-no">&nbsp;</span>
651
- <span class="cline-any cline-no">&nbsp;</span>
652
- <span class="cline-any cline-no">&nbsp;</span>
653
- <span class="cline-any cline-no">&nbsp;</span>
654
- <span class="cline-any cline-no">&nbsp;</span>
655
- <span class="cline-any cline-no">&nbsp;</span>
656
- <span class="cline-any cline-no">&nbsp;</span>
657
- <span class="cline-any cline-no">&nbsp;</span>
658
- <span class="cline-any cline-no">&nbsp;</span>
659
- <span class="cline-any cline-no">&nbsp;</span>
660
- <span class="cline-any cline-no">&nbsp;</span>
661
- <span class="cline-any cline-no">&nbsp;</span>
662
- <span class="cline-any cline-no">&nbsp;</span>
663
- <span class="cline-any cline-no">&nbsp;</span>
664
- <span class="cline-any cline-no">&nbsp;</span>
665
- <span class="cline-any cline-no">&nbsp;</span>
666
- <span class="cline-any cline-no">&nbsp;</span>
667
- <span class="cline-any cline-neutral">&nbsp;</span>
668
- <span class="cline-any cline-no">&nbsp;</span>
669
- <span class="cline-any cline-no">&nbsp;</span>
670
- <span class="cline-any cline-no">&nbsp;</span>
671
- <span class="cline-any cline-no">&nbsp;</span>
672
- <span class="cline-any cline-neutral">&nbsp;</span>
673
- <span class="cline-any cline-no">&nbsp;</span>
674
- <span class="cline-any cline-no">&nbsp;</span>
675
- <span class="cline-any cline-no">&nbsp;</span>
676
- <span class="cline-any cline-no">&nbsp;</span>
677
- <span class="cline-any cline-neutral">&nbsp;</span>
678
- <span class="cline-any cline-no">&nbsp;</span>
679
- <span class="cline-any cline-no">&nbsp;</span>
680
- <span class="cline-any cline-no">&nbsp;</span>
681
- <span class="cline-any cline-neutral">&nbsp;</span>
682
- <span class="cline-any cline-no">&nbsp;</span>
683
- <span class="cline-any cline-no">&nbsp;</span>
684
- <span class="cline-any cline-no">&nbsp;</span>
685
- <span class="cline-any cline-no">&nbsp;</span>
686
- <span class="cline-any cline-no">&nbsp;</span>
687
- <span class="cline-any cline-no">&nbsp;</span>
688
- <span class="cline-any cline-no">&nbsp;</span>
689
- <span class="cline-any cline-no">&nbsp;</span>
690
- <span class="cline-any cline-no">&nbsp;</span>
691
- <span class="cline-any cline-no">&nbsp;</span>
692
- <span class="cline-any cline-no">&nbsp;</span>
693
- <span class="cline-any cline-no">&nbsp;</span>
694
- <span class="cline-any cline-neutral">&nbsp;</span>
695
- <span class="cline-any cline-neutral">&nbsp;</span>
696
- <span class="cline-any cline-neutral">&nbsp;</span>
697
- <span class="cline-any cline-neutral">&nbsp;</span>
698
- <span class="cline-any cline-neutral">&nbsp;</span>
699
- <span class="cline-any cline-neutral">&nbsp;</span>
700
- <span class="cline-any cline-no">&nbsp;</span>
701
- <span class="cline-any cline-no">&nbsp;</span>
702
- <span class="cline-any cline-no">&nbsp;</span>
703
- <span class="cline-any cline-no">&nbsp;</span>
704
- <span class="cline-any cline-no">&nbsp;</span>
705
- <span class="cline-any cline-neutral">&nbsp;</span>
706
- <span class="cline-any cline-neutral">&nbsp;</span>
707
- <span class="cline-any cline-neutral">&nbsp;</span>
708
- <span class="cline-any cline-neutral">&nbsp;</span>
709
- <span class="cline-any cline-neutral">&nbsp;</span>
710
- <span class="cline-any cline-neutral">&nbsp;</span>
711
- <span class="cline-any cline-neutral">&nbsp;</span>
712
- <span class="cline-any cline-no">&nbsp;</span>
713
- <span class="cline-any cline-no">&nbsp;</span>
714
- <span class="cline-any cline-no">&nbsp;</span>
715
- <span class="cline-any cline-no">&nbsp;</span>
716
- <span class="cline-any cline-no">&nbsp;</span>
717
- <span class="cline-any cline-no">&nbsp;</span>
718
- <span class="cline-any cline-no">&nbsp;</span>
719
- <span class="cline-any cline-no">&nbsp;</span>
720
- <span class="cline-any cline-no">&nbsp;</span>
721
- <span class="cline-any cline-no">&nbsp;</span>
722
- <span class="cline-any cline-no">&nbsp;</span>
723
- <span class="cline-any cline-no">&nbsp;</span>
724
- <span class="cline-any cline-no">&nbsp;</span>
725
- <span class="cline-any cline-no">&nbsp;</span>
726
- <span class="cline-any cline-no">&nbsp;</span>
727
- <span class="cline-any cline-no">&nbsp;</span>
728
- <span class="cline-any cline-no">&nbsp;</span>
729
- <span class="cline-any cline-no">&nbsp;</span>
730
- <span class="cline-any cline-no">&nbsp;</span>
731
- <span class="cline-any cline-no">&nbsp;</span>
732
- <span class="cline-any cline-no">&nbsp;</span>
733
- <span class="cline-any cline-no">&nbsp;</span>
734
- <span class="cline-any cline-neutral">&nbsp;</span>
735
- <span class="cline-any cline-neutral">&nbsp;</span>
736
- <span class="cline-any cline-neutral">&nbsp;</span>
737
- <span class="cline-any cline-neutral">&nbsp;</span>
738
- <span class="cline-any cline-neutral">&nbsp;</span>
739
- <span class="cline-any cline-neutral">&nbsp;</span>
740
- <span class="cline-any cline-neutral">&nbsp;</span>
741
- <span class="cline-any cline-neutral">&nbsp;</span>
742
- <span class="cline-any cline-neutral">&nbsp;</span>
743
- <span class="cline-any cline-neutral">&nbsp;</span>
744
- <span class="cline-any cline-yes">2x</span>
745
- <span class="cline-any cline-yes">2x</span>
746
- <span class="cline-any cline-yes">2x</span>
747
- <span class="cline-any cline-yes">2x</span>
748
- <span class="cline-any cline-yes">2x</span>
749
- <span class="cline-any cline-yes">2x</span>
750
- <span class="cline-any cline-yes">2x</span>
751
- <span class="cline-any cline-yes">2x</span>
752
- <span class="cline-any cline-yes">2x</span>
753
- <span class="cline-any cline-yes">2x</span>
754
- <span class="cline-any cline-yes">2x</span>
755
- <span class="cline-any cline-yes">2x</span>
756
- <span class="cline-any cline-yes">2x</span>
757
- <span class="cline-any cline-yes">2x</span>
758
- <span class="cline-any cline-no">&nbsp;</span>
759
- <span class="cline-any cline-no">&nbsp;</span>
760
- <span class="cline-any cline-no">&nbsp;</span>
761
- <span class="cline-any cline-no">&nbsp;</span>
762
- <span class="cline-any cline-no">&nbsp;</span>
763
- <span class="cline-any cline-no">&nbsp;</span>
764
- <span class="cline-any cline-no">&nbsp;</span>
765
- <span class="cline-any cline-no">&nbsp;</span>
766
- <span class="cline-any cline-no">&nbsp;</span>
767
- <span class="cline-any cline-no">&nbsp;</span>
768
- <span class="cline-any cline-yes">2x</span></td><td class="text"><pre class="prettyprint lang-js">import { TRPCError } from "@trpc/server";
769
- import { v4 as uuidv4 } from "uuid";
770
- import { getSignedUrl, objectExists } from "./googleCloudStorage.js";
771
- import { generateMediaThumbnail } from "./thumbnailGenerator.js";
772
- import { prisma } from "./prisma.js";
773
- import { logger } from "../utils/logger.js";
774
- import { env } from "./config/env.js";
775
- &nbsp;
776
- export interface FileData {
777
- name: string;
778
- type: string;
779
- size: number;
780
- // No data field - for direct file uploads
781
- }
782
- &nbsp;
783
- export interface DirectFileData {
784
- name: string;
785
- type: string;
786
- size: number;
787
- // No data field - for direct file uploads
788
- }
789
- &nbsp;
790
- export interface UploadedFile {
791
- id: string;
792
- name: string;
793
- type: string;
794
- size: number;
795
- path: string;
796
- thumbnailId?: string;
797
- }
798
- &nbsp;
799
- export interface DirectUploadFile {
800
- id: string;
801
- name: string;
802
- type: string;
803
- size: number;
804
- path: string;
805
- uploadUrl: string;
806
- uploadExpiresAt: Date;
807
- uploadSessionId: string;
808
- }
809
- &nbsp;
810
- // DEPRECATED: These functions are no longer used - files are uploaded directly to GCS
811
- // Use createDirectUploadFile() and createDirectUploadFiles() instead
812
- &nbsp;
813
- /**
814
- * @deprecated Use createDirectUploadFile instead
815
- */
816
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function uploadFile(</span></span>
817
- <span class="cstat-no" title="statement not covered" > file: FileData,</span>
818
- <span class="cstat-no" title="statement not covered" > userId: string,</span>
819
- <span class="cstat-no" title="statement not covered" > directory?: string,</span>
820
- <span class="cstat-no" title="statement not covered" > assignmentId?: string</span>
821
- <span class="cstat-no" title="statement not covered" >): Promise&lt;UploadedFile&gt; {</span>
822
- <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
823
- <span class="cstat-no" title="statement not covered" > code: 'NOT_IMPLEMENTED',</span>
824
- <span class="cstat-no" title="statement not covered" > message: 'uploadFile is deprecated. Use createDirectUploadFile instead.',</span>
825
- <span class="cstat-no" title="statement not covered" > });</span>
826
- <span class="cstat-no" title="statement not covered" >}</span>
827
- &nbsp;
828
- /**
829
- * @deprecated Use createDirectUploadFiles instead
830
- */
831
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function uploadFiles(</span></span>
832
- <span class="cstat-no" title="statement not covered" > files: FileData[], </span>
833
- <span class="cstat-no" title="statement not covered" > userId: string,</span>
834
- <span class="cstat-no" title="statement not covered" > directory?: string</span>
835
- <span class="cstat-no" title="statement not covered" >): Promise&lt;UploadedFile[]&gt; {</span>
836
- <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
837
- <span class="cstat-no" title="statement not covered" > code: 'NOT_IMPLEMENTED',</span>
838
- <span class="cstat-no" title="statement not covered" > message: 'uploadFiles is deprecated. Use createDirectUploadFiles instead.',</span>
839
- <span class="cstat-no" title="statement not covered" > });</span>
840
- <span class="cstat-no" title="statement not covered" >}</span>
841
- &nbsp;
842
- /**
843
- * Gets a signed URL for a file
844
- * @param filePath The path of the file in Google Cloud Storage
845
- * @returns The signed URL
846
- */
847
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function getFileUrl(filePath: string): Promise&lt;string&gt; {</span></span>
848
- <span class="cstat-no" title="statement not covered" > try {</span>
849
- <span class="cstat-no" title="statement not covered" > return await getSignedUrl(filePath);</span>
850
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
851
- <span class="cstat-no" title="statement not covered" > console.error('Error getting signed URL:', error);</span>
852
- <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
853
- <span class="cstat-no" title="statement not covered" > code: 'INTERNAL_SERVER_ERROR',</span>
854
- <span class="cstat-no" title="statement not covered" > message: 'Failed to get file URL',</span>
855
- <span class="cstat-no" title="statement not covered" > });</span>
856
- <span class="cstat-no" title="statement not covered" > }</span>
857
- <span class="cstat-no" title="statement not covered" >}</span>
858
- &nbsp;
859
- /**
860
- * Creates a file record for direct upload and generates signed URL
861
- * @param file The file metadata (no base64 data)
862
- * @param userId The ID of the user uploading the file
863
- * @param directory Optional directory to store the file in
864
- * @param assignmentId Optional assignment ID to associate the file with
865
- * @param submissionId Optional submission ID to associate the file with
866
- * @returns The direct upload file information with signed URL
867
- */
868
- export async function createDirectUploadFile(
869
- file: DirectFileData,
870
- userId: string,
871
- directory?: string,
872
- assignmentId?: string,
873
- submissionId?: string,
874
- announcementId?: string
875
- ): Promise&lt;DirectUploadFile&gt; {
876
- try {
877
- // Validate file extension matches MIME type
878
- const fileExtension = file.name.split('.').pop()?.toLowerCase();
879
- const mimeType = file.type.toLowerCase();
880
-
881
- const extensionMimeMap: Record&lt;string, string[]&gt; = {
882
- 'jpg': ['image/jpeg'],
883
- 'jpeg': ['image/jpeg'],
884
- 'png': ['image/png'],
885
- 'gif': ['image/gif'],
886
- 'webp': ['image/webp']
887
- };
888
-
889
- if (fileExtension &amp;&amp; extensionMimeMap[fileExtension]) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
890
- <span class="cstat-no" title="statement not covered" > if (!extensionMimeMap[fileExtension].includes(mimeType)) {</span>
891
- <span class="cstat-no" title="statement not covered" > throw new Error(`File extension .${fileExtension} does not match MIME type ${mimeType}`);</span>
892
- <span class="cstat-no" title="statement not covered" > }</span>
893
- <span class="cstat-no" title="statement not covered" > }</span>
894
-
895
- // Create a unique filename
896
- const uniqueFilename = `${uuidv4()}.${fileExtension}`;
897
-
898
- // Construct the full path
899
- const filePath = <span class="branch-0 cbranch-no" title="branch not covered" >directory </span>
900
- <span class="cstat-no" title="statement not covered" > ? `${directory}/${uniqueFilename}`</span>
901
- : uniqueFilename;
902
-
903
- // Generate upload session ID
904
- const uploadSessionId = uuidv4();
905
-
906
- // Generate backend proxy upload URL (not direct GCS)
907
- const baseUrl = env.<span class="branch-0 cbranch-no" title="branch not covered" >BACKEND_URL || 'http://localhost:3001';</span>
908
- const uploadUrl = `${baseUrl}/api/upload/${encodeURIComponent(filePath)}`;
909
- const uploadExpiresAt = new Date(Date.now() + 15 * 60 * 1000); // 15 minutes from now
910
-
911
- // Create file record in database with PENDING status
912
- const fileRecord = await prisma.file.create({
913
- data: {
914
- name: file.name,
915
- type: file.type,
916
- size: file.size,
917
- path: filePath,
918
- uploadStatus: 'PENDING',
919
- uploadUrl,
920
- uploadExpiresAt,
921
- uploadSessionId,
922
- user: {
923
- connect: { id: userId }
924
- },
925
- ...(<span class="branch-0 cbranch-no" title="branch not covered" >directory &amp;&amp; {</span>
926
- <span class="cstat-no" title="statement not covered" > folder: {</span>
927
- <span class="cstat-no" title="statement not covered" > connect: {id: directory},</span>
928
- <span class="cstat-no" title="statement not covered" > },</span>
929
- <span class="cstat-no" title="statement not covered" > }),</span>
930
- ...(assignmentId &amp;&amp; {
931
- assignment: {
932
- connect: { id: assignmentId }
933
- }
934
- }),
935
- ...(<span class="branch-0 cbranch-no" title="branch not covered" >submissionId &amp;&amp; {</span>
936
- <span class="cstat-no" title="statement not covered" > submission: {</span>
937
- <span class="cstat-no" title="statement not covered" > connect: { id: submissionId }</span>
938
- <span class="cstat-no" title="statement not covered" > }</span>
939
- <span class="cstat-no" title="statement not covered" > }),</span>
940
- ...(announcementId &amp;&amp; {
941
- announcement: {
942
- connect: { id: announcementId }
943
- }
944
- })
945
- },
946
- });
947
-
948
- return {
949
- id: fileRecord.id,
950
- name: file.name,
951
- type: file.type,
952
- size: file.size,
953
- path: filePath,
954
- uploadUrl,
955
- uploadExpiresAt,
956
- uploadSessionId
957
- };
958
- <span class="branch-0 cbranch-no" title="branch not covered" > } catch (error) {</span>
959
- <span class="cstat-no" title="statement not covered" > logger.error('Error creating direct upload file:', {error: error instanceof Error ? {</span>
960
- <span class="cstat-no" title="statement not covered" > name: error.name,</span>
961
- <span class="cstat-no" title="statement not covered" > message: error.message,</span>
962
- <span class="cstat-no" title="statement not covered" > stack: error.stack,</span>
963
- <span class="cstat-no" title="statement not covered" > } : error});</span>
964
- <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
965
- <span class="cstat-no" title="statement not covered" > code: 'INTERNAL_SERVER_ERROR',</span>
966
- <span class="cstat-no" title="statement not covered" > message: 'Failed to create direct upload file',</span>
967
- <span class="cstat-no" title="statement not covered" > });</span>
968
- <span class="cstat-no" title="statement not covered" > }</span>
969
- }
970
- &nbsp;
971
- /**
972
- * Confirms a direct upload was successful
973
- * @param fileId The ID of the file record
974
- * @param uploadSuccess Whether the upload was successful
975
- * @param errorMessage Optional error message if upload failed
976
- */
977
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function confirmDirectUpload(</span></span>
978
- <span class="cstat-no" title="statement not covered" > fileId: string,</span>
979
- <span class="cstat-no" title="statement not covered" > uploadSuccess: boolean,</span>
980
- <span class="cstat-no" title="statement not covered" > errorMessage?: string</span>
981
- <span class="cstat-no" title="statement not covered" >): Promise&lt;void&gt; {</span>
982
- <span class="cstat-no" title="statement not covered" > try {</span>
983
- // First fetch the file record to get the object path
984
- <span class="cstat-no" title="statement not covered" > const fileRecord = await prisma.file.findUnique({</span>
985
- <span class="cstat-no" title="statement not covered" > where: { id: fileId },</span>
986
- <span class="cstat-no" title="statement not covered" > select: { path: true }</span>
987
- <span class="cstat-no" title="statement not covered" > });</span>
988
- &nbsp;
989
- <span class="cstat-no" title="statement not covered" > if (!fileRecord) {</span>
990
- <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
991
- <span class="cstat-no" title="statement not covered" > code: 'NOT_FOUND',</span>
992
- <span class="cstat-no" title="statement not covered" > message: 'File record not found',</span>
993
- <span class="cstat-no" title="statement not covered" > });</span>
994
- <span class="cstat-no" title="statement not covered" > }</span>
995
- &nbsp;
996
- <span class="cstat-no" title="statement not covered" > let actualUploadSuccess = uploadSuccess;</span>
997
- <span class="cstat-no" title="statement not covered" > let actualErrorMessage = errorMessage;</span>
998
- &nbsp;
999
- // If uploadSuccess is true, verify the object actually exists in GCS
1000
- <span class="cstat-no" title="statement not covered" > if (uploadSuccess) {</span>
1001
- <span class="cstat-no" title="statement not covered" > try {</span>
1002
- <span class="cstat-no" title="statement not covered" > const exists = await objectExists(env.GOOGLE_CLOUD_BUCKET_NAME!, fileRecord.path);</span>
1003
- <span class="cstat-no" title="statement not covered" > if (!exists) {</span>
1004
- <span class="cstat-no" title="statement not covered" > actualUploadSuccess = false;</span>
1005
- <span class="cstat-no" title="statement not covered" > actualErrorMessage = 'File upload reported as successful but object not found in Google Cloud Storage';</span>
1006
- <span class="cstat-no" title="statement not covered" > logger.error(`File upload verification failed for ${fileId}: object ${fileRecord.path} not found in GCS`);</span>
1007
- <span class="cstat-no" title="statement not covered" > }</span>
1008
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1009
- <span class="cstat-no" title="statement not covered" > logger.error(`Error verifying file existence in GCS for ${fileId}:`, {error: error instanceof Error ? {</span>
1010
- <span class="cstat-no" title="statement not covered" > name: error.name,</span>
1011
- <span class="cstat-no" title="statement not covered" > message: error.message,</span>
1012
- <span class="cstat-no" title="statement not covered" > stack: error.stack,</span>
1013
- <span class="cstat-no" title="statement not covered" > } : error});</span>
1014
- <span class="cstat-no" title="statement not covered" > actualUploadSuccess = false;</span>
1015
- <span class="cstat-no" title="statement not covered" > actualErrorMessage = 'Failed to verify file existence in Google Cloud Storage';</span>
1016
- <span class="cstat-no" title="statement not covered" > }</span>
1017
- <span class="cstat-no" title="statement not covered" > }</span>
1018
- &nbsp;
1019
- <span class="cstat-no" title="statement not covered" > const updateData: any = {</span>
1020
- <span class="cstat-no" title="statement not covered" > uploadStatus: actualUploadSuccess ? 'COMPLETED' : 'FAILED',</span>
1021
- <span class="cstat-no" title="statement not covered" > uploadProgress: actualUploadSuccess ? 100 : 0,</span>
1022
- <span class="cstat-no" title="statement not covered" > };</span>
1023
-
1024
- <span class="cstat-no" title="statement not covered" > if (!actualUploadSuccess &amp;&amp; actualErrorMessage) {</span>
1025
- <span class="cstat-no" title="statement not covered" > updateData.uploadError = actualErrorMessage;</span>
1026
- <span class="cstat-no" title="statement not covered" > updateData.uploadRetryCount = { increment: 1 };</span>
1027
- <span class="cstat-no" title="statement not covered" > }</span>
1028
-
1029
- <span class="cstat-no" title="statement not covered" > if (actualUploadSuccess) {</span>
1030
- <span class="cstat-no" title="statement not covered" > updateData.uploadedAt = new Date();</span>
1031
- <span class="cstat-no" title="statement not covered" > }</span>
1032
-
1033
- <span class="cstat-no" title="statement not covered" > await prisma.file.update({</span>
1034
- <span class="cstat-no" title="statement not covered" > where: { id: fileId },</span>
1035
- <span class="cstat-no" title="statement not covered" > data: updateData</span>
1036
- <span class="cstat-no" title="statement not covered" > });</span>
1037
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1038
- <span class="cstat-no" title="statement not covered" > logger.error('Error confirming direct upload:', {error});</span>
1039
- <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1040
- <span class="cstat-no" title="statement not covered" > code: 'INTERNAL_SERVER_ERROR',</span>
1041
- <span class="cstat-no" title="statement not covered" > message: 'Failed to confirm upload',</span>
1042
- <span class="cstat-no" title="statement not covered" > });</span>
1043
- <span class="cstat-no" title="statement not covered" > }</span>
1044
- <span class="cstat-no" title="statement not covered" >}</span>
1045
- &nbsp;
1046
- /**
1047
- * Updates upload progress for a direct upload
1048
- * @param fileId The ID of the file record
1049
- * @param progress Progress percentage (0-100)
1050
- */
1051
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function updateUploadProgress(</span></span>
1052
- <span class="cstat-no" title="statement not covered" > fileId: string,</span>
1053
- <span class="cstat-no" title="statement not covered" > progress: number</span>
1054
- <span class="cstat-no" title="statement not covered" >): Promise&lt;void&gt; {</span>
1055
- <span class="cstat-no" title="statement not covered" > try {</span>
1056
- // await prisma.file.update({
1057
- // where: { id: fileId },
1058
- // data: {
1059
- // uploadStatus: 'UPLOADING',
1060
- // uploadProgress: Math.min(100, Math.max(0, progress))
1061
- // }
1062
- // });
1063
- <span class="cstat-no" title="statement not covered" > const current = await prisma.file.findUnique({ where: { id: fileId }, select: { uploadStatus: true } });</span>
1064
- <span class="cstat-no" title="statement not covered" > if (!current || ['COMPLETED','FAILED','CANCELLED'].includes(current.uploadStatus as string)) return;</span>
1065
- <span class="cstat-no" title="statement not covered" > const clamped = Math.min(100, Math.max(0, progress));</span>
1066
- <span class="cstat-no" title="statement not covered" > await prisma.file.update({</span>
1067
- <span class="cstat-no" title="statement not covered" > where: { id: fileId },</span>
1068
- <span class="cstat-no" title="statement not covered" > data: {</span>
1069
- <span class="cstat-no" title="statement not covered" > uploadStatus: 'UPLOADING',</span>
1070
- <span class="cstat-no" title="statement not covered" > uploadProgress: clamped</span>
1071
- <span class="cstat-no" title="statement not covered" > }</span>
1072
- <span class="cstat-no" title="statement not covered" > });</span>
1073
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1074
- <span class="cstat-no" title="statement not covered" > logger.error('Error updating upload progress:', {error: error instanceof Error ? {</span>
1075
- <span class="cstat-no" title="statement not covered" > name: error.name,</span>
1076
- <span class="cstat-no" title="statement not covered" > message: error.message,</span>
1077
- <span class="cstat-no" title="statement not covered" > stack: error.stack,</span>
1078
- <span class="cstat-no" title="statement not covered" > } : error}); </span>
1079
- <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1080
- <span class="cstat-no" title="statement not covered" > code: 'INTERNAL_SERVER_ERROR',</span>
1081
- <span class="cstat-no" title="statement not covered" > message: 'Failed to update upload progress',</span>
1082
- <span class="cstat-no" title="statement not covered" > });</span>
1083
- <span class="cstat-no" title="statement not covered" > }</span>
1084
- <span class="cstat-no" title="statement not covered" >}</span>
1085
- &nbsp;
1086
- /**
1087
- * Creates multiple direct upload files
1088
- * @param files Array of file metadata
1089
- * @param userId The ID of the user uploading the files
1090
- * @param directory Optional subdirectory to store the files in
1091
- * @param assignmentId Optional assignment ID to associate files with
1092
- * @param submissionId Optional submission ID to associate files with
1093
- * @returns Array of direct upload file information
1094
- */
1095
- export async function createDirectUploadFiles(
1096
- files: DirectFileData[],
1097
- userId: string,
1098
- directory?: string,
1099
- assignmentId?: string,
1100
- submissionId?: string,
1101
- announcementId?: string
1102
- ): Promise&lt;DirectUploadFile[]&gt; {
1103
- try {
1104
- const uploadPromises = files.map(file =&gt;
1105
- createDirectUploadFile(file, userId, directory, assignmentId, submissionId, announcementId)
1106
- );
1107
- return await Promise.all(uploadPromises);
1108
- <span class="branch-0 cbranch-no" title="branch not covered" > } catch (error) {</span>
1109
- <span class="cstat-no" title="statement not covered" > logger.error('Error creating direct upload files:', {error: error instanceof Error ? {</span>
1110
- <span class="cstat-no" title="statement not covered" > name: error.name,</span>
1111
- <span class="cstat-no" title="statement not covered" > message: error.message,</span>
1112
- <span class="cstat-no" title="statement not covered" > stack: error.stack,</span>
1113
- <span class="cstat-no" title="statement not covered" > } : error});</span>
1114
- <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1115
- <span class="cstat-no" title="statement not covered" > code: 'INTERNAL_SERVER_ERROR',</span>
1116
- <span class="cstat-no" title="statement not covered" > message: 'Failed to create direct upload files',</span>
1117
- <span class="cstat-no" title="statement not covered" > });</span>
1118
- <span class="cstat-no" title="statement not covered" > }</span>
1119
- }</pre></td></tr></table></pre>
1120
-
1121
- <div class='push'></div><!-- for sticky footer -->
1122
- </div><!-- /wrapper -->
1123
- <div class='footer quiet pad2 space-top1 center small'>
1124
- Code coverage generated by
1125
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1126
- at 2025-11-22T10:42:40.796Z
1127
- </div>
1128
- <script src="../../../prettify.js"></script>
1129
- <script>
1130
- window.onload = function () {
1131
- prettyPrint();
1132
- };
1133
- </script>
1134
- <script src="../../../sorter.js"></script>
1135
- <script src="../../../block-navigation.js"></script>
1136
- </body>
1137
- </html>
1138
-