@studious-lms/server 1.12.0 → 1.14.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 (338) 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/lib/config/cors.d.ts.map +1 -1
  8. package/dist/lib/config/cors.js +31 -11
  9. package/dist/lib/config/cors.js.map +1 -1
  10. package/dist/lib/config/env.d.ts +17 -0
  11. package/dist/lib/config/env.d.ts.map +1 -1
  12. package/dist/lib/config/env.js +8 -2
  13. package/dist/lib/config/env.js.map +1 -1
  14. package/dist/lib/googleCloudStorage.d.ts +10 -0
  15. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  16. package/dist/lib/googleCloudStorage.js +22 -2
  17. package/dist/lib/googleCloudStorage.js.map +1 -1
  18. package/dist/lib/prisma.d.ts +104 -5
  19. package/dist/lib/prisma.d.ts.map +1 -1
  20. package/dist/lib/prisma.js +33 -2
  21. package/dist/lib/prisma.js.map +1 -1
  22. package/dist/models/agenda.d.ts +20 -20
  23. package/dist/models/announcement.d.ts +177 -69
  24. package/dist/models/announcement.d.ts.map +1 -1
  25. package/dist/models/assignment.d.ts +551 -353
  26. package/dist/models/assignment.d.ts.map +1 -1
  27. package/dist/models/attendance.d.ts +197 -71
  28. package/dist/models/attendance.d.ts.map +1 -1
  29. package/dist/models/auth.d.ts +348 -114
  30. package/dist/models/auth.d.ts.map +1 -1
  31. package/dist/models/class.d.ts +324 -188
  32. package/dist/models/class.d.ts.map +1 -1
  33. package/dist/models/class.js +9 -3
  34. package/dist/models/class.js.map +1 -1
  35. package/dist/models/cloudStorage.d.ts +146 -56
  36. package/dist/models/cloudStorage.d.ts.map +1 -1
  37. package/dist/models/comment.d.ts +269 -110
  38. package/dist/models/comment.d.ts.map +1 -1
  39. package/dist/models/comment.js +3 -2
  40. package/dist/models/comment.js.map +1 -1
  41. package/dist/models/conversation.d.ts +206 -63
  42. package/dist/models/conversation.d.ts.map +1 -1
  43. package/dist/models/conversation.js +13 -2
  44. package/dist/models/conversation.js.map +1 -1
  45. package/dist/models/department.d.ts +196 -70
  46. package/dist/models/department.d.ts.map +1 -1
  47. package/dist/models/event.d.ts +287 -125
  48. package/dist/models/event.d.ts.map +1 -1
  49. package/dist/models/file.d.ts +389 -263
  50. package/dist/models/file.d.ts.map +1 -1
  51. package/dist/models/folder.d.ts +433 -181
  52. package/dist/models/folder.d.ts.map +1 -1
  53. package/dist/models/labChat.d.ts +209 -83
  54. package/dist/models/labChat.d.ts.map +1 -1
  55. package/dist/models/marketing.d.ts +80 -26
  56. package/dist/models/marketing.d.ts.map +1 -1
  57. package/dist/models/message.d.ts +95 -41
  58. package/dist/models/message.d.ts.map +1 -1
  59. package/dist/models/newtonChat.d.ts +83 -29
  60. package/dist/models/newtonChat.d.ts.map +1 -1
  61. package/dist/models/notification.d.ts +61 -25
  62. package/dist/models/notification.d.ts.map +1 -1
  63. package/dist/models/school.d.ts +349 -133
  64. package/dist/models/school.d.ts.map +1 -1
  65. package/dist/models/section.d.ts +216 -72
  66. package/dist/models/section.d.ts.map +1 -1
  67. package/dist/models/tag.d.ts +156 -48
  68. package/dist/models/tag.d.ts.map +1 -1
  69. package/dist/models/user.d.ts +82 -28
  70. package/dist/models/user.d.ts.map +1 -1
  71. package/dist/models/worksheet.d.ts +1023 -410
  72. package/dist/models/worksheet.d.ts.map +1 -1
  73. package/dist/models/worksheet.js +19 -7
  74. package/dist/models/worksheet.js.map +1 -1
  75. package/dist/pipelines/aiLabChat.d.ts +0 -8
  76. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  77. package/dist/pipelines/aiLabChat.js +50 -67
  78. package/dist/pipelines/aiLabChat.js.map +1 -1
  79. package/dist/pipelines/aiLabChatContract.d.ts +393 -388
  80. package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
  81. package/dist/pipelines/aiLabChatContract.js +63 -69
  82. package/dist/pipelines/aiLabChatContract.js.map +1 -1
  83. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
  84. package/dist/pipelines/aiNewtonChat.js +41 -41
  85. package/dist/pipelines/aiNewtonChat.js.map +1 -1
  86. package/dist/pipelines/gradeWorksheet.d.ts +8 -8
  87. package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
  88. package/dist/pipelines/gradeWorksheet.js +59 -14
  89. package/dist/pipelines/gradeWorksheet.js.map +1 -1
  90. package/dist/pipelines/labChatPrompt.d.ts +10 -8
  91. package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
  92. package/dist/pipelines/labChatPrompt.js +47 -67
  93. package/dist/pipelines/labChatPrompt.js.map +1 -1
  94. package/dist/pipelines/pdfToWorksheet.d.ts +2 -2
  95. package/dist/routers/_app.d.ts +2268 -1898
  96. package/dist/routers/_app.d.ts.map +1 -1
  97. package/dist/routers/_app.js +4 -2
  98. package/dist/routers/_app.js.map +1 -1
  99. package/dist/routers/admin.d.ts +13 -13
  100. package/dist/routers/agenda.d.ts +18 -18
  101. package/dist/routers/announcement.d.ts +32 -28
  102. package/dist/routers/announcement.d.ts.map +1 -1
  103. package/dist/routers/announcement.js +6 -5
  104. package/dist/routers/announcement.js.map +1 -1
  105. package/dist/routers/assignment.d.ts +335 -327
  106. package/dist/routers/assignment.d.ts.map +1 -1
  107. package/dist/routers/assignment.js +4 -4
  108. package/dist/routers/assignment.js.map +1 -1
  109. package/dist/routers/attendance.d.ts +10 -10
  110. package/dist/routers/auth.d.ts +2 -2
  111. package/dist/routers/class.d.ts +170 -147
  112. package/dist/routers/class.d.ts.map +1 -1
  113. package/dist/routers/comment.d.ts +40 -16
  114. package/dist/routers/comment.d.ts.map +1 -1
  115. package/dist/routers/comment.js +6 -3
  116. package/dist/routers/comment.js.map +1 -1
  117. package/dist/routers/conversation.d.ts +17 -17
  118. package/dist/routers/department.d.ts +34 -34
  119. package/dist/routers/discussion.d.ts +65 -53
  120. package/dist/routers/discussion.d.ts.map +1 -1
  121. package/dist/routers/discussion.js +6 -2
  122. package/dist/routers/discussion.js.map +1 -1
  123. package/dist/routers/embedding.d.ts +69 -0
  124. package/dist/routers/embedding.d.ts.map +1 -0
  125. package/dist/routers/embedding.js +143 -0
  126. package/dist/routers/embedding.js.map +1 -0
  127. package/dist/routers/event.d.ts +39 -39
  128. package/dist/routers/file.d.ts +12 -12
  129. package/dist/routers/folder.d.ts +38 -38
  130. package/dist/routers/labChat.d.ts +19 -19
  131. package/dist/routers/marketing.d.ts +2 -2
  132. package/dist/routers/message.d.ts +13 -13
  133. package/dist/routers/newtonChat.d.ts +4 -4
  134. package/dist/routers/notifications.d.ts +9 -9
  135. package/dist/routers/permissions.d.ts +14 -14
  136. package/dist/routers/school.d.ts +55 -55
  137. package/dist/routers/search.d.ts +22 -1
  138. package/dist/routers/search.d.ts.map +1 -1
  139. package/dist/routers/search.js +9 -3
  140. package/dist/routers/search.js.map +1 -1
  141. package/dist/routers/section.d.ts +4 -4
  142. package/dist/routers/studentProgress.d.ts +1 -1
  143. package/dist/routers/tag.d.ts +7 -7
  144. package/dist/routers/user.d.ts +10 -10
  145. package/dist/routers/worksheet.d.ts +97 -56
  146. package/dist/routers/worksheet.d.ts.map +1 -1
  147. package/dist/routers/worksheet.js +28 -2
  148. package/dist/routers/worksheet.js.map +1 -1
  149. package/dist/routes/aiStream.d.ts +2 -0
  150. package/dist/routes/aiStream.d.ts.map +1 -0
  151. package/dist/routes/aiStream.js +696 -0
  152. package/dist/routes/aiStream.js.map +1 -0
  153. package/dist/seedDatabase.d.ts +2 -2
  154. package/dist/seedDatabase.js +6 -6
  155. package/dist/seedDatabase.js.map +1 -1
  156. package/dist/services/adminInstitution.d.ts +8 -8
  157. package/dist/services/adminRunJob.d.ts +4 -4
  158. package/dist/services/agenda.d.ts +18 -18
  159. package/dist/services/aiChatStream.d.ts +68 -0
  160. package/dist/services/aiChatStream.d.ts.map +1 -0
  161. package/dist/services/aiChatStream.js +157 -0
  162. package/dist/services/aiChatStream.js.map +1 -0
  163. package/dist/services/aiModifierTools.d.ts +32 -0
  164. package/dist/services/aiModifierTools.d.ts.map +1 -0
  165. package/dist/services/aiModifierTools.js +165 -0
  166. package/dist/services/aiModifierTools.js.map +1 -0
  167. package/dist/services/aiProposalTools.d.ts +32 -0
  168. package/dist/services/aiProposalTools.d.ts.map +1 -0
  169. package/dist/services/aiProposalTools.js +207 -0
  170. package/dist/services/aiProposalTools.js.map +1 -0
  171. package/dist/services/aiStream.d.ts +22 -0
  172. package/dist/services/aiStream.d.ts.map +1 -0
  173. package/dist/services/aiStream.js +142 -0
  174. package/dist/services/aiStream.js.map +1 -0
  175. package/dist/services/aiTools.d.ts +16 -0
  176. package/dist/services/aiTools.d.ts.map +1 -0
  177. package/dist/services/aiTools.js +271 -0
  178. package/dist/services/aiTools.js.map +1 -0
  179. package/dist/services/announcement.d.ts +12 -12
  180. package/dist/services/announcement.d.ts.map +1 -1
  181. package/dist/services/announcement.js +7 -2
  182. package/dist/services/announcement.js.map +1 -1
  183. package/dist/services/assignment.d.ts +293 -293
  184. package/dist/services/assignment.d.ts.map +1 -1
  185. package/dist/services/assignment.js +36 -15
  186. package/dist/services/assignment.js.map +1 -1
  187. package/dist/services/attendance.d.ts +10 -10
  188. package/dist/services/auth.d.ts +2 -2
  189. package/dist/services/class.d.ts +161 -138
  190. package/dist/services/class.d.ts.map +1 -1
  191. package/dist/services/class.js +25 -4
  192. package/dist/services/class.js.map +1 -1
  193. package/dist/services/comment.d.ts +34 -16
  194. package/dist/services/comment.d.ts.map +1 -1
  195. package/dist/services/comment.js +23 -2
  196. package/dist/services/comment.js.map +1 -1
  197. package/dist/services/conversation.d.ts +17 -17
  198. package/dist/services/conversation.d.ts.map +1 -1
  199. package/dist/services/conversation.js +9 -7
  200. package/dist/services/conversation.js.map +1 -1
  201. package/dist/services/department.d.ts +33 -33
  202. package/dist/services/discussion.d.ts +58 -58
  203. package/dist/services/discussion.d.ts.map +1 -1
  204. package/dist/services/discussion.js +8 -8
  205. package/dist/services/discussion.js.map +1 -1
  206. package/dist/services/discussionSummary.d.ts +21 -0
  207. package/dist/services/discussionSummary.d.ts.map +1 -0
  208. package/dist/services/discussionSummary.js +179 -0
  209. package/dist/services/discussionSummary.js.map +1 -0
  210. package/dist/services/embedding.d.ts +67 -0
  211. package/dist/services/embedding.d.ts.map +1 -0
  212. package/dist/services/embedding.js +226 -0
  213. package/dist/services/embedding.js.map +1 -0
  214. package/dist/services/event.d.ts +37 -37
  215. package/dist/services/file.d.ts +24 -24
  216. package/dist/services/folder.d.ts +36 -36
  217. package/dist/services/labChat.d.ts +19 -19
  218. package/dist/services/marketing.d.ts +2 -2
  219. package/dist/services/message.d.ts +11 -11
  220. package/dist/services/message.d.ts.map +1 -1
  221. package/dist/services/message.js +2 -2
  222. package/dist/services/message.js.map +1 -1
  223. package/dist/services/newtonChat.d.ts +4 -4
  224. package/dist/services/notification.d.ts +9 -9
  225. package/dist/services/notification.d.ts.map +1 -1
  226. package/dist/services/permissions.d.ts +14 -14
  227. package/dist/services/school.d.ts +50 -50
  228. package/dist/services/search.d.ts +12 -0
  229. package/dist/services/search.d.ts.map +1 -1
  230. package/dist/services/search.js +120 -2
  231. package/dist/services/search.js.map +1 -1
  232. package/dist/services/section.d.ts +3 -3
  233. package/dist/services/tag.d.ts +4 -4
  234. package/dist/services/user.d.ts +4 -4
  235. package/dist/services/user.d.ts.map +1 -1
  236. package/dist/services/user.js +10 -15
  237. package/dist/services/user.js.map +1 -1
  238. package/dist/services/worksheet.d.ts +62 -47
  239. package/dist/services/worksheet.d.ts.map +1 -1
  240. package/dist/services/worksheet.js +11 -4
  241. package/dist/services/worksheet.js.map +1 -1
  242. package/dist/utils/streamBroadcast.d.ts +11 -0
  243. package/dist/utils/streamBroadcast.d.ts.map +1 -0
  244. package/dist/utils/streamBroadcast.js +32 -0
  245. package/dist/utils/streamBroadcast.js.map +1 -0
  246. package/dist/workers/connection.d.ts +15 -0
  247. package/dist/workers/connection.d.ts.map +1 -1
  248. package/dist/workers/connection.js +20 -2
  249. package/dist/workers/connection.js.map +1 -1
  250. package/dist/workers/index.js +4 -2
  251. package/dist/workers/index.js.map +1 -1
  252. package/dist/workers/processors/createRunJobWorker.d.ts.map +1 -1
  253. package/dist/workers/processors/createRunJobWorker.js +31 -8
  254. package/dist/workers/processors/createRunJobWorker.js.map +1 -1
  255. package/dist/workers/processors/embedContent.d.ts +8 -0
  256. package/dist/workers/processors/embedContent.d.ts.map +1 -0
  257. package/dist/workers/processors/embedContent.js +76 -0
  258. package/dist/workers/processors/embedContent.js.map +1 -0
  259. package/dist/workers/queues.d.ts +6 -0
  260. package/dist/workers/queues.d.ts.map +1 -1
  261. package/dist/workers/queues.js +5 -3
  262. package/dist/workers/queues.js.map +1 -1
  263. package/package.json +5 -1
  264. package/prisma/migrations/20260609215135_init/migration.sql +1412 -0
  265. package/prisma/migrations/20260610130000_add_worksheet_tags/migration.sql +13 -0
  266. package/prisma/schema.prisma +39 -7
  267. package/src/index.ts +4 -0
  268. package/src/lib/config/cors.ts +32 -9
  269. package/src/lib/config/env.ts +6 -0
  270. package/src/lib/googleCloudStorage.ts +21 -0
  271. package/src/lib/prisma.ts +40 -1
  272. package/src/models/class.ts +10 -3
  273. package/src/models/comment.ts +1 -0
  274. package/src/models/conversation.ts +12 -0
  275. package/src/models/worksheet.ts +16 -7
  276. package/src/pipelines/aiLabChat.ts +54 -79
  277. package/src/pipelines/aiLabChatContract.ts +69 -69
  278. package/src/pipelines/aiNewtonChat.ts +46 -43
  279. package/src/pipelines/gradeWorksheet.ts +66 -15
  280. package/src/pipelines/labChatPrompt.ts +63 -88
  281. package/src/routers/_app.ts +2 -0
  282. package/src/routers/announcement.ts +4 -3
  283. package/src/routers/assignment.ts +2 -2
  284. package/src/routers/comment.ts +5 -0
  285. package/src/routers/discussion.ts +7 -0
  286. package/src/routers/embedding.ts +159 -0
  287. package/src/routers/search.ts +10 -1
  288. package/src/routers/worksheet.ts +29 -0
  289. package/src/routes/aiStream.ts +789 -0
  290. package/src/seedDatabase.ts +4 -4
  291. package/src/services/aiChatStream.ts +219 -0
  292. package/src/services/aiModifierTools.ts +188 -0
  293. package/src/services/aiProposalTools.ts +272 -0
  294. package/src/services/aiStream.ts +175 -0
  295. package/src/services/aiTools.ts +290 -0
  296. package/src/services/announcement.ts +7 -0
  297. package/src/services/assignment.ts +36 -14
  298. package/src/services/class.ts +30 -2
  299. package/src/services/comment.ts +22 -0
  300. package/src/services/conversation.ts +9 -4
  301. package/src/services/discussion.ts +9 -8
  302. package/src/services/discussionSummary.ts +226 -0
  303. package/src/services/embedding.ts +285 -0
  304. package/src/services/message.ts +2 -2
  305. package/src/services/search.ts +138 -0
  306. package/src/services/user.ts +9 -17
  307. package/src/services/worksheet.ts +10 -2
  308. package/src/utils/streamBroadcast.ts +48 -0
  309. package/src/workers/connection.ts +19 -0
  310. package/src/workers/index.ts +2 -0
  311. package/src/workers/processors/createRunJobWorker.ts +32 -6
  312. package/src/workers/processors/embedContent.ts +90 -0
  313. package/src/workers/queues.ts +5 -1
  314. package/tests/integration/routers/conversation.test.ts +9 -7
  315. package/tests/unit/pipelines/aiLabChatContract.test.ts +38 -21
  316. package/tests/unit/pipelines/labChatPrompt.test.ts +23 -36
  317. package/prisma/migrations/20250807062924_init/migration.sql +0 -436
  318. package/prisma/migrations/20250919063704_init2/migration.sql +0 -24
  319. package/prisma/migrations/20250920143543_add_profile_fields/migration.sql +0 -15
  320. package/prisma/migrations/20250922165147_add_chat_models/migration.sql +0 -68
  321. package/prisma/migrations/20250922165314_add_chat_roles/migration.sql +0 -5
  322. package/prisma/migrations/20250922171242_refactor_notification_system/migration.sql +0 -20
  323. package/prisma/migrations/20250922172208_add_mentions_system/migration.sql +0 -21
  324. package/prisma/migrations/20250925072732_add_lab_chat_system/migration.sql +0 -25
  325. package/prisma/migrations/20251020151505_add_upload_tracking_fields/migration.sql +0 -57
  326. package/prisma/migrations/20251109122857_annuoncements_comments/migration.sql +0 -30
  327. package/prisma/migrations/20251109135555_reactions_announcements_comments/migration.sql +0 -35
  328. package/prisma/migrations/20260410124000_add_submission_recommendation_state/migration.sql +0 -14
  329. package/prisma/migrations/20260415103500_add_session_type/migration.sql +0 -33
  330. package/prisma/migrations/20260415133000_add_ai_usage_logs/migration.sql +0 -19
  331. package/prisma/migrations/20260417083000_add_conversation_member_hidden_at/migration.sql +0 -2
  332. package/prisma/migrations/20260502230500_assignment_submission_comments/migration.sql +0 -60
  333. package/prisma/migrations/20260504071500_school_memberships/migration.sql +0 -81
  334. package/prisma/migrations/20260506162500_consolidate_run_job_and_unify_job_status/migration.sql +0 -166
  335. package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +0 -184
  336. package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +0 -93
  337. package/prisma/migrations/20260510183000_add_discussions/migration.sql +0 -151
  338. /package/.github/workflows/{npm.yml → npm-publish.yml} +0 -0
@@ -14,15 +14,15 @@ export declare function listConversations(userId: string): Promise<{
14
14
  id: string;
15
15
  username: string;
16
16
  profile: {
17
- displayName: string | null;
18
17
  profilePicture: string | null;
18
+ displayName: string | null;
19
19
  } | null;
20
20
  };
21
21
  } & {
22
22
  id: string;
23
23
  userId: string;
24
- role: import(".prisma/client").$Enums.ConversationRole;
25
24
  conversationId: string;
25
+ role: import(".prisma/client").$Enums.ConversationRole;
26
26
  joinedAt: Date;
27
27
  hiddenAt: Date | null;
28
28
  lastViewedAt: Date | null;
@@ -41,10 +41,10 @@ export declare function listConversations(userId: string): Promise<{
41
41
  meta: import("@prisma/client/runtime/library.js").JsonValue | null;
42
42
  id: string;
43
43
  createdAt: Date;
44
- conversationId: string;
45
44
  content: string;
46
- senderId: string;
45
+ conversationId: string;
47
46
  runJobId: string | null;
47
+ senderId: string;
48
48
  };
49
49
  unreadCount: number;
50
50
  unreadMentionCount: number;
@@ -63,8 +63,8 @@ export declare function searchConversationMembers(userId: string, query: string)
63
63
  id: string;
64
64
  username: string;
65
65
  profile: {
66
- displayName: string | null;
67
66
  profilePicture: string | null;
67
+ displayName: string | null;
68
68
  profilePictureThumbnail: string | null;
69
69
  } | null;
70
70
  }[]>;
@@ -75,15 +75,15 @@ export declare function createConversationRecord(userId: string, type: "DM" | "G
75
75
  id: string;
76
76
  username: string;
77
77
  profile: {
78
- displayName: string | null;
79
78
  profilePicture: string | null;
79
+ displayName: string | null;
80
80
  } | null;
81
81
  };
82
82
  } & {
83
83
  id: string;
84
84
  userId: string;
85
- role: import(".prisma/client").$Enums.ConversationRole;
86
85
  conversationId: string;
86
+ role: import(".prisma/client").$Enums.ConversationRole;
87
87
  joinedAt: Date;
88
88
  hiddenAt: Date | null;
89
89
  lastViewedAt: Date | null;
@@ -91,10 +91,10 @@ export declare function createConversationRecord(userId: string, type: "DM" | "G
91
91
  })[];
92
92
  } & {
93
93
  type: import(".prisma/client").$Enums.ConversationType;
94
- name: string | null;
95
94
  id: string;
96
95
  createdAt: Date;
97
96
  updatedAt: Date;
97
+ name: string | null;
98
98
  displayInChat: boolean;
99
99
  }>;
100
100
  export declare function getConversation(userId: string, conversationId: string): Promise<{
@@ -103,15 +103,15 @@ export declare function getConversation(userId: string, conversationId: string):
103
103
  id: string;
104
104
  username: string;
105
105
  profile: {
106
- displayName: string | null;
107
106
  profilePicture: string | null;
107
+ displayName: string | null;
108
108
  } | null;
109
109
  };
110
110
  } & {
111
111
  id: string;
112
112
  userId: string;
113
- role: import(".prisma/client").$Enums.ConversationRole;
114
113
  conversationId: string;
114
+ role: import(".prisma/client").$Enums.ConversationRole;
115
115
  joinedAt: Date;
116
116
  hiddenAt: Date | null;
117
117
  lastViewedAt: Date | null;
@@ -119,10 +119,10 @@ export declare function getConversation(userId: string, conversationId: string):
119
119
  })[];
120
120
  } & {
121
121
  type: import(".prisma/client").$Enums.ConversationType;
122
- name: string | null;
123
122
  id: string;
124
123
  createdAt: Date;
125
124
  updatedAt: Date;
125
+ name: string | null;
126
126
  displayInChat: boolean;
127
127
  }>;
128
128
  export declare function addMemberToConversation(userId: string, conversationId: string, memberUsername: string): Promise<{
@@ -131,15 +131,15 @@ export declare function addMemberToConversation(userId: string, conversationId:
131
131
  id: string;
132
132
  username: string;
133
133
  profile: {
134
- displayName: string | null;
135
134
  profilePicture: string | null;
135
+ displayName: string | null;
136
136
  } | null;
137
137
  };
138
138
  } & {
139
139
  id: string;
140
140
  userId: string;
141
- role: import(".prisma/client").$Enums.ConversationRole;
142
141
  conversationId: string;
142
+ role: import(".prisma/client").$Enums.ConversationRole;
143
143
  joinedAt: Date;
144
144
  hiddenAt: Date | null;
145
145
  lastViewedAt: Date | null;
@@ -147,10 +147,10 @@ export declare function addMemberToConversation(userId: string, conversationId:
147
147
  })[];
148
148
  } & {
149
149
  type: import(".prisma/client").$Enums.ConversationType;
150
- name: string | null;
151
150
  id: string;
152
151
  createdAt: Date;
153
152
  updatedAt: Date;
153
+ name: string | null;
154
154
  displayInChat: boolean;
155
155
  }>;
156
156
  export declare function removeMemberFromConversation(userId: string, conversationId: string, memberId: string): Promise<{
@@ -159,15 +159,15 @@ export declare function removeMemberFromConversation(userId: string, conversatio
159
159
  id: string;
160
160
  username: string;
161
161
  profile: {
162
- displayName: string | null;
163
162
  profilePicture: string | null;
163
+ displayName: string | null;
164
164
  } | null;
165
165
  };
166
166
  } & {
167
167
  id: string;
168
168
  userId: string;
169
- role: import(".prisma/client").$Enums.ConversationRole;
170
169
  conversationId: string;
170
+ role: import(".prisma/client").$Enums.ConversationRole;
171
171
  joinedAt: Date;
172
172
  hiddenAt: Date | null;
173
173
  lastViewedAt: Date | null;
@@ -175,10 +175,10 @@ export declare function removeMemberFromConversation(userId: string, conversatio
175
175
  })[];
176
176
  } & {
177
177
  type: import(".prisma/client").$Enums.ConversationType;
178
- name: string | null;
179
178
  id: string;
180
179
  createdAt: Date;
181
180
  updatedAt: Date;
181
+ name: string | null;
182
182
  displayInChat: boolean;
183
183
  }>;
184
184
  //# sourceMappingURL=conversation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.d.ts","sourceRoot":"/","sources":["services/conversation.ts"],"names":[],"mappings":"AAyBA,gEAAgE;AAChE,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuDrD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;;GAY5E;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;KAe5E;AAED,gEAAgE;AAChE,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,GAAG,OAAO,EACpB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,SAAS,EAAE,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEpB;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;GAavB;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BvB;AAED,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;GAejB"}
1
+ {"version":3,"file":"conversation.d.ts","sourceRoot":"/","sources":["services/conversation.ts"],"names":[],"mappings":"AA0BA,gEAAgE;AAChE,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuDrD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;;GAY5E;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;KAe5E;AAED,gEAAgE;AAChE,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,GAAG,OAAO,EACpB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,SAAS,EAAE,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EpB;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;GAavB;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BvB;AAED,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;GAejB"}
@@ -3,9 +3,9 @@
3
3
  * Handles member management and unread counts.
4
4
  */
5
5
 
6
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1d941fa8-dec4-5d6a-b549-daaf5adac742")}catch(e){}}();
6
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="617ce2d0-0467-5943-8ea4-a774f070d13e")}catch(e){}}();
7
7
  import { TRPCError } from "@trpc/server";
8
- import { findConversationsByUserId, countUnreadMessages, countUnreadMentions, findUserByUsername, searchInstitutionConversationMembers, findDmConversationsByUserId, findUsersByIdsOrUsernames, createConversation, findConversationByIdAndMember, createConversationMember, hideConversationMember, deleteConversationMember, } from "../models/conversation.js";
8
+ import { findConversationsByUserId, countUnreadMessages, countUnreadMentions, findUserByUsername, searchInstitutionConversationMembers, findDmConversationsByUserId, findUsersByIdsOrUsernames, createConversation, findConversationByIdAndMember, createConversationMember, hideConversationMember, unhideConversationMember, deleteConversationMember, } from "../models/conversation.js";
9
9
  /** Maximum number of member suggestions returned for conversation search. */
10
10
  const MAX_MEMBER_SEARCH_RESULTS = 10;
11
11
  /** Minimum non-whitespace characters required before running member search. */
@@ -102,10 +102,12 @@ export async function createConversationRecord(userId, type, name, memberIds) {
102
102
  memberUserIds.includes(targetUser.id));
103
103
  });
104
104
  if (existingDM) {
105
- throw new TRPCError({
106
- code: "BAD_REQUEST",
107
- message: `A conversation with ${targetUser.username} already exists`,
108
- });
105
+ const userMembership = existingDM.members.find((m) => m.userId === userId);
106
+ if (userMembership) {
107
+ await unhideConversationMember(userId, existingDM.id);
108
+ }
109
+ const conversation = await findConversationByIdAndMember(existingDM.id, userId);
110
+ return conversation;
109
111
  }
110
112
  }
111
113
  const members = await findUsersByIdsOrUsernames(memberIds);
@@ -172,4 +174,4 @@ export async function removeMemberFromConversation(userId, conversationId, membe
172
174
  return conversation;
173
175
  }
174
176
  //# sourceMappingURL=conversation.js.map
175
- //# debugId=1d941fa8-dec4-5d6a-b549-daaf5adac742
177
+ //# debugId=617ce2d0-0467-5943-8ea4-a774f070d13e
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.js","sources":["services/conversation.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Conversation service – list, create, and manage DM/group conversations.\n * Handles member management and unread counts.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport {\n findConversationsByUserId,\n countUnreadMessages,\n countUnreadMentions,\n findUserByUsername,\n searchInstitutionConversationMembers,\n findDmConversationsByUserId,\n findUsersByIdsOrUsernames,\n createConversation,\n findConversationByIdAndMember,\n createConversationMember,\n hideConversationMember,\n deleteConversationMember,\n} from \"../models/conversation.js\";\n\n/** Maximum number of member suggestions returned for conversation search. */\nconst MAX_MEMBER_SEARCH_RESULTS = 10;\n/** Minimum non-whitespace characters required before running member search. */\nconst MIN_MEMBER_SEARCH_QUERY_LENGTH = 2;\n\n/** List user's conversations with unread and mention counts. */\nexport async function listConversations(userId: string) {\n const conversations = await findConversationsByUserId(userId);\n const visibleConversations = conversations.filter((conversation) => {\n const userMembership = conversation.members.find((member) => member.userId === userId);\n\n if (!userMembership?.hiddenAt) {\n return true;\n }\n\n return conversation.updatedAt > userMembership.hiddenAt;\n });\n\n const conversationsWithUnread = await Promise.all(\n visibleConversations.map(async (conversation) => {\n const userMembership = conversation.members.find(\n (m) => m.userId === userId\n );\n const lastViewedAt = userMembership?.lastViewedAt;\n const lastViewedMentionAt = userMembership?.lastViewedMentionAt;\n\n const unreadCount = await countUnreadMessages(\n conversation.id,\n userId,\n lastViewedAt ?? undefined\n );\n\n const mentionCutoffTime =\n lastViewedMentionAt && lastViewedAt\n ? lastViewedMentionAt > lastViewedAt\n ? lastViewedMentionAt\n : lastViewedAt\n : lastViewedMentionAt || lastViewedAt;\n\n const unreadMentionCount = await countUnreadMentions(\n conversation.id,\n userId,\n mentionCutoffTime ?? undefined\n );\n\n return {\n id: conversation.id,\n type: conversation.type,\n name: conversation.name,\n createdAt: conversation.createdAt,\n updatedAt: conversation.updatedAt,\n labChat: conversation.labChat,\n members: conversation.members,\n lastMessage: conversation.messages[0] || null,\n unreadCount,\n unreadMentionCount,\n };\n })\n );\n\n return conversationsWithUnread;\n}\n\nexport async function hideConversation(userId: string, conversationId: string) {\n const conversation = await findConversationByIdAndMember(conversationId, userId);\n if (!conversation) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Not a member of this conversation\",\n });\n }\n\n await hideConversationMember(userId, conversationId);\n\n return { success: true };\n}\n\n/**\n * Search active school peers that can be selected for a new conversation.\n *\n * Blank or one-character input returns an empty list instead of searching all\n * institution members, which keeps typeahead callers from issuing broad result\n * queries.\n */\nexport async function searchConversationMembers(userId: string, query: string) {\n const trimmedQuery = query.trim();\n\n if (\n !trimmedQuery ||\n trimmedQuery.length < MIN_MEMBER_SEARCH_QUERY_LENGTH\n ) {\n return [];\n }\n\n return searchInstitutionConversationMembers(\n userId,\n trimmedQuery,\n MAX_MEMBER_SEARCH_RESULTS\n );\n}\n\n/** Create a DM or group conversation with the given members. */\nexport async function createConversationRecord(\n userId: string,\n type: \"DM\" | \"GROUP\",\n name: string | undefined,\n memberIds: string[]\n) {\n if (type === \"GROUP\" && !name) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Group conversations must have a name\",\n });\n }\n\n if (type === \"DM\" && memberIds.length !== 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"DM conversations must have exactly one other member\",\n });\n }\n\n if (type === \"DM\") {\n const [targetUser] = await findUsersByIdsOrUsernames([memberIds[0]]);\n if (!targetUser) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: `User not found`,\n });\n }\n\n const existingDMs = await findDmConversationsByUserId(userId);\n const existingDM = existingDMs.find((conv) => {\n const memberUserIds = conv.members.map((m) => m.userId);\n return (\n memberUserIds.length === 2 &&\n memberUserIds.includes(userId) &&\n memberUserIds.includes(targetUser.id)\n );\n });\n\n if (existingDM) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: `A conversation with ${targetUser.username} already exists`,\n });\n }\n }\n\n const members = await findUsersByIdsOrUsernames(memberIds);\n type Member = (typeof members)[number];\n const uniqueMembers = Array.from(\n new Map(members.map((m) => [m.id, m] as [string, Member])).values()\n );\n\n if (uniqueMembers.length !== memberIds.length) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"One or more members not found\",\n });\n }\n\n const toAddIds = memberIds\n .map((id) =>\n uniqueMembers.find((m) => m.id === id || m.username === id)?.id\n )\n .filter(Boolean) as string[];\n\n return createConversation({\n type,\n name,\n members: [\n { userId, role: type === \"GROUP\" ? \"ADMIN\" : \"MEMBER\" },\n ...toAddIds.map((uid) => ({ userId: uid, role: \"MEMBER\" })),\n ],\n });\n}\n\nexport async function getConversation(\n userId: string,\n conversationId: string\n) {\n const conversation = await findConversationByIdAndMember(\n conversationId,\n userId\n );\n if (!conversation) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Conversation not found or access denied\",\n });\n }\n return conversation;\n}\n\nexport async function addMemberToConversation(\n userId: string,\n conversationId: string,\n memberUsername: string\n) {\n const conversation = await findConversationByIdAndMember(\n conversationId,\n userId\n );\n if (!conversation) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Conversation not found or access denied\",\n });\n }\n\n const member = await findUserByUsername(memberUsername);\n if (!member) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Member not found\",\n });\n }\n\n await createConversationMember({\n userId: member.id,\n conversationId,\n role: \"MEMBER\",\n });\n\n return conversation;\n}\n\nexport async function removeMemberFromConversation(\n userId: string,\n conversationId: string,\n memberId: string\n) {\n const conversation = await findConversationByIdAndMember(\n conversationId,\n userId\n );\n if (!conversation) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Conversation not found or access denied\",\n });\n }\n\n await deleteConversationMember(memberId, conversationId);\n return conversation;\n}\n"],"names":[],"mappings":"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","debug_id":"1d941fa8-dec4-5d6a-b549-daaf5adac742"}
1
+ {"version":3,"file":"conversation.js","sources":["services/conversation.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Conversation service – list, create, and manage DM/group conversations.\n * Handles member management and unread counts.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport {\n findConversationsByUserId,\n countUnreadMessages,\n countUnreadMentions,\n findUserByUsername,\n searchInstitutionConversationMembers,\n findDmConversationsByUserId,\n findUsersByIdsOrUsernames,\n createConversation,\n findConversationByIdAndMember,\n createConversationMember,\n hideConversationMember,\n unhideConversationMember,\n deleteConversationMember,\n} from \"../models/conversation.js\";\n\n/** Maximum number of member suggestions returned for conversation search. */\nconst MAX_MEMBER_SEARCH_RESULTS = 10;\n/** Minimum non-whitespace characters required before running member search. */\nconst MIN_MEMBER_SEARCH_QUERY_LENGTH = 2;\n\n/** List user's conversations with unread and mention counts. */\nexport async function listConversations(userId: string) {\n const conversations = await findConversationsByUserId(userId);\n const visibleConversations = conversations.filter((conversation) => {\n const userMembership = conversation.members.find((member) => member.userId === userId);\n\n if (!userMembership?.hiddenAt) {\n return true;\n }\n\n return conversation.updatedAt > userMembership.hiddenAt;\n });\n\n const conversationsWithUnread = await Promise.all(\n visibleConversations.map(async (conversation) => {\n const userMembership = conversation.members.find(\n (m) => m.userId === userId\n );\n const lastViewedAt = userMembership?.lastViewedAt;\n const lastViewedMentionAt = userMembership?.lastViewedMentionAt;\n\n const unreadCount = await countUnreadMessages(\n conversation.id,\n userId,\n lastViewedAt ?? undefined\n );\n\n const mentionCutoffTime =\n lastViewedMentionAt && lastViewedAt\n ? lastViewedMentionAt > lastViewedAt\n ? lastViewedMentionAt\n : lastViewedAt\n : lastViewedMentionAt || lastViewedAt;\n\n const unreadMentionCount = await countUnreadMentions(\n conversation.id,\n userId,\n mentionCutoffTime ?? undefined\n );\n\n return {\n id: conversation.id,\n type: conversation.type,\n name: conversation.name,\n createdAt: conversation.createdAt,\n updatedAt: conversation.updatedAt,\n labChat: conversation.labChat,\n members: conversation.members,\n lastMessage: conversation.messages[0] || null,\n unreadCount,\n unreadMentionCount,\n };\n })\n );\n\n return conversationsWithUnread;\n}\n\nexport async function hideConversation(userId: string, conversationId: string) {\n const conversation = await findConversationByIdAndMember(conversationId, userId);\n if (!conversation) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Not a member of this conversation\",\n });\n }\n\n await hideConversationMember(userId, conversationId);\n\n return { success: true };\n}\n\n/**\n * Search active school peers that can be selected for a new conversation.\n *\n * Blank or one-character input returns an empty list instead of searching all\n * institution members, which keeps typeahead callers from issuing broad result\n * queries.\n */\nexport async function searchConversationMembers(userId: string, query: string) {\n const trimmedQuery = query.trim();\n\n if (\n !trimmedQuery ||\n trimmedQuery.length < MIN_MEMBER_SEARCH_QUERY_LENGTH\n ) {\n return [];\n }\n\n return searchInstitutionConversationMembers(\n userId,\n trimmedQuery,\n MAX_MEMBER_SEARCH_RESULTS\n );\n}\n\n/** Create a DM or group conversation with the given members. */\nexport async function createConversationRecord(\n userId: string,\n type: \"DM\" | \"GROUP\",\n name: string | undefined,\n memberIds: string[]\n) {\n if (type === \"GROUP\" && !name) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Group conversations must have a name\",\n });\n }\n\n if (type === \"DM\" && memberIds.length !== 1) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"DM conversations must have exactly one other member\",\n });\n }\n\n if (type === \"DM\") {\n const [targetUser] = await findUsersByIdsOrUsernames([memberIds[0]]);\n if (!targetUser) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: `User not found`,\n });\n }\n\n const existingDMs = await findDmConversationsByUserId(userId);\n const existingDM = existingDMs.find((conv) => {\n const memberUserIds = conv.members.map((m) => m.userId);\n return (\n memberUserIds.length === 2 &&\n memberUserIds.includes(userId) &&\n memberUserIds.includes(targetUser.id)\n );\n });\n\n if (existingDM) {\n const userMembership = existingDM.members.find(\n (m) => m.userId === userId\n );\n if (userMembership) {\n await unhideConversationMember(userId, existingDM.id);\n }\n const conversation = await findConversationByIdAndMember(existingDM.id, userId);\n return conversation!;\n }\n }\n\n const members = await findUsersByIdsOrUsernames(memberIds);\n type Member = (typeof members)[number];\n const uniqueMembers = Array.from(\n new Map(members.map((m) => [m.id, m] as [string, Member])).values()\n );\n\n if (uniqueMembers.length !== memberIds.length) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"One or more members not found\",\n });\n }\n\n const toAddIds = memberIds\n .map((id) =>\n uniqueMembers.find((m) => m.id === id || m.username === id)?.id\n )\n .filter(Boolean) as string[];\n\n return createConversation({\n type,\n name,\n members: [\n { userId, role: type === \"GROUP\" ? \"ADMIN\" : \"MEMBER\" },\n ...toAddIds.map((uid) => ({ userId: uid, role: \"MEMBER\" })),\n ],\n });\n}\n\nexport async function getConversation(\n userId: string,\n conversationId: string\n) {\n const conversation = await findConversationByIdAndMember(\n conversationId,\n userId\n );\n if (!conversation) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Conversation not found or access denied\",\n });\n }\n return conversation;\n}\n\nexport async function addMemberToConversation(\n userId: string,\n conversationId: string,\n memberUsername: string\n) {\n const conversation = await findConversationByIdAndMember(\n conversationId,\n userId\n );\n if (!conversation) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Conversation not found or access denied\",\n });\n }\n\n const member = await findUserByUsername(memberUsername);\n if (!member) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Member not found\",\n });\n }\n\n await createConversationMember({\n userId: member.id,\n conversationId,\n role: \"MEMBER\",\n });\n\n return conversation;\n}\n\nexport async function removeMemberFromConversation(\n userId: string,\n conversationId: string,\n memberId: string\n) {\n const conversation = await findConversationByIdAndMember(\n conversationId,\n userId\n );\n if (!conversation) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Conversation not found or access denied\",\n });\n }\n\n await deleteConversationMember(memberId, conversationId);\n return conversation;\n}\n"],"names":[],"mappings":"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","debug_id":"617ce2d0-0467-5943-8ea4-a774f070d13e"}
@@ -1,11 +1,9 @@
1
1
  export declare function listDepartments(userId: string, schoolId: string): Promise<{
2
- name: string;
3
2
  id: string;
4
- description: string | null;
5
3
  createdAt: Date;
6
4
  updatedAt: Date;
5
+ name: string;
7
6
  schoolId: string;
8
- color: string | null;
9
7
  _count: {
10
8
  tags: number;
11
9
  classes: number;
@@ -13,54 +11,56 @@ export declare function listDepartments(userId: string, schoolId: string): Promi
13
11
  rubricTemplates: number;
14
12
  boundaryTemplates: number;
15
13
  };
14
+ description: string | null;
15
+ color: string | null;
16
16
  }[]>;
17
17
  export declare function listMyDepartments(userId: string, schoolId: string): Promise<{
18
- name: string;
19
18
  id: string;
20
- description: string | null;
21
19
  createdAt: Date;
22
20
  updatedAt: Date;
21
+ name: string;
23
22
  schoolId: string;
23
+ description: string | null;
24
24
  color: string | null;
25
25
  }[]>;
26
26
  export declare function getDepartmentDetails(userId: string, departmentId: string): Promise<{
27
- name: string;
28
27
  id: string;
29
- description: string | null;
30
28
  createdAt: Date;
31
29
  updatedAt: Date;
30
+ name: string;
32
31
  schoolId: string;
33
- color: string | null;
34
32
  tags: {
35
- name: string;
36
33
  id: string;
34
+ name: string;
37
35
  color: string;
38
36
  }[];
37
+ description: string | null;
39
38
  classes: {
40
- name: string;
39
+ section: string;
41
40
  id: string;
42
- subject: string;
41
+ name: string;
43
42
  color: string | null;
44
- section: string;
43
+ subject: string;
45
44
  }[];
45
+ color: string | null;
46
46
  members: {
47
47
  id: string;
48
48
  username: string;
49
49
  email: string;
50
50
  profile: {
51
- displayName: string | null;
52
51
  profilePicture: string | null;
52
+ displayName: string | null;
53
53
  profilePictureThumbnail: string | null;
54
54
  } | null;
55
55
  }[];
56
56
  rubricTemplates: {
57
- name: string | null;
58
57
  id: string;
58
+ name: string | null;
59
59
  structured: string;
60
60
  }[];
61
61
  boundaryTemplates: {
62
- name: string | null;
63
62
  id: string;
63
+ name: string | null;
64
64
  structured: string;
65
65
  }[];
66
66
  }>;
@@ -70,12 +70,12 @@ export declare function createDepartmentRecord(userId: string, input: {
70
70
  description?: string;
71
71
  color?: string;
72
72
  }): Promise<{
73
- name: string;
74
73
  id: string;
75
- description: string | null;
76
74
  createdAt: Date;
77
75
  updatedAt: Date;
76
+ name: string;
78
77
  schoolId: string;
78
+ description: string | null;
79
79
  color: string | null;
80
80
  }>;
81
81
  export declare function updateDepartmentRecord(userId: string, input: {
@@ -84,12 +84,12 @@ export declare function updateDepartmentRecord(userId: string, input: {
84
84
  description?: string | null;
85
85
  color?: string;
86
86
  }): Promise<{
87
- name: string;
88
87
  id: string;
89
- description: string | null;
90
88
  createdAt: Date;
91
89
  updatedAt: Date;
90
+ name: string;
92
91
  schoolId: string;
92
+ description: string | null;
93
93
  color: string | null;
94
94
  }>;
95
95
  export declare function deleteDepartmentRecord(userId: string, departmentId: string): Promise<{
@@ -113,8 +113,8 @@ export declare function createRubricTemplate(userId: string, input: {
113
113
  name: string;
114
114
  structured: string;
115
115
  }): Promise<{
116
- name: string | null;
117
116
  id: string;
117
+ name: string | null;
118
118
  departmentId: string | null;
119
119
  structured: string;
120
120
  }>;
@@ -123,17 +123,17 @@ export declare function updateRubricTemplate(userId: string, input: {
123
123
  name?: string;
124
124
  structured?: string;
125
125
  }): Promise<{
126
- name: string | null;
127
126
  id: string;
128
- departmentId: string | null;
127
+ name: string | null;
129
128
  classId: string | null;
129
+ departmentId: string | null;
130
130
  structured: string;
131
131
  }>;
132
132
  export declare function deleteRubricTemplate(userId: string, templateId: string): Promise<{
133
- name: string | null;
134
133
  id: string;
135
- departmentId: string | null;
134
+ name: string | null;
136
135
  classId: string | null;
136
+ departmentId: string | null;
137
137
  structured: string;
138
138
  }>;
139
139
  export declare function createBoundaryTemplate(userId: string, input: {
@@ -141,8 +141,8 @@ export declare function createBoundaryTemplate(userId: string, input: {
141
141
  name: string;
142
142
  structured: string;
143
143
  }): Promise<{
144
- name: string | null;
145
144
  id: string;
145
+ name: string | null;
146
146
  departmentId: string | null;
147
147
  structured: string;
148
148
  }>;
@@ -151,17 +151,17 @@ export declare function updateBoundaryTemplate(userId: string, input: {
151
151
  name?: string;
152
152
  structured?: string;
153
153
  }): Promise<{
154
- name: string | null;
155
154
  id: string;
156
- departmentId: string | null;
155
+ name: string | null;
157
156
  classId: string | null;
157
+ departmentId: string | null;
158
158
  structured: string;
159
159
  }>;
160
160
  export declare function deleteBoundaryTemplate(userId: string, templateId: string): Promise<{
161
- name: string | null;
162
161
  id: string;
163
- departmentId: string | null;
162
+ name: string | null;
164
163
  classId: string | null;
164
+ departmentId: string | null;
165
165
  structured: string;
166
166
  }>;
167
167
  /**
@@ -172,20 +172,20 @@ export declare function applyRubricTemplate(userId: string, input: {
172
172
  classId: string;
173
173
  templateId: string;
174
174
  }): Promise<{
175
- name: string | null;
176
175
  id: string;
177
- departmentId: string | null;
176
+ name: string | null;
178
177
  classId: string | null;
178
+ departmentId: string | null;
179
179
  structured: string;
180
180
  }>;
181
181
  export declare function applyBoundaryTemplate(userId: string, input: {
182
182
  classId: string;
183
183
  templateId: string;
184
184
  }): Promise<{
185
- name: string | null;
186
185
  id: string;
187
- departmentId: string | null;
186
+ name: string | null;
188
187
  classId: string | null;
188
+ departmentId: string | null;
189
189
  structured: string;
190
190
  }>;
191
191
  /** Helper used by the auto-tag flow on class creation. */