@studious-lms/server 1.13.0 → 1.15.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 (375) hide show
  1. package/.dockerignore +28 -0
  2. package/.env.example +5 -0
  3. package/.github/workflows/deploy.yml +123 -0
  4. package/Dockerfile +54 -0
  5. package/dist/index.js +5 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/instrument.js +3 -3
  8. package/dist/instrument.js.map +1 -1
  9. package/dist/lib/config/cors.d.ts.map +1 -1
  10. package/dist/lib/config/cors.js +31 -11
  11. package/dist/lib/config/cors.js.map +1 -1
  12. package/dist/lib/config/env.d.ts +17 -0
  13. package/dist/lib/config/env.d.ts.map +1 -1
  14. package/dist/lib/config/env.js +8 -2
  15. package/dist/lib/config/env.js.map +1 -1
  16. package/dist/lib/googleCloudStorage.d.ts +10 -0
  17. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  18. package/dist/lib/googleCloudStorage.js +22 -2
  19. package/dist/lib/googleCloudStorage.js.map +1 -1
  20. package/dist/lib/inferDocumentFormat.d.ts +10 -0
  21. package/dist/lib/inferDocumentFormat.d.ts.map +1 -0
  22. package/dist/lib/inferDocumentFormat.js +48 -0
  23. package/dist/lib/inferDocumentFormat.js.map +1 -0
  24. package/dist/lib/legal.d.ts +3 -0
  25. package/dist/lib/legal.d.ts.map +1 -0
  26. package/dist/lib/legal.js +6 -0
  27. package/dist/lib/legal.js.map +1 -0
  28. package/dist/lib/prisma.d.ts +104 -5
  29. package/dist/lib/prisma.d.ts.map +1 -1
  30. package/dist/lib/prisma.js +33 -2
  31. package/dist/lib/prisma.js.map +1 -1
  32. package/dist/models/agenda.d.ts +20 -20
  33. package/dist/models/announcement.d.ts +211 -101
  34. package/dist/models/announcement.d.ts.map +1 -1
  35. package/dist/models/assignment.d.ts +560 -362
  36. package/dist/models/assignment.d.ts.map +1 -1
  37. package/dist/models/attendance.d.ts +197 -71
  38. package/dist/models/attendance.d.ts.map +1 -1
  39. package/dist/models/auth.d.ts +356 -114
  40. package/dist/models/auth.d.ts.map +1 -1
  41. package/dist/models/auth.js +4 -2
  42. package/dist/models/auth.js.map +1 -1
  43. package/dist/models/class.d.ts +327 -201
  44. package/dist/models/class.d.ts.map +1 -1
  45. package/dist/models/class.js +2 -2
  46. package/dist/models/class.js.map +1 -1
  47. package/dist/models/cloudStorage.d.ts +146 -56
  48. package/dist/models/cloudStorage.d.ts.map +1 -1
  49. package/dist/models/comment.d.ts +262 -110
  50. package/dist/models/comment.d.ts.map +1 -1
  51. package/dist/models/conversation.d.ts +206 -80
  52. package/dist/models/conversation.d.ts.map +1 -1
  53. package/dist/models/department.d.ts +196 -70
  54. package/dist/models/department.d.ts.map +1 -1
  55. package/dist/models/event.d.ts +305 -141
  56. package/dist/models/event.d.ts.map +1 -1
  57. package/dist/models/file.d.ts +422 -272
  58. package/dist/models/file.d.ts.map +1 -1
  59. package/dist/models/folder.d.ts +433 -181
  60. package/dist/models/folder.d.ts.map +1 -1
  61. package/dist/models/labChat.d.ts +205 -79
  62. package/dist/models/labChat.d.ts.map +1 -1
  63. package/dist/models/marketing.d.ts +79 -38
  64. package/dist/models/marketing.d.ts.map +1 -1
  65. package/dist/models/marketing.js +12 -4
  66. package/dist/models/marketing.js.map +1 -1
  67. package/dist/models/message.d.ts +97 -43
  68. package/dist/models/message.d.ts.map +1 -1
  69. package/dist/models/newtonChat.d.ts +84 -30
  70. package/dist/models/newtonChat.d.ts.map +1 -1
  71. package/dist/models/notification.d.ts +57 -21
  72. package/dist/models/notification.d.ts.map +1 -1
  73. package/dist/models/school.d.ts +349 -133
  74. package/dist/models/school.d.ts.map +1 -1
  75. package/dist/models/section.d.ts +216 -72
  76. package/dist/models/section.d.ts.map +1 -1
  77. package/dist/models/tag.d.ts +156 -48
  78. package/dist/models/tag.d.ts.map +1 -1
  79. package/dist/models/user.d.ts +82 -28
  80. package/dist/models/user.d.ts.map +1 -1
  81. package/dist/models/worksheet.d.ts +1032 -423
  82. package/dist/models/worksheet.d.ts.map +1 -1
  83. package/dist/models/worksheet.js +8 -2
  84. package/dist/models/worksheet.js.map +1 -1
  85. package/dist/pipelines/aiLabChat.d.ts +7 -9
  86. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  87. package/dist/pipelines/aiLabChat.js +194 -125
  88. package/dist/pipelines/aiLabChat.js.map +1 -1
  89. package/dist/pipelines/aiLabChatContract.d.ts +233 -389
  90. package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
  91. package/dist/pipelines/aiLabChatContract.js +54 -70
  92. package/dist/pipelines/aiLabChatContract.js.map +1 -1
  93. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
  94. package/dist/pipelines/aiNewtonChat.js +41 -41
  95. package/dist/pipelines/aiNewtonChat.js.map +1 -1
  96. package/dist/pipelines/gradeWorksheet.d.ts +8 -8
  97. package/dist/pipelines/labChatPrompt.d.ts +18 -11
  98. package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
  99. package/dist/pipelines/labChatPrompt.js +93 -75
  100. package/dist/pipelines/labChatPrompt.js.map +1 -1
  101. package/dist/pipelines/pdfToWorksheet.d.ts +1 -1
  102. package/dist/routers/_app.d.ts +2601 -2151
  103. package/dist/routers/_app.d.ts.map +1 -1
  104. package/dist/routers/_app.js +4 -2
  105. package/dist/routers/_app.js.map +1 -1
  106. package/dist/routers/admin.d.ts +13 -13
  107. package/dist/routers/agenda.d.ts +18 -18
  108. package/dist/routers/announcement.d.ts +60 -60
  109. package/dist/routers/assignment.d.ts +393 -383
  110. package/dist/routers/assignment.d.ts.map +1 -1
  111. package/dist/routers/attendance.d.ts +10 -10
  112. package/dist/routers/auth.d.ts +4 -2
  113. package/dist/routers/auth.d.ts.map +1 -1
  114. package/dist/routers/auth.js +15 -2
  115. package/dist/routers/auth.js.map +1 -1
  116. package/dist/routers/class.d.ts +157 -153
  117. package/dist/routers/class.d.ts.map +1 -1
  118. package/dist/routers/comment.d.ts +18 -18
  119. package/dist/routers/conversation.d.ts +11 -11
  120. package/dist/routers/department.d.ts +34 -34
  121. package/dist/routers/discussion.d.ts +68 -56
  122. package/dist/routers/discussion.d.ts.map +1 -1
  123. package/dist/routers/discussion.js +6 -2
  124. package/dist/routers/discussion.js.map +1 -1
  125. package/dist/routers/embedding.d.ts +73 -0
  126. package/dist/routers/embedding.d.ts.map +1 -0
  127. package/dist/routers/embedding.js +151 -0
  128. package/dist/routers/embedding.js.map +1 -0
  129. package/dist/routers/event.d.ts +57 -55
  130. package/dist/routers/event.d.ts.map +1 -1
  131. package/dist/routers/file.d.ts +14 -14
  132. package/dist/routers/folder.d.ts +38 -38
  133. package/dist/routers/labChat.d.ts +16 -16
  134. package/dist/routers/marketing.d.ts +1 -14
  135. package/dist/routers/marketing.d.ts.map +1 -1
  136. package/dist/routers/message.d.ts +13 -13
  137. package/dist/routers/newtonChat.d.ts +4 -4
  138. package/dist/routers/notifications.d.ts +5 -5
  139. package/dist/routers/permissions.d.ts +14 -14
  140. package/dist/routers/school.d.ts +59 -55
  141. package/dist/routers/school.d.ts.map +1 -1
  142. package/dist/routers/search.d.ts +22 -1
  143. package/dist/routers/search.d.ts.map +1 -1
  144. package/dist/routers/search.js +9 -3
  145. package/dist/routers/search.js.map +1 -1
  146. package/dist/routers/section.d.ts +4 -4
  147. package/dist/routers/studentProgress.d.ts +1 -1
  148. package/dist/routers/tag.d.ts +7 -7
  149. package/dist/routers/user.d.ts +99 -10
  150. package/dist/routers/user.d.ts.map +1 -1
  151. package/dist/routers/user.js +19 -2
  152. package/dist/routers/user.js.map +1 -1
  153. package/dist/routers/worksheet.d.ts +93 -55
  154. package/dist/routers/worksheet.d.ts.map +1 -1
  155. package/dist/routers/worksheet.js +26 -2
  156. package/dist/routers/worksheet.js.map +1 -1
  157. package/dist/routes/aiStream.d.ts +2 -0
  158. package/dist/routes/aiStream.d.ts.map +1 -0
  159. package/dist/routes/aiStream.js +726 -0
  160. package/dist/routes/aiStream.js.map +1 -0
  161. package/dist/seedDatabase.d.ts +3 -1
  162. package/dist/seedDatabase.d.ts.map +1 -1
  163. package/dist/seedDatabase.js +6 -6
  164. package/dist/seedDatabase.js.map +1 -1
  165. package/dist/services/adminInstitution.d.ts +8 -8
  166. package/dist/services/adminRunJob.d.ts +4 -4
  167. package/dist/services/agenda.d.ts +18 -18
  168. package/dist/services/aiChatStream.d.ts +88 -0
  169. package/dist/services/aiChatStream.d.ts.map +1 -0
  170. package/dist/services/aiChatStream.js +254 -0
  171. package/dist/services/aiChatStream.js.map +1 -0
  172. package/dist/services/aiModifierTools.d.ts +16 -0
  173. package/dist/services/aiModifierTools.d.ts.map +1 -0
  174. package/dist/services/aiModifierTools.js +274 -0
  175. package/dist/services/aiModifierTools.js.map +1 -0
  176. package/dist/services/aiProposalTools.d.ts +32 -0
  177. package/dist/services/aiProposalTools.d.ts.map +1 -0
  178. package/dist/services/aiProposalTools.js +207 -0
  179. package/dist/services/aiProposalTools.js.map +1 -0
  180. package/dist/services/aiStream.d.ts +22 -0
  181. package/dist/services/aiStream.d.ts.map +1 -0
  182. package/dist/services/aiStream.js +142 -0
  183. package/dist/services/aiStream.js.map +1 -0
  184. package/dist/services/aiTools.d.ts +16 -0
  185. package/dist/services/aiTools.d.ts.map +1 -0
  186. package/dist/services/aiTools.js +271 -0
  187. package/dist/services/aiTools.js.map +1 -0
  188. package/dist/services/announcement.d.ts +42 -42
  189. package/dist/services/announcement.d.ts.map +1 -1
  190. package/dist/services/announcement.js +7 -2
  191. package/dist/services/announcement.js.map +1 -1
  192. package/dist/services/assignment.d.ts +355 -345
  193. package/dist/services/assignment.d.ts.map +1 -1
  194. package/dist/services/assignment.js +30 -9
  195. package/dist/services/assignment.js.map +1 -1
  196. package/dist/services/attendance.d.ts +10 -10
  197. package/dist/services/auth.d.ts +4 -2
  198. package/dist/services/auth.d.ts.map +1 -1
  199. package/dist/services/auth.js +13 -4
  200. package/dist/services/auth.js.map +1 -1
  201. package/dist/services/class.d.ts +146 -142
  202. package/dist/services/class.d.ts.map +1 -1
  203. package/dist/services/class.js +24 -4
  204. package/dist/services/class.js.map +1 -1
  205. package/dist/services/comment.d.ts +18 -18
  206. package/dist/services/conversation.d.ts +11 -11
  207. package/dist/services/department.d.ts +33 -33
  208. package/dist/services/discussion.d.ts +58 -58
  209. package/dist/services/discussion.d.ts.map +1 -1
  210. package/dist/services/discussion.js +15 -8
  211. package/dist/services/discussion.js.map +1 -1
  212. package/dist/services/discussionSummary.d.ts +21 -0
  213. package/dist/services/discussionSummary.d.ts.map +1 -0
  214. package/dist/services/discussionSummary.js +179 -0
  215. package/dist/services/discussionSummary.js.map +1 -0
  216. package/dist/services/embedding.d.ts +85 -0
  217. package/dist/services/embedding.d.ts.map +1 -0
  218. package/dist/services/embedding.js +372 -0
  219. package/dist/services/embedding.js.map +1 -0
  220. package/dist/services/event.d.ts +55 -53
  221. package/dist/services/event.d.ts.map +1 -1
  222. package/dist/services/file.d.ts +28 -28
  223. package/dist/services/folder.d.ts +36 -36
  224. package/dist/services/folder.d.ts.map +1 -1
  225. package/dist/services/folder.js +32 -2
  226. package/dist/services/folder.js.map +1 -1
  227. package/dist/services/labChat.d.ts +16 -16
  228. package/dist/services/marketing.d.ts +2 -15
  229. package/dist/services/marketing.d.ts.map +1 -1
  230. package/dist/services/marketing.js +5 -5
  231. package/dist/services/marketing.js.map +1 -1
  232. package/dist/services/message.d.ts +11 -11
  233. package/dist/services/message.d.ts.map +1 -1
  234. package/dist/services/message.js +2 -2
  235. package/dist/services/message.js.map +1 -1
  236. package/dist/services/newtonChat.d.ts +4 -4
  237. package/dist/services/notification.d.ts +5 -5
  238. package/dist/services/notification.d.ts.map +1 -1
  239. package/dist/services/openaiDocumentGen.d.ts +37 -0
  240. package/dist/services/openaiDocumentGen.d.ts.map +1 -0
  241. package/dist/services/openaiDocumentGen.js +262 -0
  242. package/dist/services/openaiDocumentGen.js.map +1 -0
  243. package/dist/services/permissions.d.ts +14 -14
  244. package/dist/services/school.d.ts +54 -50
  245. package/dist/services/school.d.ts.map +1 -1
  246. package/dist/services/search.d.ts +13 -1
  247. package/dist/services/search.d.ts.map +1 -1
  248. package/dist/services/search.js +145 -2
  249. package/dist/services/search.js.map +1 -1
  250. package/dist/services/section.d.ts +3 -3
  251. package/dist/services/tag.d.ts +4 -4
  252. package/dist/services/user.d.ts +4 -4
  253. package/dist/services/user.d.ts.map +1 -1
  254. package/dist/services/user.js +10 -15
  255. package/dist/services/user.js.map +1 -1
  256. package/dist/services/userPrivacy.d.ts +86 -0
  257. package/dist/services/userPrivacy.d.ts.map +1 -0
  258. package/dist/services/userPrivacy.js +184 -0
  259. package/dist/services/userPrivacy.js.map +1 -0
  260. package/dist/services/worksheet.d.ts +86 -57
  261. package/dist/services/worksheet.d.ts.map +1 -1
  262. package/dist/services/worksheet.js +57 -5
  263. package/dist/services/worksheet.js.map +1 -1
  264. package/dist/utils/email.d.ts.map +1 -1
  265. package/dist/utils/email.js +7 -3
  266. package/dist/utils/email.js.map +1 -1
  267. package/dist/utils/streamBroadcast.d.ts +11 -0
  268. package/dist/utils/streamBroadcast.d.ts.map +1 -0
  269. package/dist/utils/streamBroadcast.js +32 -0
  270. package/dist/utils/streamBroadcast.js.map +1 -0
  271. package/dist/workers/connection.d.ts +15 -0
  272. package/dist/workers/connection.d.ts.map +1 -1
  273. package/dist/workers/connection.js +20 -2
  274. package/dist/workers/connection.js.map +1 -1
  275. package/dist/workers/index.js +4 -2
  276. package/dist/workers/index.js.map +1 -1
  277. package/dist/workers/processors/createRunJobWorker.d.ts.map +1 -1
  278. package/dist/workers/processors/createRunJobWorker.js +31 -8
  279. package/dist/workers/processors/createRunJobWorker.js.map +1 -1
  280. package/dist/workers/processors/embedContent.d.ts +8 -0
  281. package/dist/workers/processors/embedContent.d.ts.map +1 -0
  282. package/dist/workers/processors/embedContent.js +67 -0
  283. package/dist/workers/processors/embedContent.js.map +1 -0
  284. package/dist/workers/queues.d.ts +6 -0
  285. package/dist/workers/queues.d.ts.map +1 -1
  286. package/dist/workers/queues.js +5 -3
  287. package/dist/workers/queues.js.map +1 -1
  288. package/package.json +5 -1
  289. package/prisma/migrations/20260609215135_init/migration.sql +1412 -0
  290. package/prisma/migrations/20260610130000_add_worksheet_tags/migration.sql +13 -0
  291. package/prisma/migrations/20260610140000_expand_embedding_source_types/migration.sql +4 -0
  292. package/prisma/migrations/20260611120000_add_user_terms_acceptance/migration.sql +3 -0
  293. package/prisma/schema.prisma +44 -7
  294. package/src/index.ts +4 -0
  295. package/src/instrument.ts +1 -1
  296. package/src/lib/config/cors.ts +32 -9
  297. package/src/lib/config/env.ts +6 -0
  298. package/src/lib/googleCloudStorage.ts +21 -0
  299. package/src/lib/inferDocumentFormat.ts +58 -0
  300. package/src/lib/legal.ts +2 -0
  301. package/src/lib/prisma.ts +40 -1
  302. package/src/models/auth.ts +4 -0
  303. package/src/models/class.ts +3 -2
  304. package/src/models/marketing.ts +10 -2
  305. package/src/models/worksheet.ts +5 -2
  306. package/src/pipelines/aiLabChat.ts +245 -146
  307. package/src/pipelines/aiLabChatContract.ts +59 -69
  308. package/src/pipelines/aiNewtonChat.ts +46 -43
  309. package/src/pipelines/labChatPrompt.ts +115 -90
  310. package/src/routers/_app.ts +2 -0
  311. package/src/routers/auth.ts +13 -0
  312. package/src/routers/discussion.ts +7 -0
  313. package/src/routers/embedding.ts +164 -0
  314. package/src/routers/search.ts +10 -1
  315. package/src/routers/user.ts +26 -0
  316. package/src/routers/worksheet.ts +27 -0
  317. package/src/routes/aiStream.ts +827 -0
  318. package/src/seedDatabase.ts +4 -4
  319. package/src/services/aiChatStream.ts +341 -0
  320. package/src/services/aiModifierTools.ts +341 -0
  321. package/src/services/aiProposalTools.ts +274 -0
  322. package/src/services/aiStream.ts +175 -0
  323. package/src/services/aiTools.ts +290 -0
  324. package/src/services/announcement.ts +7 -0
  325. package/src/services/assignment.ts +31 -7
  326. package/src/services/auth.ts +14 -2
  327. package/src/services/class.ts +27 -2
  328. package/src/services/discussion.ts +22 -8
  329. package/src/services/discussionSummary.ts +226 -0
  330. package/src/services/embedding.ts +446 -0
  331. package/src/services/folder.ts +31 -0
  332. package/src/services/marketing.ts +3 -3
  333. package/src/services/message.ts +2 -2
  334. package/src/services/openaiDocumentGen.ts +319 -0
  335. package/src/services/search.ts +163 -1
  336. package/src/services/user.ts +9 -17
  337. package/src/services/userPrivacy.ts +196 -0
  338. package/src/services/worksheet.ts +77 -3
  339. package/src/utils/email.ts +5 -1
  340. package/src/utils/streamBroadcast.ts +48 -0
  341. package/src/workers/connection.ts +19 -0
  342. package/src/workers/index.ts +2 -0
  343. package/src/workers/processors/createRunJobWorker.ts +32 -6
  344. package/src/workers/processors/embedContent.ts +86 -0
  345. package/src/workers/queues.ts +5 -1
  346. package/tests/helpers/registerInput.ts +20 -0
  347. package/tests/integration/globalSetup.ts +10 -18
  348. package/tests/integration/routers/auth.test.ts +13 -18
  349. package/tests/unit/lib/inferDocumentFormat.test.ts +33 -0
  350. package/tests/unit/pipelines/aiLabChatContract.test.ts +38 -21
  351. package/tests/unit/pipelines/labChatPrompt.test.ts +23 -36
  352. package/tests/unit/services/aiChatStream.test.ts +92 -0
  353. package/tests/unit/services/openaiDocumentGen.test.ts +65 -0
  354. package/prisma/migrations/20250807062924_init/migration.sql +0 -436
  355. package/prisma/migrations/20250919063704_init2/migration.sql +0 -24
  356. package/prisma/migrations/20250920143543_add_profile_fields/migration.sql +0 -15
  357. package/prisma/migrations/20250922165147_add_chat_models/migration.sql +0 -68
  358. package/prisma/migrations/20250922165314_add_chat_roles/migration.sql +0 -5
  359. package/prisma/migrations/20250922171242_refactor_notification_system/migration.sql +0 -20
  360. package/prisma/migrations/20250922172208_add_mentions_system/migration.sql +0 -21
  361. package/prisma/migrations/20250925072732_add_lab_chat_system/migration.sql +0 -25
  362. package/prisma/migrations/20251020151505_add_upload_tracking_fields/migration.sql +0 -57
  363. package/prisma/migrations/20251109122857_annuoncements_comments/migration.sql +0 -30
  364. package/prisma/migrations/20251109135555_reactions_announcements_comments/migration.sql +0 -35
  365. package/prisma/migrations/20260410124000_add_submission_recommendation_state/migration.sql +0 -14
  366. package/prisma/migrations/20260415103500_add_session_type/migration.sql +0 -33
  367. package/prisma/migrations/20260415133000_add_ai_usage_logs/migration.sql +0 -19
  368. package/prisma/migrations/20260417083000_add_conversation_member_hidden_at/migration.sql +0 -2
  369. package/prisma/migrations/20260502230500_assignment_submission_comments/migration.sql +0 -60
  370. package/prisma/migrations/20260504071500_school_memberships/migration.sql +0 -81
  371. package/prisma/migrations/20260506162500_consolidate_run_job_and_unify_job_status/migration.sql +0 -166
  372. package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +0 -184
  373. package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +0 -93
  374. package/prisma/migrations/20260510183000_add_discussions/migration.sql +0 -151
  375. /package/.github/workflows/{npm.yml → npm-publish.yml} +0 -0
@@ -2,7 +2,7 @@
2
2
  * Announcement service – create, read, update, delete announcements.
3
3
  */
4
4
 
5
- !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]="88216f33-8458-56ce-84c5-509e783dc4e6")}catch(e){}}();
5
+ !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]="c5ff2131-07ed-588e-a43a-05af5641c732")}catch(e){}}();
6
6
  import { TRPCError } from "@trpc/server";
7
7
  import { findAnnouncementsByClassId, findAnnouncementByIdAndClass, findAnnouncementWithClass, createAnnouncement, updateAnnouncementAttachments, deleteAnnouncement, } from "../models/announcement.js";
8
8
  import { prisma } from "../lib/prisma.js";
@@ -10,6 +10,7 @@ import { createDirectUploadFiles } from "../lib/fileUpload.js";
10
10
  import { deleteFile } from "../lib/googleCloudStorage.js";
11
11
  import { sendToMultiple } from "./notification.js";
12
12
  import { logger } from "../utils/logger.js";
13
+ import { enqueueEmbedding } from "./embedding.js";
13
14
  export async function getAllAnnouncements(classId) {
14
15
  const announcements = await findAnnouncementsByClassId(classId);
15
16
  const announcementsWithCounts = announcements.map((a) => ({
@@ -95,6 +96,8 @@ export async function createAnnouncementRecord(userId, input) {
95
96
  }).catch((error) => {
96
97
  logger.error("Failed to send announcement notifications:", error);
97
98
  });
99
+ // Auto-index announcement for RAG search
100
+ enqueueEmbedding(classId, 'ANNOUNCEMENT', announcement.id);
98
101
  return {
99
102
  announcement: announcementWithAttachments || announcement,
100
103
  uploadFiles: directUploadFiles.length > 0 ? directUploadFiles : undefined,
@@ -197,6 +200,8 @@ export async function updateAnnouncementRecord(userId, input) {
197
200
  },
198
201
  },
199
202
  });
203
+ // Re-index announcement for RAG search after update
204
+ enqueueEmbedding(input.classId, 'ANNOUNCEMENT', input.id);
200
205
  return {
201
206
  announcement: updatedAnnouncement,
202
207
  uploadFiles: directUploadFiles.length > 0 ? directUploadFiles : undefined,
@@ -224,4 +229,4 @@ export async function deleteAnnouncementRecord(userId, id, classId) {
224
229
  return { success: true };
225
230
  }
226
231
  //# sourceMappingURL=announcement.js.map
227
- //# debugId=88216f33-8458-56ce-84c5-509e783dc4e6
232
+ //# debugId=c5ff2131-07ed-588e-a43a-05af5641c732
@@ -1 +1 @@
1
- {"version":3,"file":"announcement.js","sources":["services/announcement.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Announcement service – create, read, update, delete announcements.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport {\n findAnnouncementsByClassId,\n findAnnouncementByIdAndClass,\n findAnnouncementWithClass,\n createAnnouncement,\n updateAnnouncement,\n updateAnnouncementAttachments,\n deleteAnnouncement,\n} from \"../models/announcement.js\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { createDirectUploadFiles, type DirectUploadFile } from \"../lib/fileUpload.js\";\nimport { deleteFile } from \"../lib/googleCloudStorage.js\";\nimport { sendToMultiple } from \"./notification.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport async function getAllAnnouncements(classId: string) {\n const announcements = await findAnnouncementsByClassId(classId);\n const announcementsWithCounts = announcements.map((a) => ({\n ...a,\n commentCount: a._count.comments,\n _count: undefined,\n }));\n return { announcements: announcementsWithCounts };\n}\n\nexport async function getAnnouncement(id: string, classId: string) {\n const announcement = await findAnnouncementByIdAndClass(id, classId);\n if (!announcement) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Announcement not found\",\n });\n }\n return { announcement };\n}\n\nexport async function createAnnouncementRecord(\n userId: string,\n input: {\n classId: string;\n remarks: string;\n files?: { name: string; type: string; size: number }[];\n existingFileIds?: string[];\n }\n) {\n const { classId, remarks, files, existingFileIds } = input;\n\n const classData = await prisma.class.findUnique({\n where: { id: classId },\n include: { students: { select: { id: true } } },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found\",\n });\n }\n\n const announcement = await createAnnouncement({\n remarks,\n teacherId: userId,\n classId,\n });\n\n let directUploadFiles: DirectUploadFile[] = [];\n if (files && files.length > 0) {\n directUploadFiles = await createDirectUploadFiles(\n files,\n userId,\n undefined,\n undefined,\n undefined,\n announcement.id\n );\n }\n\n if (existingFileIds && existingFileIds.length > 0) {\n await updateAnnouncementAttachments(announcement.id, {\n connect: existingFileIds.map((fileId) => ({ id: fileId })),\n });\n }\n\n const announcementWithAttachments = await prisma.announcement.findUnique({\n where: { id: announcement.id },\n select: {\n id: true,\n teacher: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n remarks: true,\n createdAt: true,\n modifiedAt: true,\n attachments: {\n select: {\n id: true,\n name: true,\n type: true,\n size: true,\n path: true,\n uploadedAt: true,\n thumbnailId: true,\n },\n },\n },\n });\n\n sendToMultiple({\n receiverIds: classData.students.map((s) => s.id),\n title: `New announcement in ${classData.name}`,\n content: `${remarks}\\n\\n[View announcement](/class/${classId})`,\n }).catch((error) => {\n logger.error(\"Failed to send announcement notifications:\", error);\n });\n\n return {\n announcement: announcementWithAttachments || announcement,\n uploadFiles: directUploadFiles.length > 0 ? directUploadFiles : undefined,\n };\n}\n\nexport async function updateAnnouncementRecord(\n userId: string,\n input: {\n id: string;\n classId: string;\n data: {\n remarks?: string;\n files?: { name: string; type: string; size: number }[];\n existingFileIds?: string[];\n removedAttachments?: string[];\n };\n }\n) {\n const announcement = await findAnnouncementWithClass(input.id);\n\n if (!announcement) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Announcement not found\",\n });\n }\n\n const isCreator = announcement.teacherId === userId;\n const isClassTeacher = announcement.class.teachers.some((t) => t.id === userId);\n const isSchoolAdmin = Boolean(\n announcement.class.school?.memberships.some((admin) => admin.userId === userId) ||\n announcement.class.school?.users.some((admin) => admin.id === userId)\n );\n\n if (!isCreator && !isClassTeacher && !isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the announcement creator, class teachers, or school admins can update announcements\",\n });\n }\n\n let directUploadFiles: DirectUploadFile[] = [];\n if (input.data.files && input.data.files.length > 0) {\n directUploadFiles = await createDirectUploadFiles(\n input.data.files,\n userId,\n undefined,\n undefined,\n undefined,\n input.id\n );\n }\n\n if (input.data.removedAttachments && input.data.removedAttachments.length > 0) {\n const filesToDelete = announcement.attachments.filter((f) =>\n input.data.removedAttachments!.includes(f.id)\n );\n await Promise.all(\n filesToDelete.map(async (file) => {\n try {\n if (file.uploadStatus === \"COMPLETED\") {\n await deleteFile(file.path);\n if (file.thumbnail?.path) {\n await deleteFile(file.thumbnail.path);\n }\n }\n } catch (error) {\n logger.warn(`Failed to delete file ${file.path}:`, {\n error: error instanceof Error ? { name: error.name, message: error.message } : error,\n });\n }\n })\n );\n }\n\n const updateData: { remarks?: string; attachments?: object } = {};\n if (input.data.remarks) updateData.remarks = input.data.remarks;\n\n if (input.data.existingFileIds && input.data.existingFileIds.length > 0) {\n await prisma.announcement.update({\n where: { id: input.id },\n data: {\n attachments: {\n connect: input.data.existingFileIds.map((fileId) => ({ id: fileId })),\n },\n },\n });\n }\n\n if (input.data.removedAttachments && input.data.removedAttachments.length > 0) {\n await prisma.announcement.update({\n where: { id: input.id },\n data: {\n attachments: {\n deleteMany: { id: { in: input.data.removedAttachments } },\n },\n },\n });\n }\n\n const updatedAnnouncement = await prisma.announcement.update({\n where: { id: input.id },\n data: updateData,\n select: {\n id: true,\n teacher: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n remarks: true,\n createdAt: true,\n modifiedAt: true,\n attachments: {\n select: {\n id: true,\n name: true,\n type: true,\n size: true,\n path: true,\n uploadedAt: true,\n thumbnailId: true,\n },\n },\n },\n });\n\n return {\n announcement: updatedAnnouncement,\n uploadFiles: directUploadFiles.length > 0 ? directUploadFiles : undefined,\n };\n}\n\nexport async function deleteAnnouncementRecord(userId: string, id: string, classId: string) {\n const announcement = await findAnnouncementWithClass(id);\n\n if (!announcement) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Announcement not found\",\n });\n }\n\n const isCreator = announcement.teacherId === userId;\n const isClassTeacher = announcement.class.teachers.some((t) => t.id === userId);\n const isSchoolAdmin = Boolean(\n announcement.class.school?.memberships.some((admin) => admin.userId === userId) ||\n announcement.class.school?.users.some((admin) => admin.id === userId)\n );\n\n if (!isCreator && !isClassTeacher && !isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the announcement creator, class teachers, or school admins can delete announcements\",\n });\n }\n\n await deleteAnnouncement(id);\n return { success: true };\n}\n"],"names":[],"mappings":"AAAA;;GAEG;;;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAElB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAyB,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAe;IACvD,MAAM,aAAa,GAAG,MAAM,0BAA0B,CAAC,OAAO,CAAC,CAAC;IAChE,MAAM,uBAAuB,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxD,GAAG,CAAC;QACJ,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ;QAC/B,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC,CAAC;IACJ,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAU,EAAE,OAAe;IAC/D,MAAM,YAAY,GAAG,MAAM,4BAA4B,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACrE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,wBAAwB;SAClC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAc,EACd,KAKC;IAED,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAE3D,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;QAC9C,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;QACtB,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;KAChD,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,iBAAiB;SAC3B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC;QAC5C,OAAO;QACP,SAAS,EAAE,MAAM;QACjB,OAAO;KACR,CAAC,CAAC;IAEH,IAAI,iBAAiB,GAAuB,EAAE,CAAC;IAC/C,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,iBAAiB,GAAG,MAAM,uBAAuB,CAC/C,KAAK,EACL,MAAM,EACN,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,CAAC,EAAE,CAChB,CAAC;IACJ,CAAC;IAED,IAAI,eAAe,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,6BAA6B,CAAC,YAAY,CAAC,EAAE,EAAE;YACnD,OAAO,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;SAC3D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,2BAA2B,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;QACvE,KAAK,EAAE,EAAE,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE;QAC9B,MAAM,EAAE;YACN,EAAE,EAAE,IAAI;YACR,OAAO,EAAE;gBACP,MAAM,EAAE;oBACN,EAAE,EAAE,IAAI;oBACR,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE;wBACP,MAAM,EAAE;4BACN,WAAW,EAAE,IAAI;4BACjB,cAAc,EAAE,IAAI;4BACpB,uBAAuB,EAAE,IAAI;yBAC9B;qBACF;iBACF;aACF;YACD,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE;gBACX,MAAM,EAAE;oBACN,EAAE,EAAE,IAAI;oBACR,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,IAAI;oBACV,UAAU,EAAE,IAAI;oBAChB,WAAW,EAAE,IAAI;iBAClB;aACF;SACF;KACF,CAAC,CAAC;IAEH,cAAc,CAAC;QACb,WAAW,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,KAAK,EAAE,uBAAuB,SAAS,CAAC,IAAI,EAAE;QAC9C,OAAO,EAAE,GAAG,OAAO,kCAAkC,OAAO,GAAG;KAChE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACjB,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,YAAY,EAAE,2BAA2B,IAAI,YAAY;QACzD,WAAW,EAAE,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;KAC1E,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAc,EACd,KASC;IAED,MAAM,YAAY,GAAG,MAAM,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAE/D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,wBAAwB;SAClC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,KAAK,MAAM,CAAC;IACpD,MAAM,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IAChF,MAAM,aAAa,GAAG,OAAO,CAC3B,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;QAC7E,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,CACxE,CAAC;IAEF,IAAI,CAAC,SAAS,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa,EAAE,CAAC;QACpD,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,0FAA0F;SACpG,CAAC,CAAC;IACL,CAAC;IAED,IAAI,iBAAiB,GAAuB,EAAE,CAAC;IAC/C,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,iBAAiB,GAAG,MAAM,uBAAuB,CAC/C,KAAK,CAAC,IAAI,CAAC,KAAK,EAChB,MAAM,EACN,SAAS,EACT,SAAS,EACT,SAAS,EACT,KAAK,CAAC,EAAE,CACT,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9E,MAAM,aAAa,GAAG,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1D,KAAK,CAAC,IAAI,CAAC,kBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9C,CAAC;QACF,MAAM,OAAO,CAAC,GAAG,CACf,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAC/B,IAAI,CAAC;gBACH,IAAI,IAAI,CAAC,YAAY,KAAK,WAAW,EAAE,CAAC;oBACtC,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC5B,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;wBACzB,MAAM,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,IAAI,GAAG,EAAE;oBACjD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK;iBACrF,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAA+C,EAAE,CAAC;IAClE,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO;QAAE,UAAU,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;IAEhE,IAAI,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxE,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;YAC/B,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;YACvB,IAAI,EAAE;gBACJ,WAAW,EAAE;oBACX,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;iBACtE;aACF;SACF,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9E,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;YAC/B,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;YACvB,IAAI,EAAE;gBACJ,WAAW,EAAE;oBACX,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE;iBAC1D;aACF;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,mBAAmB,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;QAC3D,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;QACvB,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE;YACN,EAAE,EAAE,IAAI;YACR,OAAO,EAAE;gBACP,MAAM,EAAE;oBACN,EAAE,EAAE,IAAI;oBACR,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE;wBACP,MAAM,EAAE;4BACN,WAAW,EAAE,IAAI;4BACjB,cAAc,EAAE,IAAI;4BACpB,uBAAuB,EAAE,IAAI;yBAC9B;qBACF;iBACF;aACF;YACD,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE;gBACX,MAAM,EAAE;oBACN,EAAE,EAAE,IAAI;oBACR,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,IAAI;oBACV,UAAU,EAAE,IAAI;oBAChB,WAAW,EAAE,IAAI;iBAClB;aACF;SACF;KACF,CAAC,CAAC;IAEH,OAAO;QACL,YAAY,EAAE,mBAAmB;QACjC,WAAW,EAAE,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;KAC1E,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,MAAc,EAAE,EAAU,EAAE,OAAe;IACxF,MAAM,YAAY,GAAG,MAAM,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAEzD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,wBAAwB;SAClC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,KAAK,MAAM,CAAC;IACpD,MAAM,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IAChF,MAAM,aAAa,GAAG,OAAO,CAC3B,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;QAC7E,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,CACxE,CAAC;IAEF,IAAI,CAAC,SAAS,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa,EAAE,CAAC;QACpD,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,0FAA0F;SACpG,CAAC,CAAC;IACL,CAAC;IAED,MAAM,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAC7B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC","debug_id":"88216f33-8458-56ce-84c5-509e783dc4e6"}
1
+ {"version":3,"file":"announcement.js","sources":["services/announcement.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Announcement service – create, read, update, delete announcements.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport {\n findAnnouncementsByClassId,\n findAnnouncementByIdAndClass,\n findAnnouncementWithClass,\n createAnnouncement,\n updateAnnouncement,\n updateAnnouncementAttachments,\n deleteAnnouncement,\n} from \"../models/announcement.js\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { createDirectUploadFiles, type DirectUploadFile } from \"../lib/fileUpload.js\";\nimport { deleteFile } from \"../lib/googleCloudStorage.js\";\nimport { sendToMultiple } from \"./notification.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { enqueueEmbedding } from \"./embedding.js\";\n\nexport async function getAllAnnouncements(classId: string) {\n const announcements = await findAnnouncementsByClassId(classId);\n const announcementsWithCounts = announcements.map((a) => ({\n ...a,\n commentCount: a._count.comments,\n _count: undefined,\n }));\n return { announcements: announcementsWithCounts };\n}\n\nexport async function getAnnouncement(id: string, classId: string) {\n const announcement = await findAnnouncementByIdAndClass(id, classId);\n if (!announcement) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Announcement not found\",\n });\n }\n return { announcement };\n}\n\nexport async function createAnnouncementRecord(\n userId: string,\n input: {\n classId: string;\n remarks: string;\n files?: { name: string; type: string; size: number }[];\n existingFileIds?: string[];\n }\n) {\n const { classId, remarks, files, existingFileIds } = input;\n\n const classData = await prisma.class.findUnique({\n where: { id: classId },\n include: { students: { select: { id: true } } },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found\",\n });\n }\n\n const announcement = await createAnnouncement({\n remarks,\n teacherId: userId,\n classId,\n });\n\n let directUploadFiles: DirectUploadFile[] = [];\n if (files && files.length > 0) {\n directUploadFiles = await createDirectUploadFiles(\n files,\n userId,\n undefined,\n undefined,\n undefined,\n announcement.id\n );\n }\n\n if (existingFileIds && existingFileIds.length > 0) {\n await updateAnnouncementAttachments(announcement.id, {\n connect: existingFileIds.map((fileId) => ({ id: fileId })),\n });\n }\n\n const announcementWithAttachments = await prisma.announcement.findUnique({\n where: { id: announcement.id },\n select: {\n id: true,\n teacher: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n remarks: true,\n createdAt: true,\n modifiedAt: true,\n attachments: {\n select: {\n id: true,\n name: true,\n type: true,\n size: true,\n path: true,\n uploadedAt: true,\n thumbnailId: true,\n },\n },\n },\n });\n\n sendToMultiple({\n receiverIds: classData.students.map((s) => s.id),\n title: `New announcement in ${classData.name}`,\n content: `${remarks}\\n\\n[View announcement](/class/${classId})`,\n }).catch((error) => {\n logger.error(\"Failed to send announcement notifications:\", error);\n });\n\n // Auto-index announcement for RAG search\n enqueueEmbedding(classId, 'ANNOUNCEMENT', announcement.id);\n\n return {\n announcement: announcementWithAttachments || announcement,\n uploadFiles: directUploadFiles.length > 0 ? directUploadFiles : undefined,\n };\n}\n\nexport async function updateAnnouncementRecord(\n userId: string,\n input: {\n id: string;\n classId: string;\n data: {\n remarks?: string;\n files?: { name: string; type: string; size: number }[];\n existingFileIds?: string[];\n removedAttachments?: string[];\n };\n }\n) {\n const announcement = await findAnnouncementWithClass(input.id);\n\n if (!announcement) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Announcement not found\",\n });\n }\n\n const isCreator = announcement.teacherId === userId;\n const isClassTeacher = announcement.class.teachers.some((t) => t.id === userId);\n const isSchoolAdmin = Boolean(\n announcement.class.school?.memberships.some((admin) => admin.userId === userId) ||\n announcement.class.school?.users.some((admin) => admin.id === userId)\n );\n\n if (!isCreator && !isClassTeacher && !isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the announcement creator, class teachers, or school admins can update announcements\",\n });\n }\n\n let directUploadFiles: DirectUploadFile[] = [];\n if (input.data.files && input.data.files.length > 0) {\n directUploadFiles = await createDirectUploadFiles(\n input.data.files,\n userId,\n undefined,\n undefined,\n undefined,\n input.id\n );\n }\n\n if (input.data.removedAttachments && input.data.removedAttachments.length > 0) {\n const filesToDelete = announcement.attachments.filter((f) =>\n input.data.removedAttachments!.includes(f.id)\n );\n await Promise.all(\n filesToDelete.map(async (file) => {\n try {\n if (file.uploadStatus === \"COMPLETED\") {\n await deleteFile(file.path);\n if (file.thumbnail?.path) {\n await deleteFile(file.thumbnail.path);\n }\n }\n } catch (error) {\n logger.warn(`Failed to delete file ${file.path}:`, {\n error: error instanceof Error ? { name: error.name, message: error.message } : error,\n });\n }\n })\n );\n }\n\n const updateData: { remarks?: string; attachments?: object } = {};\n if (input.data.remarks) updateData.remarks = input.data.remarks;\n\n if (input.data.existingFileIds && input.data.existingFileIds.length > 0) {\n await prisma.announcement.update({\n where: { id: input.id },\n data: {\n attachments: {\n connect: input.data.existingFileIds.map((fileId) => ({ id: fileId })),\n },\n },\n });\n }\n\n if (input.data.removedAttachments && input.data.removedAttachments.length > 0) {\n await prisma.announcement.update({\n where: { id: input.id },\n data: {\n attachments: {\n deleteMany: { id: { in: input.data.removedAttachments } },\n },\n },\n });\n }\n\n const updatedAnnouncement = await prisma.announcement.update({\n where: { id: input.id },\n data: updateData,\n select: {\n id: true,\n teacher: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n },\n },\n },\n },\n remarks: true,\n createdAt: true,\n modifiedAt: true,\n attachments: {\n select: {\n id: true,\n name: true,\n type: true,\n size: true,\n path: true,\n uploadedAt: true,\n thumbnailId: true,\n },\n },\n },\n });\n\n // Re-index announcement for RAG search after update\n enqueueEmbedding(input.classId, 'ANNOUNCEMENT', input.id);\n\n return {\n announcement: updatedAnnouncement,\n uploadFiles: directUploadFiles.length > 0 ? directUploadFiles : undefined,\n };\n}\n\nexport async function deleteAnnouncementRecord(userId: string, id: string, classId: string) {\n const announcement = await findAnnouncementWithClass(id);\n\n if (!announcement) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Announcement not found\",\n });\n }\n\n const isCreator = announcement.teacherId === userId;\n const isClassTeacher = announcement.class.teachers.some((t) => t.id === userId);\n const isSchoolAdmin = Boolean(\n announcement.class.school?.memberships.some((admin) => admin.userId === userId) ||\n announcement.class.school?.users.some((admin) => admin.id === userId)\n );\n\n if (!isCreator && !isClassTeacher && !isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the announcement creator, class teachers, or school admins can delete announcements\",\n });\n }\n\n await deleteAnnouncement(id);\n return { success: true };\n}\n"],"names":[],"mappings":"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","debug_id":"c5ff2131-07ed-588e-a43a-05af5641c732"}