@studious-lms/server 1.2.45 → 1.2.47

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 (241) hide show
  1. package/.env.example +45 -0
  2. package/.env.test.example +37 -0
  3. package/README.md +34 -7
  4. package/coverage/base.css +224 -0
  5. package/coverage/block-navigation.js +87 -0
  6. package/coverage/clover.xml +12110 -0
  7. package/coverage/coverage-final.json +44 -0
  8. package/coverage/favicon.png +0 -0
  9. package/coverage/index.html +221 -0
  10. package/coverage/prettify.css +1 -0
  11. package/coverage/prettify.js +2 -0
  12. package/coverage/server/index.html +116 -0
  13. package/coverage/server/src/exportType.ts.html +109 -0
  14. package/coverage/server/src/index.html +161 -0
  15. package/coverage/server/src/index.ts.html +1702 -0
  16. package/coverage/server/src/instrument.ts.html +130 -0
  17. package/coverage/server/src/lib/config/env.ts.html +448 -0
  18. package/coverage/server/src/lib/config/index.html +116 -0
  19. package/coverage/server/src/lib/fileUpload.ts.html +1138 -0
  20. package/coverage/server/src/lib/googleCloudStorage.ts.html +334 -0
  21. package/coverage/server/src/lib/index.html +206 -0
  22. package/coverage/server/src/lib/jsonConversion.ts.html +2323 -0
  23. package/coverage/server/src/lib/jsonStyles.ts.html +193 -0
  24. package/coverage/server/src/lib/notificationHandler.ts.html +193 -0
  25. package/coverage/server/src/lib/pusher.ts.html +121 -0
  26. package/coverage/server/src/lib/thumbnailGenerator.ts.html +592 -0
  27. package/coverage/server/src/middleware/auth.ts.html +646 -0
  28. package/coverage/server/src/middleware/index.html +146 -0
  29. package/coverage/server/src/middleware/logging.ts.html +244 -0
  30. package/coverage/server/src/middleware/security.ts.html +271 -0
  31. package/coverage/server/src/routers/_app.ts.html +232 -0
  32. package/coverage/server/src/routers/agenda.ts.html +319 -0
  33. package/coverage/server/src/routers/announcement.ts.html +3481 -0
  34. package/coverage/server/src/routers/assignment.ts.html +7633 -0
  35. package/coverage/server/src/routers/attendance.ts.html +1030 -0
  36. package/coverage/server/src/routers/auth.ts.html +1081 -0
  37. package/coverage/server/src/routers/class.ts.html +3535 -0
  38. package/coverage/server/src/routers/comment.ts.html +991 -0
  39. package/coverage/server/src/routers/conversation.ts.html +982 -0
  40. package/coverage/server/src/routers/event.ts.html +1609 -0
  41. package/coverage/server/src/routers/file.ts.html +1144 -0
  42. package/coverage/server/src/routers/folder.ts.html +2797 -0
  43. package/coverage/server/src/routers/index.html +386 -0
  44. package/coverage/server/src/routers/labChat.ts.html +3073 -0
  45. package/coverage/server/src/routers/marketing.ts.html +340 -0
  46. package/coverage/server/src/routers/message.ts.html +1912 -0
  47. package/coverage/server/src/routers/notifications.ts.html +364 -0
  48. package/coverage/server/src/routers/section.ts.html +1120 -0
  49. package/coverage/server/src/routers/user.ts.html +862 -0
  50. package/coverage/server/src/routers/worksheet.ts.html +1729 -0
  51. package/coverage/server/src/trpc.ts.html +397 -0
  52. package/coverage/server/src/types/index.html +116 -0
  53. package/coverage/server/src/types/trpc.ts.html +127 -0
  54. package/coverage/server/src/utils/aiUser.ts.html +280 -0
  55. package/coverage/server/src/utils/email.ts.html +121 -0
  56. package/coverage/server/src/utils/generateInviteCode.ts.html +106 -0
  57. package/coverage/server/src/utils/index.html +206 -0
  58. package/coverage/server/src/utils/inference.ts.html +709 -0
  59. package/coverage/server/src/utils/logger.ts.html +664 -0
  60. package/coverage/server/src/utils/prismaErrorHandler.ts.html +907 -0
  61. package/coverage/server/src/utils/prismaWrapper.ts.html +355 -0
  62. package/coverage/server/vitest.config.ts.html +196 -0
  63. package/coverage/sort-arrow-sprite.png +0 -0
  64. package/coverage/sorter.js +210 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +83 -52
  67. package/dist/index.js.map +1 -1
  68. package/dist/instrument.js +15 -8
  69. package/dist/instrument.js.map +1 -1
  70. package/dist/lib/config/env.d.ts +169 -0
  71. package/dist/lib/config/env.d.ts.map +1 -0
  72. package/dist/lib/config/env.js +115 -0
  73. package/dist/lib/config/env.js.map +1 -0
  74. package/dist/lib/fileUpload.d.ts.map +1 -1
  75. package/dist/lib/fileUpload.js +5 -4
  76. package/dist/lib/fileUpload.js.map +1 -1
  77. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  78. package/dist/lib/googleCloudStorage.js +7 -8
  79. package/dist/lib/googleCloudStorage.js.map +1 -1
  80. package/dist/lib/jsonConversion.d.ts.map +1 -1
  81. package/dist/lib/jsonConversion.js +14 -16
  82. package/dist/lib/jsonConversion.js.map +1 -1
  83. package/dist/lib/notificationHandler.d.ts +2 -2
  84. package/dist/lib/prisma.d.ts +2 -2
  85. package/dist/lib/prisma.d.ts.map +1 -1
  86. package/dist/lib/prisma.js +22 -3
  87. package/dist/lib/prisma.js.map +1 -1
  88. package/dist/lib/pusher.d.ts.map +1 -1
  89. package/dist/lib/pusher.js +8 -7
  90. package/dist/lib/pusher.js.map +1 -1
  91. package/dist/middleware/auth.d.ts.map +1 -1
  92. package/dist/middleware/auth.js +7 -5
  93. package/dist/middleware/auth.js.map +1 -1
  94. package/dist/middleware/security.d.ts +5 -0
  95. package/dist/middleware/security.d.ts.map +1 -0
  96. package/dist/middleware/security.js +77 -0
  97. package/dist/middleware/security.js.map +1 -0
  98. package/dist/routers/_app.d.ts +368 -108
  99. package/dist/routers/_app.d.ts.map +1 -1
  100. package/dist/routers/_app.js +4 -2
  101. package/dist/routers/_app.js.map +1 -1
  102. package/dist/routers/agenda.d.ts.map +1 -1
  103. package/dist/routers/agenda.js +12 -9
  104. package/dist/routers/agenda.js.map +1 -1
  105. package/dist/routers/announcement.d.ts +8 -0
  106. package/dist/routers/announcement.d.ts.map +1 -1
  107. package/dist/routers/announcement.js +6 -4
  108. package/dist/routers/announcement.js.map +1 -1
  109. package/dist/routers/assignment.d.ts +17 -4
  110. package/dist/routers/assignment.d.ts.map +1 -1
  111. package/dist/routers/assignment.js +51 -19
  112. package/dist/routers/assignment.js.map +1 -1
  113. package/dist/routers/attendance.d.ts +1 -0
  114. package/dist/routers/attendance.d.ts.map +1 -1
  115. package/dist/routers/attendance.js +4 -4
  116. package/dist/routers/attendance.js.map +1 -1
  117. package/dist/routers/auth.d.ts +20 -0
  118. package/dist/routers/auth.d.ts.map +1 -1
  119. package/dist/routers/auth.js +132 -15
  120. package/dist/routers/auth.js.map +1 -1
  121. package/dist/routers/class.d.ts +10 -0
  122. package/dist/routers/class.d.ts.map +1 -1
  123. package/dist/routers/class.js +49 -5
  124. package/dist/routers/class.js.map +1 -1
  125. package/dist/routers/comment.d.ts +2 -0
  126. package/dist/routers/comment.d.ts.map +1 -1
  127. package/dist/routers/conversation.d.ts +2 -0
  128. package/dist/routers/conversation.d.ts.map +1 -1
  129. package/dist/routers/conversation.js +46 -31
  130. package/dist/routers/conversation.js.map +1 -1
  131. package/dist/routers/file.d.ts.map +1 -1
  132. package/dist/routers/file.js +30 -7
  133. package/dist/routers/file.js.map +1 -1
  134. package/dist/routers/labChat.d.ts +2 -0
  135. package/dist/routers/labChat.d.ts.map +1 -1
  136. package/dist/routers/labChat.js +5 -322
  137. package/dist/routers/labChat.js.map +1 -1
  138. package/dist/routers/marketing.d.ts +1 -1
  139. package/dist/routers/message.d.ts +1 -0
  140. package/dist/routers/message.d.ts.map +1 -1
  141. package/dist/routers/message.js +3 -2
  142. package/dist/routers/message.js.map +1 -1
  143. package/dist/routers/newtonChat.d.ts +55 -0
  144. package/dist/routers/newtonChat.d.ts.map +1 -0
  145. package/dist/routers/newtonChat.js +262 -0
  146. package/dist/routers/newtonChat.js.map +1 -0
  147. package/dist/routers/notifications.d.ts +4 -4
  148. package/dist/routers/section.d.ts +19 -4
  149. package/dist/routers/section.d.ts.map +1 -1
  150. package/dist/routers/section.js +26 -8
  151. package/dist/routers/section.js.map +1 -1
  152. package/dist/routers/user.d.ts.map +1 -1
  153. package/dist/routers/user.js +5 -4
  154. package/dist/routers/user.js.map +1 -1
  155. package/dist/routers/worksheet.d.ts +44 -41
  156. package/dist/routers/worksheet.d.ts.map +1 -1
  157. package/dist/routers/worksheet.js +25 -34
  158. package/dist/routers/worksheet.js.map +1 -1
  159. package/dist/seedDatabase.d.ts +1 -1
  160. package/dist/seedDatabase.js +275 -284
  161. package/dist/seedDatabase.js.map +1 -1
  162. package/dist/server/pipelines/aiLabChat.d.ts +21 -0
  163. package/dist/server/pipelines/aiLabChat.d.ts.map +1 -0
  164. package/dist/server/pipelines/aiLabChat.js +456 -0
  165. package/dist/server/pipelines/aiLabChat.js.map +1 -0
  166. package/dist/server/pipelines/aiNewtonChat.d.ts +30 -0
  167. package/dist/server/pipelines/aiNewtonChat.d.ts.map +1 -0
  168. package/dist/server/pipelines/aiNewtonChat.js +280 -0
  169. package/dist/server/pipelines/aiNewtonChat.js.map +1 -0
  170. package/dist/server/pipelines/gradeWorksheet.d.ts +15 -0
  171. package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -0
  172. package/dist/server/pipelines/gradeWorksheet.js +139 -0
  173. package/dist/server/pipelines/gradeWorksheet.js.map +1 -0
  174. package/dist/trpc.d.ts.map +1 -1
  175. package/dist/trpc.js +2 -2
  176. package/dist/trpc.js.map +1 -1
  177. package/dist/utils/email.d.ts +9 -1
  178. package/dist/utils/email.d.ts.map +1 -1
  179. package/dist/utils/email.js +20 -5
  180. package/dist/utils/email.js.map +1 -1
  181. package/dist/utils/inference.d.ts +5 -0
  182. package/dist/utils/inference.d.ts.map +1 -1
  183. package/dist/utils/inference.js +71 -7
  184. package/dist/utils/inference.js.map +1 -1
  185. package/dist/utils/logger.d.ts.map +1 -1
  186. package/dist/utils/logger.js +3 -3
  187. package/dist/utils/logger.js.map +1 -1
  188. package/docker-compose.yml +14 -0
  189. package/package.json +13 -4
  190. package/prisma/schema.prisma +34 -5
  191. package/scripts/test-pre-push.ts +14 -0
  192. package/src/index.ts +98 -54
  193. package/src/instrument.ts +13 -6
  194. package/src/lib/config/env.ts +126 -0
  195. package/src/lib/fileUpload.ts +3 -2
  196. package/src/lib/googleCloudStorage.ts +6 -6
  197. package/src/lib/jsonConversion.ts +12 -14
  198. package/src/lib/prisma.ts +23 -2
  199. package/src/lib/pusher.ts +6 -5
  200. package/src/middleware/auth.ts +5 -3
  201. package/src/middleware/security.ts +80 -0
  202. package/src/routers/_app.ts +2 -0
  203. package/src/routers/agenda.ts +10 -7
  204. package/src/routers/announcement.ts +4 -2
  205. package/src/routers/assignment.ts +74 -41
  206. package/src/routers/attendance.ts +2 -2
  207. package/src/routers/auth.ts +143 -14
  208. package/src/routers/class.ts +52 -3
  209. package/src/routers/conversation.ts +49 -29
  210. package/src/routers/file.ts +29 -5
  211. package/src/routers/labChat.ts +3 -367
  212. package/src/routers/message.ts +1 -1
  213. package/src/routers/newtonChat.ts +299 -0
  214. package/src/routers/section.ts +26 -6
  215. package/src/routers/user.ts +3 -2
  216. package/src/routers/worksheet.ts +26 -38
  217. package/src/seedDatabase.ts +290 -283
  218. package/src/server/pipelines/aiLabChat.ts +507 -0
  219. package/src/server/pipelines/aiNewtonChat.ts +338 -0
  220. package/src/server/pipelines/gradeWorksheet.ts +151 -0
  221. package/src/trpc.ts +2 -0
  222. package/src/utils/email.ts +30 -3
  223. package/src/utils/inference.ts +85 -5
  224. package/src/utils/logger.ts +2 -1
  225. package/tests/announcement.test.ts +164 -0
  226. package/tests/assignment.test.ts +296 -0
  227. package/tests/attendance.test.ts +168 -0
  228. package/tests/auth.test.ts +33 -10
  229. package/tests/class.test.ts +34 -9
  230. package/tests/event.test.ts +228 -0
  231. package/tests/section.test.ts +216 -0
  232. package/tests/setup.ts +70 -16
  233. package/tests/user.test.ts +158 -0
  234. package/vitest.config.ts +26 -0
  235. package/API_SPECIFICATION.md +0 -1597
  236. package/BASE64_REMOVAL_SUMMARY.md +0 -164
  237. package/CHAT_API_SPEC.md +0 -579
  238. package/LAB_CHAT_API_SPEC.md +0 -518
  239. package/dist/routers/school.d.ts +0 -208
  240. package/dist/routers/school.d.ts.map +0 -1
  241. package/dist/routers/school.js +0 -483
@@ -0,0 +1,262 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="725aad78-0e5f-5b68-a668-413b3e62886e")}catch(e){}}();
3
+ import { z } from 'zod';
4
+ import { createTRPCRouter, protectedProcedure } from '../trpc.js';
5
+ import { prisma } from '../lib/prisma.js';
6
+ import { pusher } from '../lib/pusher.js';
7
+ import { TRPCError } from '@trpc/server';
8
+ import { logger } from '../utils/logger.js';
9
+ import { isAIUser } from '../utils/aiUser.js';
10
+ import { generateAndSendNewtonIntroduction, generateAndSendNewtonResponse } from '../server/pipelines/aiNewtonChat.js';
11
+ export const newtonChatRouter = createTRPCRouter({
12
+ getTutorConversation: protectedProcedure
13
+ .input(z.object({
14
+ assignmentId: z.string(),
15
+ classId: z.string(),
16
+ }))
17
+ .query(async ({ input, ctx }) => {
18
+ const userId = ctx.user.id;
19
+ const { assignmentId, classId } = input;
20
+ // Verify user is a student in the class
21
+ const classMembership = await prisma.class.findFirst({
22
+ where: {
23
+ id: classId,
24
+ students: {
25
+ some: {
26
+ id: userId,
27
+ },
28
+ },
29
+ },
30
+ });
31
+ if (!classMembership) {
32
+ throw new TRPCError({
33
+ code: 'FORBIDDEN',
34
+ message: 'Not a student in this class',
35
+ });
36
+ }
37
+ // Find or create submission for this student and assignment
38
+ const submission = await prisma.submission.findFirst({
39
+ where: {
40
+ assignmentId,
41
+ studentId: userId,
42
+ },
43
+ });
44
+ if (!submission) {
45
+ throw new TRPCError({
46
+ code: 'NOT_FOUND',
47
+ message: 'Submission not found. Please create a submission first.',
48
+ });
49
+ }
50
+ // Find the latest NewtonChat for this submission, or create a new one
51
+ const result = await prisma.$transaction(async (tx) => {
52
+ // Get the latest NewtonChat for this submission
53
+ const existingNewtonChat = await tx.newtonChat.findFirst({
54
+ where: {
55
+ submissionId: submission.id,
56
+ },
57
+ include: {
58
+ conversation: {
59
+ include: {
60
+ members: {
61
+ where: {
62
+ userId,
63
+ },
64
+ },
65
+ },
66
+ },
67
+ },
68
+ orderBy: {
69
+ createdAt: 'desc',
70
+ },
71
+ });
72
+ // If exists and user is already a member, return it
73
+ if (existingNewtonChat && existingNewtonChat.conversation.members.length > 0) {
74
+ return existingNewtonChat;
75
+ }
76
+ // If exists but user is not a member, add them
77
+ if (existingNewtonChat) {
78
+ await tx.conversationMember.create({
79
+ data: {
80
+ userId,
81
+ conversationId: existingNewtonChat.conversationId,
82
+ role: 'MEMBER',
83
+ },
84
+ });
85
+ return existingNewtonChat;
86
+ }
87
+ // Create new NewtonChat with associated conversation
88
+ const conversation = await tx.conversation.create({
89
+ data: {
90
+ type: 'DM',
91
+ name: 'Session with Newton Tutor',
92
+ displayInChat: false, // Newton chats don't show in regular chat list
93
+ },
94
+ });
95
+ // Add student to the conversation
96
+ await tx.conversationMember.create({
97
+ data: {
98
+ userId,
99
+ conversationId: conversation.id,
100
+ role: 'MEMBER',
101
+ },
102
+ });
103
+ // Create the NewtonChat
104
+ const newtonChat = await tx.newtonChat.create({
105
+ data: {
106
+ submissionId: submission.id,
107
+ conversationId: conversation.id,
108
+ title: 'Session with Newton Tutor',
109
+ },
110
+ });
111
+ return newtonChat;
112
+ });
113
+ // Generate AI introduction message in parallel (don't await - fire and forget)
114
+ generateAndSendNewtonIntroduction(result.id, result.conversationId, submission.id).catch(error => {
115
+ logger.error('Failed to generate AI introduction:', { error, newtonChatId: result.id });
116
+ });
117
+ return {
118
+ conversationId: result.conversationId,
119
+ newtonChatId: result.id,
120
+ };
121
+ }),
122
+ postToNewtonChat: protectedProcedure
123
+ .input(z.object({
124
+ newtonChatId: z.string(),
125
+ content: z.string().min(1).max(4000),
126
+ mentionedUserIds: z.array(z.string()).optional(),
127
+ }))
128
+ .mutation(async ({ input, ctx }) => {
129
+ const userId = ctx.user.id;
130
+ const { newtonChatId, content, mentionedUserIds = [] } = input;
131
+ // Get newton chat and verify user is a member
132
+ const newtonChat = await prisma.newtonChat.findFirst({
133
+ where: {
134
+ id: newtonChatId,
135
+ conversation: {
136
+ members: {
137
+ some: {
138
+ userId,
139
+ },
140
+ },
141
+ },
142
+ },
143
+ include: {
144
+ conversation: {
145
+ select: {
146
+ id: true,
147
+ },
148
+ },
149
+ submission: {
150
+ include: {
151
+ assignment: {
152
+ select: {
153
+ id: true,
154
+ title: true,
155
+ instructions: true,
156
+ class: {
157
+ select: {
158
+ subject: true,
159
+ },
160
+ },
161
+ },
162
+ },
163
+ },
164
+ },
165
+ },
166
+ });
167
+ if (!newtonChat) {
168
+ throw new TRPCError({
169
+ code: 'FORBIDDEN',
170
+ message: 'Newton chat not found or access denied',
171
+ });
172
+ }
173
+ // Verify mentioned users are members of the conversation
174
+ if (mentionedUserIds.length > 0) {
175
+ const mentionedMemberships = await prisma.conversationMember.findMany({
176
+ where: {
177
+ conversationId: newtonChat.conversationId,
178
+ userId: { in: mentionedUserIds },
179
+ },
180
+ });
181
+ if (mentionedMemberships.length !== mentionedUserIds.length) {
182
+ throw new TRPCError({
183
+ code: 'BAD_REQUEST',
184
+ message: 'Some mentioned users are not members of this conversation',
185
+ });
186
+ }
187
+ }
188
+ // Create message and mentions
189
+ const result = await prisma.$transaction(async (tx) => {
190
+ const message = await tx.message.create({
191
+ data: {
192
+ content,
193
+ senderId: userId,
194
+ conversationId: newtonChat.conversationId,
195
+ },
196
+ include: {
197
+ sender: {
198
+ select: {
199
+ id: true,
200
+ username: true,
201
+ profile: {
202
+ select: {
203
+ displayName: true,
204
+ profilePicture: true,
205
+ },
206
+ },
207
+ },
208
+ },
209
+ },
210
+ });
211
+ // Create mentions
212
+ if (mentionedUserIds.length > 0) {
213
+ await tx.mention.createMany({
214
+ data: mentionedUserIds.map((mentionedUserId) => ({
215
+ messageId: message.id,
216
+ userId: mentionedUserId,
217
+ })),
218
+ });
219
+ }
220
+ // Update newton chat timestamp
221
+ await tx.newtonChat.update({
222
+ where: { id: newtonChatId },
223
+ data: { updatedAt: new Date() },
224
+ });
225
+ return message;
226
+ });
227
+ // Broadcast to Pusher channel (same format as regular chat)
228
+ try {
229
+ await pusher.trigger(`conversation-${newtonChat.conversationId}`, 'new-message', {
230
+ id: result.id,
231
+ content: result.content,
232
+ senderId: result.senderId,
233
+ conversationId: result.conversationId,
234
+ createdAt: result.createdAt,
235
+ sender: result.sender,
236
+ mentionedUserIds,
237
+ });
238
+ }
239
+ catch (error) {
240
+ console.error('Failed to broadcast newton chat message:', error);
241
+ // Don't fail the request if Pusher fails
242
+ }
243
+ // Generate AI response in parallel (don't await - fire and forget)
244
+ if (!isAIUser(userId)) {
245
+ // Run AI response generation in background
246
+ generateAndSendNewtonResponse(newtonChatId, content, newtonChat.conversationId, newtonChat.submission).catch(error => {
247
+ logger.error('Failed to generate AI response:', { error });
248
+ });
249
+ }
250
+ return {
251
+ id: result.id,
252
+ content: result.content,
253
+ senderId: result.senderId,
254
+ conversationId: result.conversationId,
255
+ createdAt: result.createdAt,
256
+ sender: result.sender,
257
+ mentionedUserIds,
258
+ };
259
+ }),
260
+ });
261
+ //# sourceMappingURL=newtonChat.js.map
262
+ //# debugId=725aad78-0e5f-5b68-a668-413b3e62886e
@@ -0,0 +1 @@
1
+ {"version":3,"file":"newtonChat.js","sources":["routers/newtonChat.ts"],"sourceRoot":"/","sourcesContent":["import { z } from 'zod';\nimport { createTRPCRouter, protectedProcedure } from '../trpc.js';\nimport { prisma } from '../lib/prisma.js';\nimport { pusher } from '../lib/pusher.js';\nimport { TRPCError } from '@trpc/server';\nimport { logger } from '../utils/logger.js';\nimport { isAIUser } from '../utils/aiUser.js';\nimport { generateAndSendNewtonIntroduction, generateAndSendNewtonResponse } from '../server/pipelines/aiNewtonChat.js';\n\nexport const newtonChatRouter = createTRPCRouter({\n getTutorConversation: protectedProcedure\n .input(\n z.object({\n assignmentId: z.string(),\n classId: z.string(),\n })\n )\n .query(async ({ input, ctx }) => {\n const userId = ctx.user!.id;\n const { assignmentId, classId } = input;\n\n // Verify user is a student in the class\n const classMembership = await prisma.class.findFirst({\n where: {\n id: classId,\n students: {\n some: {\n id: userId,\n },\n },\n },\n });\n\n if (!classMembership) {\n throw new TRPCError({\n code: 'FORBIDDEN',\n message: 'Not a student in this class',\n });\n }\n\n // Find or create submission for this student and assignment\n const submission = await prisma.submission.findFirst({\n where: {\n assignmentId,\n studentId: userId,\n },\n });\n\n if (!submission) {\n throw new TRPCError({\n code: 'NOT_FOUND',\n message: 'Submission not found. Please create a submission first.',\n });\n }\n\n // Find the latest NewtonChat for this submission, or create a new one\n const result = await prisma.$transaction(async (tx) => {\n // Get the latest NewtonChat for this submission\n const existingNewtonChat = await tx.newtonChat.findFirst({\n where: {\n submissionId: submission.id,\n },\n include: {\n conversation: {\n include: {\n members: {\n where: {\n userId,\n },\n },\n },\n },\n },\n orderBy: {\n createdAt: 'desc',\n },\n });\n\n // If exists and user is already a member, return it\n if (existingNewtonChat && existingNewtonChat.conversation.members.length > 0) {\n return existingNewtonChat;\n }\n\n // If exists but user is not a member, add them\n if (existingNewtonChat) {\n await tx.conversationMember.create({\n data: {\n userId,\n conversationId: existingNewtonChat.conversationId,\n role: 'MEMBER',\n },\n });\n\n return existingNewtonChat;\n }\n\n // Create new NewtonChat with associated conversation\n const conversation = await tx.conversation.create({\n data: {\n type: 'DM',\n name: 'Session with Newton Tutor',\n displayInChat: false, // Newton chats don't show in regular chat list\n },\n });\n\n // Add student to the conversation\n await tx.conversationMember.create({\n data: {\n userId,\n conversationId: conversation.id,\n role: 'MEMBER',\n },\n });\n\n // Create the NewtonChat\n const newtonChat = await tx.newtonChat.create({\n data: {\n submissionId: submission.id,\n conversationId: conversation.id,\n title: 'Session with Newton Tutor',\n },\n });\n\n return newtonChat;\n });\n\n // Generate AI introduction message in parallel (don't await - fire and forget)\n generateAndSendNewtonIntroduction(\n result.id,\n result.conversationId,\n submission.id\n ).catch(error => {\n logger.error('Failed to generate AI introduction:', { error, newtonChatId: result.id });\n });\n\n return {\n conversationId: result.conversationId,\n newtonChatId: result.id,\n };\n }),\n\n postToNewtonChat: protectedProcedure\n .input(\n z.object({\n newtonChatId: z.string(),\n content: z.string().min(1).max(4000),\n mentionedUserIds: z.array(z.string()).optional(),\n })\n )\n .mutation(async ({ input, ctx }) => {\n const userId = ctx.user!.id;\n const { newtonChatId, content, mentionedUserIds = [] } = input;\n\n // Get newton chat and verify user is a member\n const newtonChat = await prisma.newtonChat.findFirst({\n where: {\n id: newtonChatId,\n conversation: {\n members: {\n some: {\n userId,\n },\n },\n },\n },\n include: {\n conversation: {\n select: {\n id: true,\n },\n },\n submission: {\n include: {\n assignment: {\n select: {\n id: true,\n title: true,\n instructions: true,\n class: {\n select: {\n subject: true,\n },\n },\n },\n },\n },\n },\n },\n });\n\n if (!newtonChat) {\n throw new TRPCError({\n code: 'FORBIDDEN',\n message: 'Newton chat not found or access denied',\n });\n }\n\n // Verify mentioned users are members of the conversation\n if (mentionedUserIds.length > 0) {\n const mentionedMemberships = await prisma.conversationMember.findMany({\n where: {\n conversationId: newtonChat.conversationId,\n userId: { in: mentionedUserIds },\n },\n });\n\n if (mentionedMemberships.length !== mentionedUserIds.length) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: 'Some mentioned users are not members of this conversation',\n });\n }\n }\n\n // Create message and mentions\n const result = await prisma.$transaction(async (tx) => {\n const message = await tx.message.create({\n data: {\n content,\n senderId: userId,\n conversationId: newtonChat.conversationId,\n },\n include: {\n sender: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n },\n },\n },\n },\n },\n });\n\n // Create mentions\n if (mentionedUserIds.length > 0) {\n await tx.mention.createMany({\n data: mentionedUserIds.map((mentionedUserId) => ({\n messageId: message.id,\n userId: mentionedUserId,\n })),\n });\n }\n\n // Update newton chat timestamp\n await tx.newtonChat.update({\n where: { id: newtonChatId },\n data: { updatedAt: new Date() },\n });\n\n return message;\n });\n\n // Broadcast to Pusher channel (same format as regular chat)\n try {\n await pusher.trigger(`conversation-${newtonChat.conversationId}`, 'new-message', {\n id: result.id,\n content: result.content,\n senderId: result.senderId,\n conversationId: result.conversationId,\n createdAt: result.createdAt,\n sender: result.sender,\n mentionedUserIds,\n });\n } catch (error) {\n console.error('Failed to broadcast newton chat message:', error);\n // Don't fail the request if Pusher fails\n }\n\n // Generate AI response in parallel (don't await - fire and forget)\n if (!isAIUser(userId)) {\n // Run AI response generation in background\n generateAndSendNewtonResponse(\n newtonChatId,\n content,\n newtonChat.conversationId,\n newtonChat.submission\n ).catch(error => {\n logger.error('Failed to generate AI response:', { error });\n });\n }\n\n return {\n id: result.id,\n content: result.content,\n senderId: result.senderId,\n conversationId: result.conversationId,\n createdAt: result.createdAt,\n sender: result.sender,\n mentionedUserIds,\n };\n }),\n});\n\n\n"],"names":[],"mappings":"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","debug_id":"725aad78-0e5f-5b68-a668-413b3e62886e"}
@@ -30,9 +30,9 @@ export declare const notificationRouter: import("@trpc/server").TRPCBuiltRouter<
30
30
  title: string;
31
31
  content: string;
32
32
  createdAt: Date;
33
+ read: boolean;
33
34
  senderId: string | null;
34
35
  receiverId: string;
35
- read: boolean;
36
36
  })[];
37
37
  meta: object;
38
38
  }>;
@@ -52,9 +52,9 @@ export declare const notificationRouter: import("@trpc/server").TRPCBuiltRouter<
52
52
  title: string;
53
53
  content: string;
54
54
  createdAt: Date;
55
+ read: boolean;
55
56
  senderId: string | null;
56
57
  receiverId: string;
57
- read: boolean;
58
58
  }) | null;
59
59
  meta: object;
60
60
  }>;
@@ -69,9 +69,9 @@ export declare const notificationRouter: import("@trpc/server").TRPCBuiltRouter<
69
69
  title: string;
70
70
  content: string;
71
71
  createdAt: Date;
72
+ read: boolean;
72
73
  senderId: string | null;
73
74
  receiverId: string;
74
- read: boolean;
75
75
  };
76
76
  meta: object;
77
77
  }>;
@@ -93,9 +93,9 @@ export declare const notificationRouter: import("@trpc/server").TRPCBuiltRouter<
93
93
  title: string;
94
94
  content: string;
95
95
  createdAt: Date;
96
+ read: boolean;
96
97
  senderId: string | null;
97
98
  receiverId: string;
98
- read: boolean;
99
99
  };
100
100
  meta: object;
101
101
  }>;
@@ -16,10 +16,21 @@ export declare const sectionRouter: import("@trpc/server").TRPCBuiltRouter<{
16
16
  };
17
17
  transformer: false;
18
18
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
19
+ exists: import("@trpc/server").TRPCQueryProcedure<{
20
+ input: {
21
+ [x: string]: unknown;
22
+ classId: string;
23
+ id: string;
24
+ };
25
+ output: boolean;
26
+ meta: object;
27
+ }>;
19
28
  create: import("@trpc/server").TRPCMutationProcedure<{
20
29
  input: {
21
- name: string;
30
+ [x: string]: unknown;
22
31
  classId: string;
32
+ name: string;
33
+ id?: string | undefined;
23
34
  color?: string | undefined;
24
35
  };
25
36
  output: {
@@ -33,6 +44,7 @@ export declare const sectionRouter: import("@trpc/server").TRPCBuiltRouter<{
33
44
  }>;
34
45
  reorder: import("@trpc/server").TRPCMutationProcedure<{
35
46
  input: {
47
+ [x: string]: unknown;
36
48
  classId: string;
37
49
  movedId: string;
38
50
  position: "start" | "end" | "before" | "after";
@@ -49,9 +61,10 @@ export declare const sectionRouter: import("@trpc/server").TRPCBuiltRouter<{
49
61
  }>;
50
62
  update: import("@trpc/server").TRPCMutationProcedure<{
51
63
  input: {
64
+ [x: string]: unknown;
65
+ classId: string;
52
66
  id: string;
53
67
  name: string;
54
- classId: string;
55
68
  color?: string | undefined;
56
69
  };
57
70
  output: {
@@ -65,8 +78,9 @@ export declare const sectionRouter: import("@trpc/server").TRPCBuiltRouter<{
65
78
  }>;
66
79
  reOrder: import("@trpc/server").TRPCMutationProcedure<{
67
80
  input: {
68
- id: string;
81
+ [x: string]: unknown;
69
82
  classId: string;
83
+ id: string;
70
84
  order: number;
71
85
  };
72
86
  output: {
@@ -76,8 +90,9 @@ export declare const sectionRouter: import("@trpc/server").TRPCBuiltRouter<{
76
90
  }>;
77
91
  delete: import("@trpc/server").TRPCMutationProcedure<{
78
92
  input: {
79
- id: string;
93
+ [x: string]: unknown;
80
94
  classId: string;
95
+ id: string;
81
96
  };
82
97
  output: {
83
98
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"section.d.ts","sourceRoot":"/","sources":["routers/section.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAuBxB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkUxB,CAAC"}
1
+ {"version":3,"file":"section.d.ts","sourceRoot":"/","sources":["routers/section.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwBxB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqVxB,CAAC"}
@@ -1,11 +1,12 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ac1474d5-7092-5f48-9b93-aa7c2055bdb3")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="fd56eafe-403c-58b3-b36f-74a278bc60c9")}catch(e){}}();
3
3
  import { z } from "zod";
4
- import { createTRPCRouter, protectedProcedure } from "../trpc.js";
4
+ import { createTRPCRouter, protectedClassMemberProcedure, protectedTeacherProcedure } from "../trpc.js";
5
5
  import { TRPCError } from "@trpc/server";
6
6
  import { prisma } from "../lib/prisma.js";
7
7
  const createSectionSchema = z.object({
8
8
  classId: z.string(),
9
+ id: z.string().optional(),
9
10
  name: z.string(),
10
11
  color: z.string().optional(),
11
12
  });
@@ -20,7 +21,23 @@ const deleteSectionSchema = z.object({
20
21
  classId: z.string(),
21
22
  });
22
23
  export const sectionRouter = createTRPCRouter({
23
- create: protectedProcedure
24
+ exists: protectedClassMemberProcedure
25
+ .input(z.object({
26
+ id: z.string(),
27
+ }))
28
+ .query(async ({ ctx, input }) => {
29
+ if (!ctx.user) {
30
+ throw new TRPCError({
31
+ code: "UNAUTHORIZED",
32
+ message: "User must be authenticated",
33
+ });
34
+ }
35
+ const section = await prisma.section.findUnique({
36
+ where: { id: input.id },
37
+ });
38
+ return section ? true : false;
39
+ }),
40
+ create: protectedTeacherProcedure
24
41
  .input(createSectionSchema)
25
42
  .mutation(async ({ ctx, input }) => {
26
43
  if (!ctx.user) {
@@ -48,6 +65,7 @@ export const sectionRouter = createTRPCRouter({
48
65
  }
49
66
  const section = await prisma.section.create({
50
67
  data: {
68
+ ...(input.id && { id: input.id }),
51
69
  name: input.name,
52
70
  order: 0,
53
71
  class: {
@@ -85,7 +103,7 @@ export const sectionRouter = createTRPCRouter({
85
103
  }));
86
104
  return section;
87
105
  }),
88
- reorder: protectedProcedure
106
+ reorder: protectedTeacherProcedure
89
107
  .input(z.object({
90
108
  classId: z.string(),
91
109
  movedId: z.string(), // Section ID
@@ -171,7 +189,7 @@ export const sectionRouter = createTRPCRouter({
171
189
  });
172
190
  return result;
173
191
  }),
174
- update: protectedProcedure
192
+ update: protectedTeacherProcedure
175
193
  .input(updateSectionSchema)
176
194
  .mutation(async ({ ctx, input }) => {
177
195
  if (!ctx.user) {
@@ -208,7 +226,7 @@ export const sectionRouter = createTRPCRouter({
208
226
  });
209
227
  return section;
210
228
  }),
211
- reOrder: protectedProcedure
229
+ reOrder: protectedTeacherProcedure
212
230
  .input(z.object({
213
231
  id: z.string(),
214
232
  classId: z.string(),
@@ -270,7 +288,7 @@ export const sectionRouter = createTRPCRouter({
270
288
  });
271
289
  return { id: input.id };
272
290
  }),
273
- delete: protectedProcedure
291
+ delete: protectedTeacherProcedure
274
292
  .input(deleteSectionSchema)
275
293
  .mutation(async ({ ctx, input }) => {
276
294
  if (!ctx.user) {
@@ -303,4 +321,4 @@ export const sectionRouter = createTRPCRouter({
303
321
  }),
304
322
  });
305
323
  //# sourceMappingURL=section.js.map
306
- //# debugId=ac1474d5-7092-5f48-9b93-aa7c2055bdb3
324
+ //# debugId=fd56eafe-403c-58b3-b36f-74a278bc60c9
@@ -1 +1 @@
1
- {"version":3,"file":"section.js","sources":["routers/section.ts"],"sourceRoot":"/","sourcesContent":["import { z } from \"zod\";\nimport { createTRPCRouter, protectedProcedure } from \"../trpc.js\";\nimport { TRPCError } from \"@trpc/server\";\nimport { prisma } from \"../lib/prisma.js\";\n\nconst createSectionSchema = z.object({\n classId: z.string(),\n name: z.string(),\n color: z.string().optional(),\n});\n\nconst updateSectionSchema = z.object({\n id: z.string(),\n classId: z.string(),\n name: z.string(),\n color: z.string().optional(),\n});\n\nconst deleteSectionSchema = z.object({\n id: z.string(),\n classId: z.string(),\n});\n\nexport const sectionRouter = createTRPCRouter({\n create: protectedProcedure\n .input(createSectionSchema)\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n // Verify user is a teacher of the class\n const classData = await prisma.class.findFirst({\n where: {\n id: input.classId,\n teachers: {\n some: {\n id: ctx.user.id,\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found or you are not a teacher\",\n });\n }\n\n const section = await prisma.section.create({\n data: {\n name: input.name,\n order: 0,\n class: {\n connect: { id: input.classId },\n },\n ...(input.color && {\n color: input.color,\n }),\n },\n });\n\n // Insert new section at top of unified list (sections + assignments) and normalize\n const [sections, assignments] = await Promise.all([\n prisma.section.findMany({\n where: { classId: input.classId },\n select: { id: true, order: true },\n }),\n prisma.assignment.findMany({\n where: { classId: input.classId },\n select: { id: true, order: true },\n }),\n ]);\n\n const unified = [\n ...sections.map(s => ({ id: s.id, order: s.order, type: 'section' as const })),\n ...assignments.map(a => ({ id: a.id, order: a.order, type: 'assignment' as const })),\n ].sort((a, b) => (a.order ?? Number.MAX_SAFE_INTEGER) - (b.order ?? Number.MAX_SAFE_INTEGER));\n\n const withoutNew = unified.filter(item => !(item.id === section.id && item.type === 'section'));\n const reindexed = [{ id: section.id, type: 'section' as const }, ...withoutNew.map(item => ({ id: item.id, type: item.type }))];\n\n await Promise.all(\n reindexed.map((item, index) => {\n if (item.type === 'section') {\n return prisma.section.update({ where: { id: item.id }, data: { order: index + 1 } });\n } else {\n return prisma.assignment.update({ where: { id: item.id }, data: { order: index + 1 } });\n }\n })\n );\n\n return section;\n }),\n\n reorder: protectedProcedure\n .input(z.object({\n classId: z.string(),\n movedId: z.string(), // Section ID\n // One of: place at start/end of unified list, or relative to targetId (can be section or assignment)\n position: z.enum(['start', 'end', 'before', 'after']),\n targetId: z.string().optional(), // Can be a section ID or assignment ID\n }))\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n const { classId, movedId, position, targetId } = input;\n\n const moved = await prisma.section.findFirst({\n where: { id: movedId, classId },\n select: { id: true, classId: true },\n });\n\n if (!moved) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Section not found' });\n }\n\n if ((position === 'before' || position === 'after') && !targetId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'targetId required for before/after' });\n }\n\n const result = await prisma.$transaction(async (tx) => {\n const [sections, assignments] = await Promise.all([\n tx.section.findMany({\n where: { classId },\n select: { id: true, order: true },\n }),\n tx.assignment.findMany({\n where: { classId },\n select: { id: true, order: true },\n }),\n ]);\n\n const unified = [\n ...sections.map(s => ({ id: s.id, order: s.order, type: 'section' as const })),\n ...assignments.map(a => ({ id: a.id, order: a.order, type: 'assignment' as const })),\n ].sort((a, b) => (a.order ?? Number.MAX_SAFE_INTEGER) - (b.order ?? Number.MAX_SAFE_INTEGER));\n\n const movedIdx = unified.findIndex(item => item.id === movedId && item.type === 'section');\n if (movedIdx === -1) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Section not found in unified list' });\n }\n\n const withoutMoved = unified.filter(item => !(item.id === movedId && item.type === 'section'));\n\n let next: Array<{ id: string; type: 'section' | 'assignment' }> = [];\n\n if (position === 'start') {\n next = [{ id: movedId, type: 'section' }, ...withoutMoved.map(item => ({ id: item.id, type: item.type }))];\n } else if (position === 'end') {\n next = [...withoutMoved.map(item => ({ id: item.id, type: item.type })), { id: movedId, type: 'section' }];\n } else {\n const targetIdx = withoutMoved.findIndex(item => item.id === targetId);\n if (targetIdx === -1) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'targetId not found in unified list' });\n }\n if (position === 'before') {\n next = [\n ...withoutMoved.slice(0, targetIdx).map(item => ({ id: item.id, type: item.type })),\n { id: movedId, type: 'section' },\n ...withoutMoved.slice(targetIdx).map(item => ({ id: item.id, type: item.type })),\n ];\n } else {\n next = [\n ...withoutMoved.slice(0, targetIdx + 1).map(item => ({ id: item.id, type: item.type })),\n { id: movedId, type: 'section' },\n ...withoutMoved.slice(targetIdx + 1).map(item => ({ id: item.id, type: item.type })),\n ];\n }\n }\n\n // Normalize to 1..n\n await Promise.all(\n next.map((item, index) => {\n if (item.type === 'section') {\n return tx.section.update({ where: { id: item.id }, data: { order: index + 1 } });\n } else {\n return tx.assignment.update({ where: { id: item.id }, data: { order: index + 1 } });\n }\n })\n );\n\n return tx.section.findUnique({ where: { id: movedId } });\n });\n\n return result;\n }),\n\n update: protectedProcedure\n .input(updateSectionSchema)\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n // Verify user is a teacher of the class\n const classData = await prisma.class.findFirst({\n where: {\n id: input.classId,\n teachers: {\n some: {\n id: ctx.user.id,\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found or you are not a teacher\",\n });\n }\n\n const section = await prisma.section.update({\n where: { id: input.id },\n data: {\n name: input.name,\n ...(input.color && {\n color: input.color,\n }),\n },\n });\n\n return section;\n }),\n\n reOrder: protectedProcedure\n .input(z.object({\n id: z.string(),\n classId: z.string(),\n order: z.number(),\n }))\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n // Verify user is a teacher of the class\n const classData = await prisma.class.findFirst({\n where: {\n id: input.classId,\n teachers: {\n some: {\n id: ctx.user.id,\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found or you are not a teacher\",\n });\n }\n\n // Update order and normalize unified list\n await prisma.$transaction(async (tx) => {\n await tx.section.update({\n where: { id: input.id },\n data: { order: input.order },\n });\n\n // Normalize entire unified list\n const [sections, assignments] = await Promise.all([\n tx.section.findMany({\n where: { classId: input.classId },\n select: { id: true, order: true },\n }),\n tx.assignment.findMany({\n where: { classId: input.classId },\n select: { id: true, order: true },\n }),\n ]);\n\n const unified = [\n ...sections.map(s => ({ id: s.id, order: s.order, type: 'section' as const })),\n ...assignments.map(a => ({ id: a.id, order: a.order, type: 'assignment' as const })),\n ].sort((a, b) => (a.order ?? Number.MAX_SAFE_INTEGER) - (b.order ?? Number.MAX_SAFE_INTEGER));\n\n await Promise.all(\n unified.map((item, index) => {\n if (item.type === 'section') {\n return tx.section.update({ where: { id: item.id }, data: { order: index + 1 } });\n } else {\n return tx.assignment.update({ where: { id: item.id }, data: { order: index + 1 } });\n }\n })\n );\n });\n\n return { id: input.id };\n }),\n\n delete: protectedProcedure\n .input(deleteSectionSchema)\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n // Verify user is a teacher of the class\n const classData = await prisma.class.findFirst({\n where: {\n id: input.classId,\n teachers: {\n some: {\n id: ctx.user.id,\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found or you are not a teacher\",\n });\n }\n\n await prisma.section.delete({\n where: { id: input.id },\n });\n\n return { id: input.id };\n }),\n}); "],"names":[],"mappings":"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","debug_id":"ac1474d5-7092-5f48-9b93-aa7c2055bdb3"}
1
+ {"version":3,"file":"section.js","sources":["routers/section.ts"],"sourceRoot":"/","sourcesContent":["import { z } from \"zod\";\nimport { createTRPCRouter, protectedClassMemberProcedure, protectedProcedure, protectedTeacherProcedure } from \"../trpc.js\";\nimport { TRPCError } from \"@trpc/server\";\nimport { prisma } from \"../lib/prisma.js\";\n\nconst createSectionSchema = z.object({\n classId: z.string(),\n id: z.string().optional(),\n name: z.string(),\n color: z.string().optional(),\n});\n\nconst updateSectionSchema = z.object({\n id: z.string(),\n classId: z.string(),\n name: z.string(),\n color: z.string().optional(),\n});\n\nconst deleteSectionSchema = z.object({\n id: z.string(),\n classId: z.string(),\n});\n\nexport const sectionRouter = createTRPCRouter({\n exists: protectedClassMemberProcedure\n .input(z.object({\n id: z.string(),\n }))\n .query(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n const section = await prisma.section.findUnique({\n where: { id: input.id },\n });\n\n return section ? true : false;\n }),\n create: protectedTeacherProcedure\n .input(createSectionSchema)\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n // Verify user is a teacher of the class\n const classData = await prisma.class.findFirst({\n where: {\n id: input.classId,\n teachers: {\n some: {\n id: ctx.user.id,\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found or you are not a teacher\",\n });\n }\n\n const section = await prisma.section.create({\n data: {\n ...(input.id && { id: input.id }),\n name: input.name,\n order: 0,\n class: {\n connect: { id: input.classId },\n },\n ...(input.color && {\n color: input.color,\n }),\n },\n });\n\n // Insert new section at top of unified list (sections + assignments) and normalize\n const [sections, assignments] = await Promise.all([\n prisma.section.findMany({\n where: { classId: input.classId },\n select: { id: true, order: true },\n }),\n prisma.assignment.findMany({\n where: { classId: input.classId },\n select: { id: true, order: true },\n }),\n ]);\n\n const unified = [\n ...sections.map(s => ({ id: s.id, order: s.order, type: 'section' as const })),\n ...assignments.map(a => ({ id: a.id, order: a.order, type: 'assignment' as const })),\n ].sort((a, b) => (a.order ?? Number.MAX_SAFE_INTEGER) - (b.order ?? Number.MAX_SAFE_INTEGER));\n\n const withoutNew = unified.filter(item => !(item.id === section.id && item.type === 'section'));\n const reindexed = [{ id: section.id, type: 'section' as const }, ...withoutNew.map(item => ({ id: item.id, type: item.type }))];\n\n await Promise.all(\n reindexed.map((item, index) => {\n if (item.type === 'section') {\n return prisma.section.update({ where: { id: item.id }, data: { order: index + 1 } });\n } else {\n return prisma.assignment.update({ where: { id: item.id }, data: { order: index + 1 } });\n }\n })\n );\n\n return section;\n }),\n\n reorder: protectedTeacherProcedure\n .input(z.object({\n classId: z.string(),\n movedId: z.string(), // Section ID\n // One of: place at start/end of unified list, or relative to targetId (can be section or assignment)\n position: z.enum(['start', 'end', 'before', 'after']),\n targetId: z.string().optional(), // Can be a section ID or assignment ID\n }))\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n const { classId, movedId, position, targetId } = input;\n\n const moved = await prisma.section.findFirst({\n where: { id: movedId, classId },\n select: { id: true, classId: true },\n });\n\n if (!moved) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Section not found' });\n }\n\n if ((position === 'before' || position === 'after') && !targetId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'targetId required for before/after' });\n }\n\n const result = await prisma.$transaction(async (tx) => {\n const [sections, assignments] = await Promise.all([\n tx.section.findMany({\n where: { classId },\n select: { id: true, order: true },\n }),\n tx.assignment.findMany({\n where: { classId },\n select: { id: true, order: true },\n }),\n ]);\n\n const unified = [\n ...sections.map(s => ({ id: s.id, order: s.order, type: 'section' as const })),\n ...assignments.map(a => ({ id: a.id, order: a.order, type: 'assignment' as const })),\n ].sort((a, b) => (a.order ?? Number.MAX_SAFE_INTEGER) - (b.order ?? Number.MAX_SAFE_INTEGER));\n\n const movedIdx = unified.findIndex(item => item.id === movedId && item.type === 'section');\n if (movedIdx === -1) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Section not found in unified list' });\n }\n\n const withoutMoved = unified.filter(item => !(item.id === movedId && item.type === 'section'));\n\n let next: Array<{ id: string; type: 'section' | 'assignment' }> = [];\n\n if (position === 'start') {\n next = [{ id: movedId, type: 'section' }, ...withoutMoved.map(item => ({ id: item.id, type: item.type }))];\n } else if (position === 'end') {\n next = [...withoutMoved.map(item => ({ id: item.id, type: item.type })), { id: movedId, type: 'section' }];\n } else {\n const targetIdx = withoutMoved.findIndex(item => item.id === targetId);\n if (targetIdx === -1) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'targetId not found in unified list' });\n }\n if (position === 'before') {\n next = [\n ...withoutMoved.slice(0, targetIdx).map(item => ({ id: item.id, type: item.type })),\n { id: movedId, type: 'section' },\n ...withoutMoved.slice(targetIdx).map(item => ({ id: item.id, type: item.type })),\n ];\n } else {\n next = [\n ...withoutMoved.slice(0, targetIdx + 1).map(item => ({ id: item.id, type: item.type })),\n { id: movedId, type: 'section' },\n ...withoutMoved.slice(targetIdx + 1).map(item => ({ id: item.id, type: item.type })),\n ];\n }\n }\n\n // Normalize to 1..n\n await Promise.all(\n next.map((item, index) => {\n if (item.type === 'section') {\n return tx.section.update({ where: { id: item.id }, data: { order: index + 1 } });\n } else {\n return tx.assignment.update({ where: { id: item.id }, data: { order: index + 1 } });\n }\n })\n );\n\n return tx.section.findUnique({ where: { id: movedId } });\n });\n\n return result;\n }),\n\n update: protectedTeacherProcedure\n .input(updateSectionSchema)\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n // Verify user is a teacher of the class\n const classData = await prisma.class.findFirst({\n where: {\n id: input.classId,\n teachers: {\n some: {\n id: ctx.user.id,\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found or you are not a teacher\",\n });\n }\n\n const section = await prisma.section.update({\n where: { id: input.id },\n data: {\n name: input.name,\n ...(input.color && {\n color: input.color,\n }),\n },\n });\n\n return section;\n }),\n\n reOrder: protectedTeacherProcedure\n .input(z.object({\n id: z.string(),\n classId: z.string(),\n order: z.number(),\n }))\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n // Verify user is a teacher of the class\n const classData = await prisma.class.findFirst({\n where: {\n id: input.classId,\n teachers: {\n some: {\n id: ctx.user.id,\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found or you are not a teacher\",\n });\n }\n\n // Update order and normalize unified list\n await prisma.$transaction(async (tx) => {\n await tx.section.update({\n where: { id: input.id },\n data: { order: input.order },\n });\n\n // Normalize entire unified list\n const [sections, assignments] = await Promise.all([\n tx.section.findMany({\n where: { classId: input.classId },\n select: { id: true, order: true },\n }),\n tx.assignment.findMany({\n where: { classId: input.classId },\n select: { id: true, order: true },\n }),\n ]);\n\n const unified = [\n ...sections.map(s => ({ id: s.id, order: s.order, type: 'section' as const })),\n ...assignments.map(a => ({ id: a.id, order: a.order, type: 'assignment' as const })),\n ].sort((a, b) => (a.order ?? Number.MAX_SAFE_INTEGER) - (b.order ?? Number.MAX_SAFE_INTEGER));\n\n await Promise.all(\n unified.map((item, index) => {\n if (item.type === 'section') {\n return tx.section.update({ where: { id: item.id }, data: { order: index + 1 } });\n } else {\n return tx.assignment.update({ where: { id: item.id }, data: { order: index + 1 } });\n }\n })\n );\n });\n\n return { id: input.id };\n }),\n\n delete: protectedTeacherProcedure\n .input(deleteSectionSchema)\n .mutation(async ({ ctx, input }) => {\n if (!ctx.user) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"User must be authenticated\",\n });\n }\n\n // Verify user is a teacher of the class\n const classData = await prisma.class.findFirst({\n where: {\n id: input.classId,\n teachers: {\n some: {\n id: ctx.user.id,\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Class not found or you are not a teacher\",\n });\n }\n\n await prisma.section.delete({\n where: { id: input.id },\n });\n\n return { id: input.id };\n }),\n}); "],"names":[],"mappings":"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","debug_id":"fd56eafe-403c-58b3-b36f-74a278bc60c9"}
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"/","sources":["routers/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2DxB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuMrB,CAAC"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"/","sources":["routers/user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA4DxB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuMrB,CAAC"}