@studious-lms/server 1.4.6 → 1.4.9

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 (177) hide show
  1. package/.github/workflows/npm.yml +28 -0
  2. package/dist/models/access.d.ts +112 -0
  3. package/dist/models/access.d.ts.map +1 -0
  4. package/dist/models/access.js +49 -0
  5. package/dist/models/access.js.map +1 -0
  6. package/dist/models/announcement.d.ts +17 -2
  7. package/dist/models/announcement.d.ts.map +1 -1
  8. package/dist/models/announcement.js +21 -4
  9. package/dist/models/announcement.js.map +1 -1
  10. package/dist/models/assignment.d.ts +69 -37
  11. package/dist/models/assignment.d.ts.map +1 -1
  12. package/dist/models/assignment.js +124 -15
  13. package/dist/models/assignment.js.map +1 -1
  14. package/dist/models/attendance.d.ts +1 -1
  15. package/dist/models/attendance.d.ts.map +1 -1
  16. package/dist/models/attendance.js +6 -5
  17. package/dist/models/attendance.js.map +1 -1
  18. package/dist/models/auth.d.ts +5 -5
  19. package/dist/models/auth.d.ts.map +1 -1
  20. package/dist/models/auth.js +7 -11
  21. package/dist/models/auth.js.map +1 -1
  22. package/dist/models/class.d.ts +26 -26
  23. package/dist/models/class.d.ts.map +1 -1
  24. package/dist/models/class.js +7 -11
  25. package/dist/models/class.js.map +1 -1
  26. package/dist/models/comment.d.ts +134 -70
  27. package/dist/models/comment.d.ts.map +1 -1
  28. package/dist/models/comment.js +30 -42
  29. package/dist/models/comment.js.map +1 -1
  30. package/dist/models/conversation.d.ts +7 -7
  31. package/dist/models/event.d.ts +52 -3
  32. package/dist/models/event.d.ts.map +1 -1
  33. package/dist/models/event.js +56 -6
  34. package/dist/models/event.js.map +1 -1
  35. package/dist/models/file.d.ts +178 -103
  36. package/dist/models/file.d.ts.map +1 -1
  37. package/dist/models/file.js +54 -14
  38. package/dist/models/file.js.map +1 -1
  39. package/dist/models/folder.d.ts +22 -22
  40. package/dist/models/folder.d.ts.map +1 -1
  41. package/dist/models/folder.js +5 -4
  42. package/dist/models/folder.js.map +1 -1
  43. package/dist/models/labChat.d.ts +20 -20
  44. package/dist/models/labChat.d.ts.map +1 -1
  45. package/dist/models/labChat.js +8 -10
  46. package/dist/models/labChat.js.map +1 -1
  47. package/dist/models/marketing.d.ts +1 -1
  48. package/dist/models/message.d.ts +6 -6
  49. package/dist/models/newtonChat.d.ts +5 -5
  50. package/dist/models/school.d.ts +361 -0
  51. package/dist/models/school.d.ts.map +1 -0
  52. package/dist/models/school.js +314 -0
  53. package/dist/models/school.js.map +1 -0
  54. package/dist/models/section.d.ts +1 -1
  55. package/dist/models/section.d.ts.map +1 -1
  56. package/dist/models/section.js +5 -4
  57. package/dist/models/section.js.map +1 -1
  58. package/dist/models/user.d.ts +4 -4
  59. package/dist/models/worksheet.d.ts +163 -141
  60. package/dist/models/worksheet.d.ts.map +1 -1
  61. package/dist/models/worksheet.js +42 -17
  62. package/dist/models/worksheet.js.map +1 -1
  63. package/dist/pipelines/gradeWorksheet.d.ts +2 -2
  64. package/dist/pipelines/pdfToWorksheet.d.ts +1 -1
  65. package/dist/routers/_app.d.ts +1271 -327
  66. package/dist/routers/_app.d.ts.map +1 -1
  67. package/dist/routers/_app.js +4 -2
  68. package/dist/routers/_app.js.map +1 -1
  69. package/dist/routers/announcement.d.ts +5 -5
  70. package/dist/routers/announcement.d.ts.map +1 -1
  71. package/dist/routers/announcement.js +25 -5
  72. package/dist/routers/announcement.js.map +1 -1
  73. package/dist/routers/assignment.d.ts +79 -44
  74. package/dist/routers/assignment.d.ts.map +1 -1
  75. package/dist/routers/assignment.js +32 -12
  76. package/dist/routers/assignment.js.map +1 -1
  77. package/dist/routers/class.d.ts +40 -20
  78. package/dist/routers/class.d.ts.map +1 -1
  79. package/dist/routers/class.js +3 -2
  80. package/dist/routers/class.js.map +1 -1
  81. package/dist/routers/comment.d.ts +5 -5
  82. package/dist/routers/conversation.d.ts +6 -6
  83. package/dist/routers/event.d.ts +21 -2
  84. package/dist/routers/event.d.ts.map +1 -1
  85. package/dist/routers/file.d.ts +2 -2
  86. package/dist/routers/folder.d.ts +24 -24
  87. package/dist/routers/labChat.d.ts +7 -7
  88. package/dist/routers/school.d.ts +384 -0
  89. package/dist/routers/school.d.ts.map +1 -0
  90. package/dist/routers/school.js +79 -0
  91. package/dist/routers/school.js.map +1 -0
  92. package/dist/routers/search.d.ts +1 -1
  93. package/dist/routers/worksheet.d.ts +36 -20
  94. package/dist/routers/worksheet.d.ts.map +1 -1
  95. package/dist/routers/worksheet.js +10 -3
  96. package/dist/routers/worksheet.js.map +1 -1
  97. package/dist/services/announcement.d.ts.map +1 -1
  98. package/dist/services/announcement.js +10 -6
  99. package/dist/services/announcement.js.map +1 -1
  100. package/dist/services/assignment.d.ts +66 -36
  101. package/dist/services/assignment.d.ts.map +1 -1
  102. package/dist/services/assignment.js +37 -3
  103. package/dist/services/assignment.js.map +1 -1
  104. package/dist/services/class.d.ts +39 -19
  105. package/dist/services/class.d.ts.map +1 -1
  106. package/dist/services/class.js +52 -15
  107. package/dist/services/class.js.map +1 -1
  108. package/dist/services/comment.d.ts +5 -5
  109. package/dist/services/comment.d.ts.map +1 -1
  110. package/dist/services/comment.js +8 -3
  111. package/dist/services/comment.js.map +1 -1
  112. package/dist/services/conversation.d.ts +6 -6
  113. package/dist/services/event.d.ts +21 -2
  114. package/dist/services/event.d.ts.map +1 -1
  115. package/dist/services/event.js +11 -7
  116. package/dist/services/event.js.map +1 -1
  117. package/dist/services/file.d.ts +2 -2
  118. package/dist/services/file.d.ts.map +1 -1
  119. package/dist/services/file.js +17 -8
  120. package/dist/services/file.js.map +1 -1
  121. package/dist/services/folder.d.ts +24 -24
  122. package/dist/services/labChat.d.ts +7 -7
  123. package/dist/services/school.d.ts +299 -0
  124. package/dist/services/school.d.ts.map +1 -0
  125. package/dist/services/school.js +225 -0
  126. package/dist/services/school.js.map +1 -0
  127. package/dist/services/worksheet.d.ts +31 -20
  128. package/dist/services/worksheet.d.ts.map +1 -1
  129. package/dist/services/worksheet.js +37 -3
  130. package/dist/services/worksheet.js.map +1 -1
  131. package/package.json +1 -1
  132. package/prisma/migrations/20260504071500_school_memberships/migration.sql +81 -0
  133. package/prisma/schema.prisma +66 -2
  134. package/src/models/access.ts +48 -0
  135. package/src/models/announcement.ts +19 -2
  136. package/src/models/assignment.ts +149 -13
  137. package/src/models/attendance.ts +4 -3
  138. package/src/models/auth.ts +8 -9
  139. package/src/models/class.ts +8 -9
  140. package/src/models/comment.ts +29 -40
  141. package/src/models/event.ts +54 -4
  142. package/src/models/file.ts +53 -12
  143. package/src/models/folder.ts +3 -2
  144. package/src/models/labChat.ts +9 -8
  145. package/src/models/school.ts +361 -0
  146. package/src/models/section.ts +3 -2
  147. package/src/models/worksheet.ts +61 -12
  148. package/src/routers/_app.ts +2 -0
  149. package/src/routers/announcement.ts +30 -4
  150. package/src/routers/assignment.ts +46 -9
  151. package/src/routers/class.ts +1 -0
  152. package/src/routers/school.ts +122 -0
  153. package/src/routers/worksheet.ts +18 -0
  154. package/src/services/announcement.ts +12 -4
  155. package/src/services/assignment.ts +47 -1
  156. package/src/services/class.ts +61 -14
  157. package/src/services/comment.ts +10 -1
  158. package/src/services/event.ts +23 -6
  159. package/src/services/file.ts +20 -6
  160. package/src/services/school.ts +308 -0
  161. package/src/services/worksheet.ts +46 -0
  162. package/dist/lib/notificationHandler.d.ts +0 -25
  163. package/dist/lib/notificationHandler.d.ts.map +0 -1
  164. package/dist/lib/notificationHandler.js +0 -32
  165. package/dist/lib/notificationHandler.js.map +0 -1
  166. package/dist/server/pipelines/aiLabChat.d.ts +0 -21
  167. package/dist/server/pipelines/aiLabChat.d.ts.map +0 -1
  168. package/dist/server/pipelines/aiLabChat.js +0 -456
  169. package/dist/server/pipelines/aiLabChat.js.map +0 -1
  170. package/dist/server/pipelines/aiNewtonChat.d.ts +0 -30
  171. package/dist/server/pipelines/aiNewtonChat.d.ts.map +0 -1
  172. package/dist/server/pipelines/aiNewtonChat.js +0 -285
  173. package/dist/server/pipelines/aiNewtonChat.js.map +0 -1
  174. package/dist/server/pipelines/gradeWorksheet.d.ts +0 -30
  175. package/dist/server/pipelines/gradeWorksheet.d.ts.map +0 -1
  176. package/dist/server/pipelines/gradeWorksheet.js +0 -248
  177. package/dist/server/pipelines/gradeWorksheet.js.map +0 -1
@@ -0,0 +1,308 @@
1
+ /**
2
+ * School service - school admin workflow, memberships, and invites.
3
+ */
4
+ import { SchoolMembershipRole } from "@prisma/client";
5
+ import { TRPCError } from "@trpc/server";
6
+ import { v4 as uuidv4 } from "uuid";
7
+ import { env } from "../lib/config/env.js";
8
+ import { prisma } from "../lib/prisma.js";
9
+ import { sendMail } from "../utils/email.js";
10
+ import { logger } from "../utils/logger.js";
11
+ import {
12
+ acceptSchoolInvite,
13
+ countActiveAdmins,
14
+ createSchoolInvite,
15
+ createSchoolWithAdmin,
16
+ findActiveSchoolAdminMembership,
17
+ findPendingInviteByToken,
18
+ findSchoolMembership,
19
+ findUserByIdForSchool,
20
+ getSchoolById,
21
+ getSchoolOverview,
22
+ listSchoolClasses,
23
+ listSchoolInvites,
24
+ listSchoolMembers,
25
+ listUserSchoolMemberships,
26
+ removeSchoolMembershipPreservingContent,
27
+ revokeSchoolInvite,
28
+ updateSchoolMembershipRole,
29
+ upsertSchoolMembership,
30
+ } from "../models/school.js";
31
+
32
+ async function requireSchoolAdmin(schoolId: string, userId: string) {
33
+ const membership = await findActiveSchoolAdminMembership(schoolId, userId);
34
+ if (!membership) {
35
+ throw new TRPCError({
36
+ code: "FORBIDDEN",
37
+ message: "Only school admins can perform this action",
38
+ });
39
+ }
40
+ return membership;
41
+ }
42
+
43
+ async function requireSchoolMember(schoolId: string, userId: string) {
44
+ const membership = await findSchoolMembership(schoolId, userId);
45
+ if (!membership || membership.status !== "ACTIVE") {
46
+ throw new TRPCError({
47
+ code: "FORBIDDEN",
48
+ message: "You are not a member of this school",
49
+ });
50
+ }
51
+ return membership;
52
+ }
53
+
54
+ export async function getCurrentSchool(userId: string, schoolId?: string) {
55
+ const memberships = await listUserSchoolMemberships(userId);
56
+ const activeMembership = schoolId
57
+ ? memberships.find((membership) => membership.schoolId === schoolId)
58
+ : memberships[0];
59
+
60
+ return {
61
+ activeSchool: activeMembership?.school ?? null,
62
+ activeRole: activeMembership?.role ?? null,
63
+ memberships,
64
+ };
65
+ }
66
+
67
+ export async function createSchoolRecord(
68
+ userId: string,
69
+ input: { name: string; subdomain?: string; logoId?: string }
70
+ ) {
71
+ const school = await createSchoolWithAdmin({
72
+ userId,
73
+ name: input.name,
74
+ subdomain: input.subdomain,
75
+ logoId: input.logoId,
76
+ });
77
+
78
+ return { school };
79
+ }
80
+
81
+ export async function getAdminOverview(userId: string, schoolId: string) {
82
+ await requireSchoolAdmin(schoolId, userId);
83
+ const school = await getSchoolOverview(schoolId);
84
+ if (!school) {
85
+ throw new TRPCError({ code: "NOT_FOUND", message: "School not found" });
86
+ }
87
+
88
+ const roleCounts = school.memberships.reduce(
89
+ (counts, membership) => {
90
+ counts[membership.role] += 1;
91
+ return counts;
92
+ },
93
+ { ADMIN: 0, TEACHER: 0, STUDENT: 0 } satisfies Record<SchoolMembershipRole, number>
94
+ );
95
+
96
+ return {
97
+ school: {
98
+ id: school.id,
99
+ name: school.name,
100
+ subdomain: school.subdomain,
101
+ counts: {
102
+ classes: school._count.classes,
103
+ members: school._count.memberships,
104
+ pendingInvites: school._count.invites,
105
+ ...roleCounts,
106
+ },
107
+ recentClasses: school.classes,
108
+ recentInvites: school.invites,
109
+ },
110
+ };
111
+ }
112
+
113
+ export async function listClasses(userId: string, schoolId: string) {
114
+ await requireSchoolAdmin(schoolId, userId);
115
+ return { classes: await listSchoolClasses(schoolId) };
116
+ }
117
+
118
+ export async function createSchoolClass(
119
+ userId: string,
120
+ input: {
121
+ schoolId: string;
122
+ name: string;
123
+ section: string;
124
+ subject: string;
125
+ color?: string;
126
+ teachers?: string[];
127
+ students?: string[];
128
+ }
129
+ ) {
130
+ await requireSchoolAdmin(input.schoolId, userId);
131
+ const createdClass = await prisma.class.create({
132
+ data: {
133
+ name: input.name,
134
+ section: input.section,
135
+ subject: input.subject,
136
+ color: input.color,
137
+ schoolId: input.schoolId,
138
+ teachers: input.teachers?.length
139
+ ? { connect: input.teachers.map((id) => ({ id })) }
140
+ : undefined,
141
+ students: input.students?.length
142
+ ? { connect: input.students.map((id) => ({ id })) }
143
+ : undefined,
144
+ },
145
+ include: { teachers: true, students: true },
146
+ });
147
+
148
+ return { class: createdClass };
149
+ }
150
+
151
+ export async function listMembers(userId: string, schoolId: string) {
152
+ await requireSchoolAdmin(schoolId, userId);
153
+ return { members: await listSchoolMembers(schoolId) };
154
+ }
155
+
156
+ export async function addMember(
157
+ userId: string,
158
+ input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }
159
+ ) {
160
+ await requireSchoolAdmin(input.schoolId, userId);
161
+ const membership = await upsertSchoolMembership({
162
+ schoolId: input.schoolId,
163
+ userId: input.memberUserId,
164
+ role: input.role,
165
+ });
166
+ return { membership };
167
+ }
168
+
169
+ export async function updateMemberRole(
170
+ userId: string,
171
+ input: { schoolId: string; memberUserId: string; role: SchoolMembershipRole }
172
+ ) {
173
+ await requireSchoolAdmin(input.schoolId, userId);
174
+ const current = await findSchoolMembership(input.schoolId, input.memberUserId);
175
+ if (!current) {
176
+ throw new TRPCError({ code: "NOT_FOUND", message: "Member not found" });
177
+ }
178
+
179
+ if (current.role === "ADMIN" && input.role !== "ADMIN") {
180
+ const adminCount = await countActiveAdmins(input.schoolId);
181
+ if (adminCount <= 1) {
182
+ throw new TRPCError({
183
+ code: "BAD_REQUEST",
184
+ message: "A school must have at least one active admin",
185
+ });
186
+ }
187
+ }
188
+
189
+ const membership = await updateSchoolMembershipRole(
190
+ input.schoolId,
191
+ input.memberUserId,
192
+ input.role
193
+ );
194
+ return { membership };
195
+ }
196
+
197
+ export async function removeMember(
198
+ userId: string,
199
+ input: { schoolId: string; memberUserId: string }
200
+ ) {
201
+ await requireSchoolAdmin(input.schoolId, userId);
202
+ const current = await findSchoolMembership(input.schoolId, input.memberUserId);
203
+ if (!current) {
204
+ throw new TRPCError({ code: "NOT_FOUND", message: "Member not found" });
205
+ }
206
+
207
+ if (current.role === "ADMIN" && current.status === "ACTIVE") {
208
+ const adminCount = await countActiveAdmins(input.schoolId);
209
+ if (adminCount <= 1) {
210
+ throw new TRPCError({
211
+ code: "BAD_REQUEST",
212
+ message: "A school must have at least one active admin",
213
+ });
214
+ }
215
+ }
216
+
217
+ await removeSchoolMembershipPreservingContent(input.schoolId, input.memberUserId);
218
+ return { success: true };
219
+ }
220
+
221
+ export async function listInvites(userId: string, schoolId: string) {
222
+ await requireSchoolAdmin(schoolId, userId);
223
+ return { invites: await listSchoolInvites(schoolId) };
224
+ }
225
+
226
+ export async function createInvite(
227
+ userId: string,
228
+ input: { schoolId: string; email: string; role: SchoolMembershipRole }
229
+ ) {
230
+ await requireSchoolAdmin(input.schoolId, userId);
231
+ const token = uuidv4();
232
+ const invite = await createSchoolInvite({
233
+ schoolId: input.schoolId,
234
+ invitedById: userId,
235
+ email: input.email,
236
+ role: input.role,
237
+ token,
238
+ expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 14),
239
+ });
240
+
241
+ try {
242
+ await sendMail({
243
+ from: "hello@studious.sh",
244
+ to: input.email,
245
+ subject: `Join ${invite.school.name} on Studious`,
246
+ text: `Click the link to join ${invite.school.name}: ${env.NEXT_PUBLIC_APP_URL}/school/invite/${token}`,
247
+ });
248
+ } catch (err) {
249
+ logger.error("Failed to send school invite email", {
250
+ schoolId: input.schoolId,
251
+ email: input.email,
252
+ err,
253
+ });
254
+ }
255
+
256
+ return { invite };
257
+ }
258
+
259
+ export async function revokeInvite(
260
+ userId: string,
261
+ input: { schoolId: string; inviteId: string }
262
+ ) {
263
+ await requireSchoolAdmin(input.schoolId, userId);
264
+ return { invite: await revokeSchoolInvite(input.inviteId, input.schoolId) };
265
+ }
266
+
267
+ export async function getInvite(token: string) {
268
+ const invite = await findPendingInviteByToken(token);
269
+ if (!invite || invite.status !== "PENDING") {
270
+ throw new TRPCError({ code: "NOT_FOUND", message: "Invite not found" });
271
+ }
272
+ if (invite.expiresAt < new Date()) {
273
+ throw new TRPCError({ code: "UNAUTHORIZED", message: "Invite expired" });
274
+ }
275
+ return {
276
+ invite: {
277
+ id: invite.id,
278
+ email: invite.email,
279
+ role: invite.role,
280
+ school: invite.school,
281
+ expiresAt: invite.expiresAt,
282
+ },
283
+ };
284
+ }
285
+
286
+ export async function acceptInvite(userId: string, token: string) {
287
+ const invite = await findPendingInviteByToken(token);
288
+ if (!invite || invite.status !== "PENDING") {
289
+ throw new TRPCError({ code: "NOT_FOUND", message: "Invite not found" });
290
+ }
291
+ if (invite.expiresAt < new Date()) {
292
+ throw new TRPCError({ code: "UNAUTHORIZED", message: "Invite expired" });
293
+ }
294
+
295
+ const user = await findUserByIdForSchool(userId);
296
+ if (!user) {
297
+ throw new TRPCError({ code: "NOT_FOUND", message: "User not found" });
298
+ }
299
+ if (user.email.toLowerCase() !== invite.email.toLowerCase()) {
300
+ throw new TRPCError({
301
+ code: "FORBIDDEN",
302
+ message: "This invite was sent to a different account",
303
+ });
304
+ }
305
+
306
+ const membership = await acceptSchoolInvite(invite.id, userId);
307
+ return { membership };
308
+ }
@@ -14,6 +14,7 @@ import {
14
14
  findWorksheetByIdForTeacher,
15
15
  findWorksheetsByClassId,
16
16
  createWorksheet,
17
+ duplicateWorksheet,
17
18
  updateWorksheet,
18
19
  deleteWorksheet,
19
20
  findQuestionsByWorksheetId,
@@ -123,6 +124,51 @@ export async function createWorksheetRecord(classId: string, name: string) {
123
124
  return createWorksheet({ classId, name });
124
125
  }
125
126
 
127
+ /**
128
+ * Duplicate a worksheet into another class. Caller must teach both the source worksheet's class
129
+ * and the target class.
130
+ */
131
+ export async function duplicateWorksheetRecord(
132
+ worksheetId: string,
133
+ classId: string,
134
+ name: string,
135
+ userId: string
136
+ ) {
137
+ const source = await findWorksheetByIdForTeacher(worksheetId, userId);
138
+ if (!source) {
139
+ throw new TRPCError({
140
+ code: "NOT_FOUND",
141
+ message:
142
+ "Worksheet not found or you are not a teacher of the class it belongs to",
143
+ });
144
+ }
145
+
146
+ const targetOk = await prisma.class.findFirst({
147
+ where: {
148
+ id: classId,
149
+ teachers: { some: { id: userId } },
150
+ },
151
+ select: { id: true },
152
+ });
153
+
154
+ if (!targetOk) {
155
+ throw new TRPCError({
156
+ code: "FORBIDDEN",
157
+ message: "You are not a teacher of the target class",
158
+ });
159
+ }
160
+
161
+ const created = await duplicateWorksheet(worksheetId, classId, name);
162
+ if (!created) {
163
+ throw new TRPCError({
164
+ code: "NOT_FOUND",
165
+ message: "Worksheet not found",
166
+ });
167
+ }
168
+
169
+ return created;
170
+ }
171
+
126
172
  /**
127
173
  * Create a worksheet by converting a PDF (URL) into structured questions.
128
174
  * Uses the `pdfToWorksheet` pipeline to do inference + persistence.
@@ -1,25 +0,0 @@
1
- interface notificationData {
2
- title: string;
3
- content: string;
4
- }
5
- export declare function sendNotification(receiver: string, data: notificationData): Promise<{
6
- id: string;
7
- title: string;
8
- content: string;
9
- createdAt: Date;
10
- read: boolean;
11
- senderId: string | null;
12
- receiverId: string;
13
- }>;
14
- export declare function sendNotifications(receiverIds: Array<string>, data: notificationData): Promise<import(".prisma/client").Prisma.BatchPayload>;
15
- export declare function markRead(id: string, read?: boolean): Promise<{
16
- id: string;
17
- title: string;
18
- content: string;
19
- createdAt: Date;
20
- read: boolean;
21
- senderId: string | null;
22
- receiverId: string;
23
- }>;
24
- export {};
25
- //# sourceMappingURL=notificationHandler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notificationHandler.d.ts","sourceRoot":"/","sources":["lib/notificationHandler.ts"],"names":[],"mappings":"AAEA,UAAU,gBAAgB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAA;CAClB;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB;;;;;;;;GAS9E;AAED,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,gBAAgB,yDASzF;AAED,wBAAsB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,OAAc;;;;;;;;GAM9D"}
@@ -1,32 +0,0 @@
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]="e0e01d37-e6fd-5751-a9d2-fece72c46422")}catch(e){}}();
3
- import { prisma } from "./prisma.js";
4
- export async function sendNotification(receiver, data) {
5
- const notification = await prisma.notification.create({
6
- data: {
7
- receiverId: receiver,
8
- title: data.title,
9
- content: data.content,
10
- },
11
- });
12
- return notification;
13
- }
14
- export async function sendNotifications(receiverIds, data) {
15
- const notifications = await prisma.notification.createMany({
16
- data: receiverIds.map(receiverId => ({
17
- receiverId: receiverId,
18
- title: data.title,
19
- content: data.content,
20
- })),
21
- });
22
- return notifications;
23
- }
24
- export async function markRead(id, read = true) {
25
- const notification = await prisma.notification.update({
26
- where: { id },
27
- data: { read: read },
28
- });
29
- return notification;
30
- }
31
- //# sourceMappingURL=notificationHandler.js.map
32
- //# debugId=e0e01d37-e6fd-5751-a9d2-fece72c46422
@@ -1 +0,0 @@
1
- {"version":3,"file":"notificationHandler.js","sources":["lib/notificationHandler.ts"],"sourceRoot":"/","sourcesContent":["import { prisma } from \"./prisma.js\";\n\ninterface notificationData {\n title: string,\n content: string\n}\n\nexport async function sendNotification(receiver: string, data: notificationData) {\n const notification = await prisma.notification.create({\n data: {\n receiverId: receiver,\n title: data.title,\n content: data.content,\n },\n });\n return notification;\n}\n\nexport async function sendNotifications(receiverIds: Array<string>, data: notificationData) {\n const notifications = await prisma.notification.createMany({\n data: receiverIds.map(receiverId => ({\n receiverId: receiverId,\n title: data.title,\n content: data.content,\n })),\n });\n return notifications;\n}\n\nexport async function markRead(id: string, read: boolean = true) {\n const notification = await prisma.notification.update({\n where: {id},\n data: {read: read},\n });\n return notification;\n}\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAOrC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,IAAsB;IAC3E,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;QAClD,IAAI,EAAE;YACF,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;SACxB;KACJ,CAAC,CAAC;IACH,OAAO,YAAY,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,WAA0B,EAAE,IAAsB;IACtF,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC;QACvD,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YACjC,UAAU,EAAE,UAAU;YACtB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;SACxB,CAAC,CAAC;KACN,CAAC,CAAC;IACH,OAAO,aAAa,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,EAAU,EAAE,OAAgB,IAAI;IAC3D,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;QAClD,KAAK,EAAE,EAAC,EAAE,EAAC;QACX,IAAI,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC;KACrB,CAAC,CAAC;IACH,OAAO,YAAY,CAAC;AACxB,CAAC","debug_id":"e0e01d37-e6fd-5751-a9d2-fece72c46422"}
@@ -1,21 +0,0 @@
1
- import { Assignment, Class, File, Section, User } from "@prisma/client";
2
- export declare const getBaseSystemPrompt: (context: Class, members: User[], assignments: Assignment[], files: File[], sections: Section[]) => string;
3
- /**
4
- * Generate labchat responses
5
- * Allow for the generation of the following:
6
- * - Assignment(s) either individual or bulk as an lesson / course plan.
7
- * - Worksheet(s) either individual or bulk as an lesson / course plan.
8
- * - Files (PDFs)
9
- * @param labChatId
10
- */
11
- /**
12
- * Generate and send AI introduction for lab chat
13
- * Uses the stored context directly from database
14
- */
15
- export declare const generateAndSendLabIntroduction: (labChatId: string, conversationId: string, contextString: string, subject: string) => Promise<void>;
16
- /**
17
- * Generate and send AI response to teacher message
18
- * Uses the stored context directly from database
19
- */
20
- export declare const generateAndSendLabResponse: (labChatId: string, teacherMessage: string, conversationId: string) => Promise<void>;
21
- //# sourceMappingURL=aiLabChat.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aiLabChat.d.ts","sourceRoot":"/","sources":["server/pipelines/aiLabChat.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AA4ExE,eAAO,MAAM,mBAAmB,GAAI,SAAS,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,aAAa,UAAU,EAAE,EAAE,OAAO,IAAI,EAAE,EAAE,UAAU,OAAO,EAAE,WA6BjI,CAAA;AAID;;;;;;;GAOG;AAoBH;;;GAGG;AACH,eAAO,MAAM,8BAA8B,GACvC,WAAW,MAAM,EACjB,gBAAgB,MAAM,EACtB,eAAe,MAAM,EACrB,SAAS,MAAM,KACd,OAAO,CAAC,IAAI,CA2Dd,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,GACrC,WAAW,MAAM,EACjB,gBAAgB,MAAM,EACtB,gBAAgB,MAAM,KACrB,OAAO,CAAC,IAAI,CAkSd,CAAA"}