@studious-lms/server 1.25.0 → 1.27.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.
- package/.env.example +3 -1
- package/.github/workflows/npm-publish.yml +1 -0
- package/AGENTS.md +84 -0
- package/dist/models/cloudStorage.d.ts +11 -0
- package/dist/models/cloudStorage.d.ts.map +1 -1
- package/dist/models/cloudStorage.js +18 -2
- package/dist/models/cloudStorage.js.map +1 -1
- package/dist/models/conversation.d.ts +1 -0
- package/dist/models/conversation.d.ts.map +1 -1
- package/dist/models/labChat.d.ts +40 -0
- package/dist/models/labChat.d.ts.map +1 -1
- package/dist/models/labChat.js +32 -2
- package/dist/models/labChat.js.map +1 -1
- package/dist/models/marketplace.d.ts +35 -0
- package/dist/models/marketplace.d.ts.map +1 -1
- package/dist/models/marketplace.js +9 -2
- package/dist/models/marketplace.js.map +1 -1
- package/dist/models/message.d.ts +3 -0
- package/dist/models/message.d.ts.map +1 -1
- package/dist/models/module.d.ts +228 -0
- package/dist/models/module.d.ts.map +1 -0
- package/dist/models/module.js +69 -0
- package/dist/models/module.js.map +1 -0
- package/dist/pipelines/aiLabChat.d.ts +2 -0
- package/dist/pipelines/aiLabChat.d.ts.map +1 -1
- package/dist/pipelines/aiLabChat.js +60 -16
- package/dist/pipelines/aiLabChat.js.map +1 -1
- package/dist/pipelines/aiLabChatContract.d.ts +170 -2
- package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
- package/dist/pipelines/aiLabChatContract.js +30 -2
- package/dist/pipelines/aiLabChatContract.js.map +1 -1
- package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
- package/dist/pipelines/aiNewtonChat.js +30 -5
- package/dist/pipelines/aiNewtonChat.js.map +1 -1
- package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
- package/dist/pipelines/gradeWorksheet.js +4 -2
- package/dist/pipelines/gradeWorksheet.js.map +1 -1
- package/dist/pipelines/labChatPrompt.d.ts +1 -1
- package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
- package/dist/pipelines/labChatPrompt.js +13 -14
- package/dist/pipelines/labChatPrompt.js.map +1 -1
- package/dist/routers/_app.d.ts +1185 -215
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/_app.js +4 -2
- package/dist/routers/_app.js.map +1 -1
- package/dist/routers/admin.d.ts +0 -1
- package/dist/routers/admin.d.ts.map +1 -1
- package/dist/routers/conversation.d.ts +1 -0
- package/dist/routers/conversation.d.ts.map +1 -1
- package/dist/routers/labChat.d.ts +10 -0
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/labChat.js +6 -3
- package/dist/routers/labChat.js.map +1 -1
- package/dist/routers/marketplace.d.ts +41 -0
- package/dist/routers/marketplace.d.ts.map +1 -1
- package/dist/routers/marketplace.js +13 -3
- package/dist/routers/marketplace.js.map +1 -1
- package/dist/routers/message.d.ts +37 -4
- package/dist/routers/message.d.ts.map +1 -1
- package/dist/routers/message.js +24 -7
- package/dist/routers/message.js.map +1 -1
- package/dist/routers/module.d.ts +345 -0
- package/dist/routers/module.d.ts.map +1 -0
- package/dist/routers/module.js +82 -0
- package/dist/routers/module.js.map +1 -0
- package/dist/routers/parent.d.ts +18 -0
- package/dist/routers/parent.d.ts.map +1 -1
- package/dist/routers/parent.js +10 -3
- package/dist/routers/parent.js.map +1 -1
- package/dist/routers/studentProgress.d.ts +44 -0
- package/dist/routers/studentProgress.d.ts.map +1 -1
- package/dist/routers/studentProgress.js +12 -3
- package/dist/routers/studentProgress.js.map +1 -1
- package/dist/routes/aiStream.js +32 -2
- package/dist/routes/aiStream.js.map +1 -1
- package/dist/seedDatabase.d.ts.map +1 -1
- package/dist/seedDatabase.js +107 -3
- package/dist/seedDatabase.js.map +1 -1
- package/dist/services/adminUser.d.ts +0 -1
- package/dist/services/adminUser.d.ts.map +1 -1
- package/dist/services/adminUser.js +7 -4
- package/dist/services/adminUser.js.map +1 -1
- package/dist/services/aiChatStream.d.ts +15 -0
- package/dist/services/aiChatStream.d.ts.map +1 -1
- package/dist/services/aiChatStream.js +144 -74
- package/dist/services/aiChatStream.js.map +1 -1
- package/dist/services/aiGeneration.d.ts +4 -0
- package/dist/services/aiGeneration.d.ts.map +1 -0
- package/dist/services/aiGeneration.js +88 -0
- package/dist/services/aiGeneration.js.map +1 -0
- package/dist/services/aiProposalTools.d.ts +4 -1
- package/dist/services/aiProposalTools.d.ts.map +1 -1
- package/dist/services/aiProposalTools.js +128 -3
- package/dist/services/aiProposalTools.js.map +1 -1
- package/dist/services/aiProposals.d.ts +70 -0
- package/dist/services/aiProposals.d.ts.map +1 -0
- package/dist/services/aiProposals.js +363 -0
- package/dist/services/aiProposals.js.map +1 -0
- package/dist/services/assignment.d.ts.map +1 -1
- package/dist/services/assignment.js +8 -3
- package/dist/services/assignment.js.map +1 -1
- package/dist/services/conversation.d.ts +1 -0
- package/dist/services/conversation.d.ts.map +1 -1
- package/dist/services/labChat.d.ts +10 -0
- package/dist/services/labChat.d.ts.map +1 -1
- package/dist/services/labChat.js +52 -3
- package/dist/services/labChat.js.map +1 -1
- package/dist/services/marketplace.d.ts +36 -0
- package/dist/services/marketplace.d.ts.map +1 -1
- package/dist/services/marketplace.js +30 -3
- package/dist/services/marketplace.js.map +1 -1
- package/dist/services/message.d.ts +24 -8
- package/dist/services/message.d.ts.map +1 -1
- package/dist/services/message.js +170 -117
- package/dist/services/message.js.map +1 -1
- package/dist/services/module.d.ts +288 -0
- package/dist/services/module.d.ts.map +1 -0
- package/dist/services/module.js +518 -0
- package/dist/services/module.js.map +1 -0
- package/dist/services/parentPortal.d.ts +14 -0
- package/dist/services/parentPortal.d.ts.map +1 -1
- package/dist/services/parentPortal.js +72 -2
- package/dist/services/parentPortal.js.map +1 -1
- package/dist/services/school.d.ts.map +1 -1
- package/dist/services/school.js +17 -5
- package/dist/services/school.js.map +1 -1
- package/dist/services/studentProgress.d.ts +50 -0
- package/dist/services/studentProgress.d.ts.map +1 -1
- package/dist/services/studentProgress.js +107 -2
- package/dist/services/studentProgress.js.map +1 -1
- package/dist/utils/inference.d.ts +10 -0
- package/dist/utils/inference.d.ts.map +1 -1
- package/dist/utils/inference.js +77 -2
- package/dist/utils/inference.js.map +1 -1
- package/dist/workers/processors/createRunJobWorker.js +17 -16
- package/dist/workers/processors/createRunJobWorker.js.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/20260708013000_add_modules/migration.sql +100 -0
- package/prisma/migrations/20260811130000_add_ai_message_feedback/migration.sql +7 -0
- package/prisma/schema.prisma +101 -0
- package/src/models/cloudStorage.ts +19 -0
- package/src/models/labChat.ts +34 -0
- package/src/models/marketplace.ts +16 -0
- package/src/models/module.ts +77 -0
- package/src/pipelines/aiLabChat.ts +79 -18
- package/src/pipelines/aiLabChatContract.ts +35 -0
- package/src/pipelines/aiNewtonChat.ts +34 -2
- package/src/pipelines/gradeWorksheet.ts +6 -0
- package/src/pipelines/labChatPrompt.ts +11 -12
- package/src/routers/_app.ts +2 -0
- package/src/routers/labChat.ts +5 -0
- package/src/routers/marketplace.ts +16 -0
- package/src/routers/message.ts +34 -5
- package/src/routers/module.ts +118 -0
- package/src/routers/parent.ts +11 -0
- package/src/routers/studentProgress.ts +15 -0
- package/src/routes/aiStream.ts +32 -0
- package/src/seedDatabase.ts +107 -2
- package/src/services/adminUser.ts +5 -2
- package/src/services/aiChatStream.ts +83 -7
- package/src/services/aiGeneration.ts +92 -0
- package/src/services/aiProposalTools.ts +166 -1
- package/src/services/aiProposals.ts +428 -0
- package/src/services/assignment.ts +12 -1
- package/src/services/labChat.ts +65 -0
- package/src/services/marketplace.ts +39 -0
- package/src/services/message.ts +205 -142
- package/src/services/module.ts +683 -0
- package/src/services/parentPortal.ts +85 -0
- package/src/services/school.ts +15 -3
- package/src/services/studentProgress.ts +135 -0
- package/src/utils/inference.ts +85 -0
- package/src/workers/processors/createRunJobWorker.ts +17 -17
- package/tests/unit/services/adminUser.test.ts +75 -0
- package/tests/unit/utils/adminPanelAccess.test.ts +26 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"labChat.js","sources":["services/labChat.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Lab chat service – AI-powered lab conversations. Create lab chats, post messages,\n * trigger AI responses, and broadcast via Pusher.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport { JobStatus } from \"@prisma/client\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { chatChannel, teacherChannel, pusher } from \"../lib/pusher.js\";\nimport {\n findClassWithTeachersForLab,\n findLabChatByMember,\n findLabChatByTeacher,\n findLabChatById,\n findClassMembership,\n findLabChatsByClass,\n findLabChatForPost,\n findLabChatForDelete,\n findMentionedMemberships,\n} from \"../models/labChat.js\";\nimport { getAIUserId, isAIUser } from \"../utils/aiUser.js\";\nimport { createPendingAIMessage } from \"../utils/inference.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { enqueueRunJob } from \"../workers/queues.js\";\nimport {\n claimMessageAttachments,\n ensureMessageHasContentOrAttachments,\n} from \"./message.js\";\nimport { messageFileSelect } from \"../models/message.js\";\n\n/** Create a lab chat with conversation and teacher members. Broadcasts via Pusher. */\nexport async function createLabChat(\n userId: string,\n input: { classId: string; title: string; context: string }\n) {\n const { classId, title, context } = input;\n\n const classWithTeachers = await findClassWithTeachersForLab(classId, userId);\n if (!classWithTeachers) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Not a teacher in this class\",\n });\n }\n\n try {\n JSON.parse(context);\n } catch {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Context must be valid JSON\",\n });\n }\n\n const result = await prisma.$transaction(async (tx) => {\n const conversation = await tx.conversation.create({\n data: {\n type: \"GROUP\",\n name: `Lab: ${title}`,\n displayInChat: false,\n },\n });\n\n const teacherMembers = classWithTeachers.teachers.map((t) => ({\n userId: t.id,\n role: \"ADMIN\" as const,\n }));\n\n await tx.conversationMember.createMany({\n data: teacherMembers.map((member) => ({\n userId: member.userId,\n conversationId: conversation.id,\n role: member.role,\n })),\n });\n\n const labChat = await tx.labChat.create({\n data: {\n title,\n context,\n classId,\n conversationId: conversation.id,\n createdById: userId,\n },\n include: {\n conversation: {\n include: {\n members: {\n include: {\n user: {\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 },\n createdBy: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n },\n },\n },\n },\n class: {\n select: {\n id: true,\n name: true,\n subject: true,\n section: true,\n },\n },\n },\n });\n\n return labChat;\n });\n\n // Create the AI introduction placeholder *outside* the transaction (the\n // helper triggers Pusher and we don't want a tx rollback to leave a\n // dangling broadcast). The pipeline will fill this row in.\n try {\n const aiPlaceholder = await createPendingAIMessage(result.conversationId);\n await enqueueRunJob(\n \"AI_LAB_CHAT\",\n { conversationId: result.conversationId, aiMessageId: aiPlaceholder.id },\n { classId, userId },\n );\n } catch (error) {\n logger.error(\"Failed to enqueue lab chat introduction\", {\n error,\n labChatId: result.id,\n conversationId: result.conversationId,\n });\n }\n\n try {\n await pusher.trigger(teacherChannel(classId), \"lab-chat-created\", {\n id: result.id,\n title: result.title,\n classId: result.classId,\n conversationId: result.conversationId,\n createdBy: result.createdBy,\n createdAt: result.createdAt,\n });\n } catch (error) {\n console.error(\"Failed to broadcast lab chat creation:\", error);\n }\n\n return result;\n}\n\nexport async function getLabChat(userId: string, labChatId: string) {\n let labChat = await findLabChatByMember(labChatId, userId);\n\n if (!labChat) {\n const labChatForTeacher = await findLabChatByTeacher(labChatId, userId);\n if (labChatForTeacher) {\n await prisma.conversationMember.create({\n data: {\n userId,\n conversationId: labChatForTeacher.conversation.id,\n role: \"ADMIN\",\n },\n });\n labChat = await findLabChatById(labChatId);\n }\n }\n\n if (!labChat) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Lab chat not found or access denied\",\n });\n }\n\n // The AI placeholder row IS the pending generation marker now — its\n // status flips PENDING → COMPLETED / FAILED as the pipeline runs.\n const pendingMessage = await prisma.message.findFirst({\n where: {\n conversationId: labChat.conversationId,\n status: JobStatus.PENDING,\n senderId: getAIUserId(),\n },\n orderBy: { createdAt: \"desc\" },\n select: { id: true },\n });\n\n return {\n ...labChat,\n pendingGenerationMessageId: pendingMessage?.id ?? null,\n };\n}\n\nexport async function listLabChats(userId: string, classId: string) {\n const classMembership = await findClassMembership(classId, userId);\n if (!classMembership) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Not a member of this class\",\n });\n }\n\n const labChats = await findLabChatsByClass(classId);\n return labChats.map((labChat) => ({\n id: labChat.id,\n title: labChat.title,\n classId: labChat.classId,\n conversationId: labChat.conversationId,\n createdBy: labChat.createdBy,\n createdAt: labChat.createdAt,\n updatedAt: labChat.updatedAt,\n lastMessage: labChat.conversation.messages[0] || null,\n messageCount: labChat.conversation._count.messages,\n }));\n}\n\nexport async function postToLabChat(\n userId: string,\n input: {\n labChatId: string;\n content: string;\n mentionedUserIds?: string[];\n fileIds?: string[];\n }\n) {\n const { labChatId, content, mentionedUserIds = [], fileIds = [] } = input;\n\n const labChat = await findLabChatForPost(labChatId, userId);\n if (!labChat) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Lab chat not found or access denied\",\n });\n }\n\n if (mentionedUserIds.length > 0) {\n const mentionedMemberships = await findMentionedMemberships(\n labChat.conversationId,\n mentionedUserIds\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 lab chat\",\n });\n }\n }\n\n ensureMessageHasContentOrAttachments(content, fileIds);\n const normalizedContent = content.trim();\n\n const result = await prisma.$transaction(async (tx) => {\n const message = await tx.message.create({\n data: {\n content: normalizedContent,\n senderId: userId,\n conversationId: labChat.conversationId,\n },\n });\n\n await claimMessageAttachments(\n tx,\n userId,\n labChat.conversationId,\n message.id,\n fileIds\n );\n\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 await tx.labChat.update({\n where: { id: labChatId },\n data: { updatedAt: new Date() },\n });\n\n return tx.message.findUniqueOrThrow({\n where: { id: message.id },\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 attachments: {\n select: messageFileSelect,\n },\n },\n });\n });\n\n try {\n await pusher.trigger(\n chatChannel(labChat.conversationId),\n \"new-message\",\n {\n id: result.id,\n content: result.content,\n senderId: result.senderId,\n conversationId: result.conversationId,\n status: result.status,\n createdAt: result.createdAt,\n sender: result.sender,\n attachments: result.attachments ?? [],\n mentionedUserIds,\n meta: {},\n }\n );\n } catch (error) {\n console.error(\"Failed to broadcast lab chat message:\", error);\n }\n\n if (!isAIUser(userId)) {\n // Create the AI placeholder post-tx so a transaction rollback can never\n // leave a dangling PENDING bubble. The placeholder broadcast IS the\n // \"AI is thinking...\" indicator inline in the chat; the teacher-channel\n // event below drives the lab list \"AI busy in this lab\" pill.\n let aiPlaceholderId: string | null = null;\n try {\n const aiPlaceholder = await createPendingAIMessage(labChat.conversationId);\n aiPlaceholderId = aiPlaceholder.id;\n } catch (error) {\n logger.error(\"Failed to create AI placeholder for lab response\", {\n error,\n labChatId,\n teacherMessageId: result.id,\n conversationId: labChat.conversationId,\n });\n }\n\n try {\n await pusher.trigger(teacherChannel(labChat.classId), \"lab-response-pending\", {\n labChatId,\n messageId: aiPlaceholderId ?? result.id,\n conversationId: labChat.conversationId,\n });\n } catch (error) {\n console.error(\"Failed to broadcast lab response pending:\", error);\n }\n\n if (aiPlaceholderId) {\n try {\n await enqueueRunJob(\n \"AI_LAB_CHAT\",\n { conversationId: labChat.conversationId, aiMessageId: aiPlaceholderId },\n { classId: labChat.classId, userId },\n );\n } catch (error) {\n logger.error(\"Failed to enqueue lab response\", {\n error,\n labChatId,\n aiMessageId: aiPlaceholderId,\n conversationId: labChat.conversationId,\n });\n }\n }\n }\n\n return {\n id: result.id,\n content: result.content,\n senderId: result.senderId,\n conversationId: result.conversationId,\n status: result.status,\n createdAt: result.createdAt,\n sender: result.sender,\n attachments: result.attachments ?? [],\n mentionedUserIds,\n };\n}\n\nexport async function deleteLabChat(userId: string, labChatId: string) {\n const labChat = await findLabChatForDelete(labChatId, userId);\n if (!labChat) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Lab chat not found or not the creator\",\n });\n }\n\n await prisma.$transaction(async (tx) => {\n await tx.mention.deleteMany({\n where: {\n message: {\n conversationId: labChat.conversationId,\n },\n },\n });\n\n await tx.message.deleteMany({\n where: {\n conversationId: labChat.conversationId,\n },\n });\n\n await tx.conversationMember.deleteMany({\n where: {\n conversationId: labChat.conversationId,\n },\n });\n\n await tx.labChat.delete({\n where: { id: labChatId },\n });\n\n await tx.conversation.delete({\n where: { id: labChat.conversationId },\n });\n });\n\n try {\n await pusher.trigger(teacherChannel(labChat.classId), \"lab-chat-deleted\", {\n labChatId,\n classId: labChat.classId,\n });\n } catch (error) {\n console.error(\"Failed to broadcast lab chat deletion:\", error);\n }\n\n return { success: true };\n}\n\n/**\n * Rerun the last AI response in a lab chat.\n *\n * The AI message bubble is reused (not deleted): we flip it back to\n * PENDING and clear its content so the existing message id stays stable\n * for the client. The pipeline then refills it.\n */\nexport async function rerunLastResponse(userId: string, labChatId: string) {\n const labChat = await findLabChatForPost(labChatId, userId);\n if (!labChat) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Lab chat not found or access denied\",\n });\n }\n\n const messages = await prisma.message.findMany({\n where: { conversationId: labChat.conversationId },\n orderBy: { createdAt: \"desc\" },\n take: 10,\n select: { id: true, content: true, senderId: true, createdAt: true },\n });\n\n const lastMessage = messages[0];\n if (!lastMessage) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"No messages to rerun\",\n });\n }\n\n if (!isAIUser(lastMessage.senderId)) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Last message is not from AI – nothing to rerun\",\n });\n }\n\n const teacherMessage = messages.find((m) => !isAIUser(m.senderId));\n if (!teacherMessage) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"No teacher message found to rerun from\",\n });\n }\n\n const reusedAiMessage = await prisma.message.update({\n where: { id: lastMessage.id },\n data: {\n content: \"\",\n status: JobStatus.PENDING,\n meta: {},\n },\n select: { id: true, conversationId: true, status: true, content: true, senderId: true, createdAt: true },\n });\n\n // Tell the chat UI the existing AI bubble is regenerating — content\n // cleared, status flipped back to PENDING, same id.\n try {\n await pusher.trigger(chatChannel(labChat.conversationId), \"message-updated\", {\n id: reusedAiMessage.id,\n content: reusedAiMessage.content,\n senderId: reusedAiMessage.senderId,\n conversationId: reusedAiMessage.conversationId,\n status: reusedAiMessage.status,\n createdAt: reusedAiMessage.createdAt,\n sender: {\n id: reusedAiMessage.senderId,\n username: 'Newton_AI',\n profile: { displayName: 'Newton AI', profilePicture: null },\n },\n mentionedUserIds: [],\n meta: {},\n attachments: [],\n });\n } catch (error) {\n console.error(\"Failed to broadcast AI message rerun reset:\", error);\n }\n try {\n await pusher.trigger(teacherChannel(labChat.classId), \"lab-response-pending\", {\n labChatId,\n messageId: reusedAiMessage.id,\n conversationId: labChat.conversationId,\n });\n } catch (error) {\n console.error(\"Failed to broadcast lab response pending:\", error);\n }\n\n try {\n await enqueueRunJob(\n \"AI_LAB_CHAT\",\n { conversationId: labChat.conversationId, aiMessageId: reusedAiMessage.id },\n { classId: labChat.classId, userId },\n );\n } catch (error) {\n logger.error(\"Failed to enqueue lab response rerun\", {\n error,\n labChatId,\n aiMessageId: reusedAiMessage.id,\n conversationId: labChat.conversationId,\n });\n }\n\n return { success: true };\n}\n"],"names":[],"mappings":"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","debug_id":"cc39fd7c-6d0d-5f42-9fd5-2f11bde711b3"}
|
|
1
|
+
{"version":3,"file":"labChat.js","sources":["services/labChat.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Lab chat service – AI-powered lab conversations. Create lab chats, post messages,\n * trigger AI responses, and broadcast via Pusher.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport { JobStatus } from \"@prisma/client\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { chatChannel, teacherChannel, pusher } from \"../lib/pusher.js\";\nimport {\n findClassWithTeachersForLab,\n findLabChatByMember,\n findLabChatByTeacher,\n findLabChatById,\n findClassContextForStarterPrompts,\n findClassMembership,\n findLabChatsByClass,\n findLabChatForPost,\n findLabChatForDelete,\n findMentionedMemberships,\n} from \"../models/labChat.js\";\nimport { getAIUserId, isAIUser } from \"../utils/aiUser.js\";\nimport { createPendingAIMessage } from \"../utils/inference.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { enqueueRunJob } from \"../workers/queues.js\";\nimport {\n claimMessageAttachments,\n ensureMessageHasContentOrAttachments,\n} from \"./message.js\";\nimport { messageFileSelect } from \"../models/message.js\";\n\n/** Create a lab chat with conversation and teacher members. Broadcasts via Pusher. */\nexport async function createLabChat(\n userId: string,\n input: { classId: string; title: string; context: string }\n) {\n const { classId, title, context } = input;\n\n const classWithTeachers = await findClassWithTeachersForLab(classId, userId);\n if (!classWithTeachers) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Not a teacher in this class\",\n });\n }\n\n try {\n JSON.parse(context);\n } catch {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Context must be valid JSON\",\n });\n }\n\n const result = await prisma.$transaction(async (tx) => {\n const conversation = await tx.conversation.create({\n data: {\n type: \"GROUP\",\n name: `Lab: ${title}`,\n displayInChat: false,\n },\n });\n\n const teacherMembers = classWithTeachers.teachers.map((t) => ({\n userId: t.id,\n role: \"ADMIN\" as const,\n }));\n\n await tx.conversationMember.createMany({\n data: teacherMembers.map((member) => ({\n userId: member.userId,\n conversationId: conversation.id,\n role: member.role,\n })),\n });\n\n const labChat = await tx.labChat.create({\n data: {\n title,\n context,\n classId,\n conversationId: conversation.id,\n createdById: userId,\n },\n include: {\n conversation: {\n include: {\n members: {\n include: {\n user: {\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 },\n createdBy: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n },\n },\n },\n },\n class: {\n select: {\n id: true,\n name: true,\n subject: true,\n section: true,\n },\n },\n },\n });\n\n return labChat;\n });\n\n // Create the AI introduction placeholder *outside* the transaction (the\n // helper triggers Pusher and we don't want a tx rollback to leave a\n // dangling broadcast). The pipeline will fill this row in.\n try {\n const aiPlaceholder = await createPendingAIMessage(result.conversationId);\n await enqueueRunJob(\n \"AI_LAB_CHAT\",\n { conversationId: result.conversationId, aiMessageId: aiPlaceholder.id },\n { classId, userId },\n );\n } catch (error) {\n logger.error(\"Failed to enqueue lab chat introduction\", {\n error,\n labChatId: result.id,\n conversationId: result.conversationId,\n });\n }\n\n try {\n await pusher.trigger(teacherChannel(classId), \"lab-chat-created\", {\n id: result.id,\n title: result.title,\n classId: result.classId,\n conversationId: result.conversationId,\n createdBy: result.createdBy,\n createdAt: result.createdAt,\n });\n } catch (error) {\n console.error(\"Failed to broadcast lab chat creation:\", error);\n }\n\n return result;\n}\n\nexport async function getLabChat(userId: string, labChatId: string) {\n let labChat = await findLabChatByMember(labChatId, userId);\n\n if (!labChat) {\n const labChatForTeacher = await findLabChatByTeacher(labChatId, userId);\n if (labChatForTeacher) {\n await prisma.conversationMember.create({\n data: {\n userId,\n conversationId: labChatForTeacher.conversation.id,\n role: \"ADMIN\",\n },\n });\n labChat = await findLabChatById(labChatId);\n }\n }\n\n if (!labChat) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Lab chat not found or access denied\",\n });\n }\n\n // The AI placeholder row IS the pending generation marker now — its\n // status flips PENDING → COMPLETED / FAILED as the pipeline runs.\n const pendingMessage = await prisma.message.findFirst({\n where: {\n conversationId: labChat.conversationId,\n status: JobStatus.PENDING,\n senderId: getAIUserId(),\n },\n orderBy: { createdAt: \"desc\" },\n select: { id: true },\n });\n\n return {\n ...labChat,\n pendingGenerationMessageId: pendingMessage?.id ?? null,\n };\n}\n\nconst GENERIC_STARTER_PROMPTS = [\n \"Create a quiz on this week's topic\",\n \"Draft a worksheet with 10 practice questions\",\n \"Plan a lesson with objectives and activities\",\n \"Suggest an assignment with a mark scheme\",\n];\n\nconst MAX_STARTER_PROMPTS = 5;\n\n/**\n * Suggest starter prompts for a class's lab chat, derived from recent\n * class context (upcoming due work, recent assignments, units, subject).\n * Pure heuristics — no LLM call — so it stays cheap and fast. Falls back\n * to generic defaults when the class has no usable context.\n */\nexport async function getStarterPrompts(userId: string, classId: string) {\n const classContext = await findClassContextForStarterPrompts(\n classId,\n userId\n );\n if (!classContext) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Not a teacher in this class\",\n });\n }\n\n const prompts: string[] = [];\n const now = new Date();\n\n const published = classContext.assignments.filter((a) => !a.inProgress);\n const upcoming = published\n .filter((a) => a.dueDate > now)\n .sort((a, b) => a.dueDate.getTime() - b.dueDate.getTime())[0];\n if (upcoming) {\n prompts.push(\n `Create a worksheet to help students prepare for \"${upcoming.title}\"`\n );\n }\n\n const recent = published.find((a) => a.title !== upcoming?.title);\n if (recent) {\n prompts.push(`Draft a quiz reviewing \"${recent.title}\"`);\n }\n\n const unit = classContext.sections[0];\n if (unit) {\n prompts.push(`Plan a lesson for the unit \"${unit.name}\"`);\n }\n\n if (classContext.subject) {\n prompts.push(\n `Suggest a ${classContext.subject} assignment with a mark scheme`\n );\n }\n\n for (const generic of GENERIC_STARTER_PROMPTS) {\n if (prompts.length >= 3) break;\n if (!prompts.includes(generic)) prompts.push(generic);\n }\n\n return { prompts: prompts.slice(0, MAX_STARTER_PROMPTS) };\n}\n\nexport async function listLabChats(userId: string, classId: string) {\n const classMembership = await findClassMembership(classId, userId);\n if (!classMembership) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Not a member of this class\",\n });\n }\n\n const labChats = await findLabChatsByClass(classId);\n return labChats.map((labChat) => ({\n id: labChat.id,\n title: labChat.title,\n classId: labChat.classId,\n conversationId: labChat.conversationId,\n createdBy: labChat.createdBy,\n createdAt: labChat.createdAt,\n updatedAt: labChat.updatedAt,\n lastMessage: labChat.conversation.messages[0] || null,\n messageCount: labChat.conversation._count.messages,\n }));\n}\n\nexport async function postToLabChat(\n userId: string,\n input: {\n labChatId: string;\n content: string;\n mentionedUserIds?: string[];\n fileIds?: string[];\n }\n) {\n const { labChatId, content, mentionedUserIds = [], fileIds = [] } = input;\n\n const labChat = await findLabChatForPost(labChatId, userId);\n if (!labChat) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Lab chat not found or access denied\",\n });\n }\n\n if (mentionedUserIds.length > 0) {\n const mentionedMemberships = await findMentionedMemberships(\n labChat.conversationId,\n mentionedUserIds\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 lab chat\",\n });\n }\n }\n\n ensureMessageHasContentOrAttachments(content, fileIds);\n const normalizedContent = content.trim();\n\n const result = await prisma.$transaction(async (tx) => {\n const message = await tx.message.create({\n data: {\n content: normalizedContent,\n senderId: userId,\n conversationId: labChat.conversationId,\n },\n });\n\n await claimMessageAttachments(\n tx,\n userId,\n labChat.conversationId,\n message.id,\n fileIds\n );\n\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 await tx.labChat.update({\n where: { id: labChatId },\n data: { updatedAt: new Date() },\n });\n\n return tx.message.findUniqueOrThrow({\n where: { id: message.id },\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 attachments: {\n select: messageFileSelect,\n },\n },\n });\n });\n\n try {\n await pusher.trigger(\n chatChannel(labChat.conversationId),\n \"new-message\",\n {\n id: result.id,\n content: result.content,\n senderId: result.senderId,\n conversationId: result.conversationId,\n status: result.status,\n createdAt: result.createdAt,\n sender: result.sender,\n attachments: result.attachments ?? [],\n mentionedUserIds,\n meta: {},\n }\n );\n } catch (error) {\n console.error(\"Failed to broadcast lab chat message:\", error);\n }\n\n if (!isAIUser(userId)) {\n // Create the AI placeholder post-tx so a transaction rollback can never\n // leave a dangling PENDING bubble. The placeholder broadcast IS the\n // \"AI is thinking...\" indicator inline in the chat; the teacher-channel\n // event below drives the lab list \"AI busy in this lab\" pill.\n let aiPlaceholderId: string | null = null;\n try {\n const aiPlaceholder = await createPendingAIMessage(labChat.conversationId);\n aiPlaceholderId = aiPlaceholder.id;\n } catch (error) {\n logger.error(\"Failed to create AI placeholder for lab response\", {\n error,\n labChatId,\n teacherMessageId: result.id,\n conversationId: labChat.conversationId,\n });\n }\n\n try {\n await pusher.trigger(teacherChannel(labChat.classId), \"lab-response-pending\", {\n labChatId,\n messageId: aiPlaceholderId ?? result.id,\n conversationId: labChat.conversationId,\n });\n } catch (error) {\n console.error(\"Failed to broadcast lab response pending:\", error);\n }\n\n if (aiPlaceholderId) {\n try {\n await enqueueRunJob(\n \"AI_LAB_CHAT\",\n { conversationId: labChat.conversationId, aiMessageId: aiPlaceholderId },\n { classId: labChat.classId, userId },\n );\n } catch (error) {\n logger.error(\"Failed to enqueue lab response\", {\n error,\n labChatId,\n aiMessageId: aiPlaceholderId,\n conversationId: labChat.conversationId,\n });\n }\n }\n }\n\n return {\n id: result.id,\n content: result.content,\n senderId: result.senderId,\n conversationId: result.conversationId,\n status: result.status,\n createdAt: result.createdAt,\n sender: result.sender,\n attachments: result.attachments ?? [],\n mentionedUserIds,\n };\n}\n\nexport async function deleteLabChat(userId: string, labChatId: string) {\n const labChat = await findLabChatForDelete(labChatId, userId);\n if (!labChat) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Lab chat not found or not the creator\",\n });\n }\n\n await prisma.$transaction(async (tx) => {\n await tx.mention.deleteMany({\n where: {\n message: {\n conversationId: labChat.conversationId,\n },\n },\n });\n\n await tx.message.deleteMany({\n where: {\n conversationId: labChat.conversationId,\n },\n });\n\n await tx.conversationMember.deleteMany({\n where: {\n conversationId: labChat.conversationId,\n },\n });\n\n await tx.labChat.delete({\n where: { id: labChatId },\n });\n\n await tx.conversation.delete({\n where: { id: labChat.conversationId },\n });\n });\n\n try {\n await pusher.trigger(teacherChannel(labChat.classId), \"lab-chat-deleted\", {\n labChatId,\n classId: labChat.classId,\n });\n } catch (error) {\n console.error(\"Failed to broadcast lab chat deletion:\", error);\n }\n\n return { success: true };\n}\n\n/**\n * Rerun the last AI response in a lab chat.\n *\n * The AI message bubble is reused (not deleted): we flip it back to\n * PENDING and clear its content so the existing message id stays stable\n * for the client. The pipeline then refills it.\n */\nexport async function rerunLastResponse(userId: string, labChatId: string) {\n const labChat = await findLabChatForPost(labChatId, userId);\n if (!labChat) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Lab chat not found or access denied\",\n });\n }\n\n const messages = await prisma.message.findMany({\n where: { conversationId: labChat.conversationId },\n orderBy: { createdAt: \"desc\" },\n take: 10,\n select: { id: true, content: true, senderId: true, createdAt: true },\n });\n\n const lastMessage = messages[0];\n if (!lastMessage) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"No messages to rerun\",\n });\n }\n\n if (!isAIUser(lastMessage.senderId)) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Last message is not from AI – nothing to rerun\",\n });\n }\n\n const teacherMessage = messages.find((m) => !isAIUser(m.senderId));\n if (!teacherMessage) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"No teacher message found to rerun from\",\n });\n }\n\n const reusedAiMessage = await prisma.message.update({\n where: { id: lastMessage.id },\n data: {\n content: \"\",\n status: JobStatus.PENDING,\n meta: {},\n },\n select: { id: true, conversationId: true, status: true, content: true, senderId: true, createdAt: true },\n });\n\n // Tell the chat UI the existing AI bubble is regenerating — content\n // cleared, status flipped back to PENDING, same id.\n try {\n await pusher.trigger(chatChannel(labChat.conversationId), \"message-updated\", {\n id: reusedAiMessage.id,\n content: reusedAiMessage.content,\n senderId: reusedAiMessage.senderId,\n conversationId: reusedAiMessage.conversationId,\n status: reusedAiMessage.status,\n createdAt: reusedAiMessage.createdAt,\n sender: {\n id: reusedAiMessage.senderId,\n username: 'Newton_AI',\n profile: { displayName: 'Newton AI', profilePicture: null },\n },\n mentionedUserIds: [],\n meta: {},\n attachments: [],\n });\n } catch (error) {\n console.error(\"Failed to broadcast AI message rerun reset:\", error);\n }\n try {\n await pusher.trigger(teacherChannel(labChat.classId), \"lab-response-pending\", {\n labChatId,\n messageId: reusedAiMessage.id,\n conversationId: labChat.conversationId,\n });\n } catch (error) {\n console.error(\"Failed to broadcast lab response pending:\", error);\n }\n\n try {\n await enqueueRunJob(\n \"AI_LAB_CHAT\",\n { conversationId: labChat.conversationId, aiMessageId: reusedAiMessage.id },\n { classId: labChat.classId, userId },\n );\n } catch (error) {\n logger.error(\"Failed to enqueue lab response rerun\", {\n error,\n labChatId,\n aiMessageId: reusedAiMessage.id,\n conversationId: labChat.conversationId,\n });\n }\n\n return { success: true };\n}\n"],"names":[],"mappings":"AAAA;;;GAGG;;;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,iCAAiC,EACjC,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,uBAAuB,EACvB,oCAAoC,GACrC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,KAA0D;IAE1D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAE1C,MAAM,iBAAiB,GAAG,MAAM,2BAA2B,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7E,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,6BAA6B;SACvC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,4BAA4B;SACtC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACpD,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC;YAChD,IAAI,EAAE;gBACJ,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,QAAQ,KAAK,EAAE;gBACrB,aAAa,EAAE,KAAK;aACrB;SACF,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5D,MAAM,EAAE,CAAC,CAAC,EAAE;YACZ,IAAI,EAAE,OAAgB;SACvB,CAAC,CAAC,CAAC;QAEJ,MAAM,EAAE,CAAC,kBAAkB,CAAC,UAAU,CAAC;YACrC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBACpC,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,cAAc,EAAE,YAAY,CAAC,EAAE;gBAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;aAClB,CAAC,CAAC;SACJ,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;YACtC,IAAI,EAAE;gBACJ,KAAK;gBACL,OAAO;gBACP,OAAO;gBACP,cAAc,EAAE,YAAY,CAAC,EAAE;gBAC/B,WAAW,EAAE,MAAM;aACpB;YACD,OAAO,EAAE;gBACP,YAAY,EAAE;oBACZ,OAAO,EAAE;wBACP,OAAO,EAAE;4BACP,OAAO,EAAE;gCACP,IAAI,EAAE;oCACJ,MAAM,EAAE;wCACN,EAAE,EAAE,IAAI;wCACR,QAAQ,EAAE,IAAI;wCACd,OAAO,EAAE;4CACP,MAAM,EAAE;gDACN,WAAW,EAAE,IAAI;gDACjB,cAAc,EAAE,IAAI;6CACrB;yCACF;qCACF;iCACF;6BACF;yBACF;qBACF;iBACF;gBACD,SAAS,EAAE;oBACT,MAAM,EAAE;wBACN,EAAE,EAAE,IAAI;wBACR,QAAQ,EAAE,IAAI;wBACd,OAAO,EAAE;4BACP,MAAM,EAAE;gCACN,WAAW,EAAE,IAAI;6BAClB;yBACF;qBACF;iBACF;gBACD,KAAK,EAAE;oBACL,MAAM,EAAE;wBACN,EAAE,EAAE,IAAI;wBACR,IAAI,EAAE,IAAI;wBACV,OAAO,EAAE,IAAI;wBACb,OAAO,EAAE,IAAI;qBACd;iBACF;aACF;SACF,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,wEAAwE;IACxE,oEAAoE;IACpE,2DAA2D;IAC3D,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,sBAAsB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC1E,MAAM,aAAa,CACjB,aAAa,EACb,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,EAAE,EACxE,EAAE,OAAO,EAAE,MAAM,EAAE,CACpB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE;YACtD,KAAK;YACL,SAAS,EAAE,MAAM,CAAC,EAAE;YACpB,cAAc,EAAE,MAAM,CAAC,cAAc;SACtC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,kBAAkB,EAAE;YAChE,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc,EAAE,SAAiB;IAChE,IAAI,OAAO,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAE3D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,iBAAiB,GAAG,MAAM,oBAAoB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACxE,IAAI,iBAAiB,EAAE,CAAC;YACtB,MAAM,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC;gBACrC,IAAI,EAAE;oBACJ,MAAM;oBACN,cAAc,EAAE,iBAAiB,CAAC,YAAY,CAAC,EAAE;oBACjD,IAAI,EAAE,OAAO;iBACd;aACF,CAAC,CAAC;YACH,OAAO,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,qCAAqC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,oEAAoE;IACpE,kEAAkE;IAClE,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;QACpD,KAAK,EAAE;YACL,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,MAAM,EAAE,SAAS,CAAC,OAAO;YACzB,QAAQ,EAAE,WAAW,EAAE;SACxB;QACD,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;QAC9B,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE;KACrB,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,OAAO;QACV,0BAA0B,EAAE,cAAc,EAAE,EAAE,IAAI,IAAI;KACvD,CAAC;AACJ,CAAC;AAED,MAAM,uBAAuB,GAAG;IAC9B,oCAAoC;IACpC,8CAA8C;IAC9C,8CAA8C;IAC9C,0CAA0C;CAC3C,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,OAAe;IACrE,MAAM,YAAY,GAAG,MAAM,iCAAiC,CAC1D,OAAO,EACP,MAAM,CACP,CAAC;IACF,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,6BAA6B;SACvC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,MAAM,SAAS,GAAG,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IACxE,MAAM,QAAQ,GAAG,SAAS;SACvB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC;SAC9B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CACV,oDAAoD,QAAQ,CAAC,KAAK,GAAG,CACtE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,KAAK,CAAC,CAAC;IAClE,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,2BAA2B,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtC,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,IAAI,CAAC,+BAA+B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CACV,aAAa,YAAY,CAAC,OAAO,gCAAgC,CAClE,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,uBAAuB,EAAE,CAAC;QAC9C,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;YAAE,MAAM;QAC/B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc,EAAE,OAAe;IAChE,MAAM,eAAe,GAAG,MAAM,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACnE,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,4BAA4B;SACtC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAChC,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI;QACrD,YAAY,EAAE,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ;KACnD,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,KAKC;IAED,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;IAE1E,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,qCAAqC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,oBAAoB,GAAG,MAAM,wBAAwB,CACzD,OAAO,CAAC,cAAc,EACtB,gBAAgB,CACjB,CAAC;QACF,IAAI,oBAAoB,CAAC,MAAM,KAAK,gBAAgB,CAAC,MAAM,EAAE,CAAC;YAC5D,MAAM,IAAI,SAAS,CAAC;gBAClB,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,uDAAuD;aACjE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,oCAAoC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,iBAAiB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAEzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACpD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;YACtC,IAAI,EAAE;gBACJ,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,MAAM;gBAChB,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC;SACF,CAAC,CAAC;QAEH,MAAM,uBAAuB,CAC3B,EAAE,EACF,MAAM,EACN,OAAO,CAAC,cAAc,EACtB,OAAO,CAAC,EAAE,EACV,OAAO,CACR,CAAC;QAEF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;gBAC1B,IAAI,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;oBAC/C,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,MAAM,EAAE,eAAe;iBACxB,CAAC,CAAC;aACJ,CAAC,CAAC;QACL,CAAC;QAED,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;YACtB,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;YACxB,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE;SAChC,CAAC,CAAC;QAEH,OAAO,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC;YAClC,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE;YACzB,OAAO,EAAE;gBACP,MAAM,EAAE;oBACN,MAAM,EAAE;wBACN,EAAE,EAAE,IAAI;wBACR,QAAQ,EAAE,IAAI;wBACd,OAAO,EAAE;4BACP,MAAM,EAAE;gCACN,WAAW,EAAE,IAAI;gCACjB,cAAc,EAAE,IAAI;6BACrB;yBACF;qBACF;iBACF;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,iBAAiB;iBAC1B;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAClB,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,EACnC,aAAa,EACb;YACE,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;YACrC,gBAAgB;YAChB,IAAI,EAAE,EAAE;SACT,CACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,wEAAwE;QACxE,oEAAoE;QACpE,wEAAwE;QACxE,8DAA8D;QAC9D,IAAI,eAAe,GAAkB,IAAI,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAC3E,eAAe,GAAG,aAAa,CAAC,EAAE,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,kDAAkD,EAAE;gBAC/D,KAAK;gBACL,SAAS;gBACT,gBAAgB,EAAE,MAAM,CAAC,EAAE;gBAC3B,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,sBAAsB,EAAE;gBAC5E,SAAS;gBACT,SAAS,EAAE,eAAe,IAAI,MAAM,CAAC,EAAE;gBACvC,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,KAAK,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,eAAe,EAAE,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,aAAa,CACjB,aAAa,EACb,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,EACxE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,CACrC,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE;oBAC7C,KAAK;oBACL,SAAS;oBACT,WAAW,EAAE,eAAe;oBAC5B,cAAc,EAAE,OAAO,CAAC,cAAc;iBACvC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;QACrC,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,SAAiB;IACnE,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,uCAAuC;SACjD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACrC,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;YAC1B,KAAK,EAAE;gBACL,OAAO,EAAE;oBACP,cAAc,EAAE,OAAO,CAAC,cAAc;iBACvC;aACF;SACF,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;YAC1B,KAAK,EAAE;gBACL,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC;SACF,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,kBAAkB,CAAC,UAAU,CAAC;YACrC,KAAK,EAAE;gBACL,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC;SACF,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;YACtB,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;SACzB,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC;YAC3B,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,cAAc,EAAE;SACtC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,kBAAkB,EAAE;YACxE,SAAS;YACT,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,SAAiB;IACvE,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,qCAAqC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC7C,KAAK,EAAE,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE;QACjD,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;QAC9B,IAAI,EAAE,EAAE;QACR,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;KACrE,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,sBAAsB;SAChC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,gDAAgD;SAC1D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,wCAAwC;SAClD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAClD,KAAK,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE;QAC7B,IAAI,EAAE;YACJ,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,SAAS,CAAC,OAAO;YACzB,IAAI,EAAE,EAAE;SACT;QACD,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;KACzG,CAAC,CAAC;IAEH,oEAAoE;IACpE,oDAAoD;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,iBAAiB,EAAE;YAC3E,EAAE,EAAE,eAAe,CAAC,EAAE;YACtB,OAAO,EAAE,eAAe,CAAC,OAAO;YAChC,QAAQ,EAAE,eAAe,CAAC,QAAQ;YAClC,cAAc,EAAE,eAAe,CAAC,cAAc;YAC9C,MAAM,EAAE,eAAe,CAAC,MAAM;YAC9B,SAAS,EAAE,eAAe,CAAC,SAAS;YACpC,MAAM,EAAE;gBACN,EAAE,EAAE,eAAe,CAAC,QAAQ;gBAC5B,QAAQ,EAAE,WAAW;gBACrB,OAAO,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE;aAC5D;YACD,gBAAgB,EAAE,EAAE;YACpB,IAAI,EAAE,EAAE;YACR,WAAW,EAAE,EAAE;SAChB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,KAAK,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,sBAAsB,EAAE;YAC5E,SAAS;YACT,SAAS,EAAE,eAAe,CAAC,EAAE;YAC7B,cAAc,EAAE,OAAO,CAAC,cAAc;SACvC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,KAAK,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,aAAa,CACjB,aAAa,EACb,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,WAAW,EAAE,eAAe,CAAC,EAAE,EAAE,EAC3E,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,CACrC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE;YACnD,KAAK;YACL,SAAS;YACT,WAAW,EAAE,eAAe,CAAC,EAAE;YAC/B,cAAc,EAAE,OAAO,CAAC,cAAc;SACvC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC","debug_id":"0ed3ef9f-a8ca-5f2e-90d9-3ceddc9af625"}
|
|
@@ -228,6 +228,42 @@ export declare function reportMarketplaceListing(userId: string, listingId: stri
|
|
|
228
228
|
reportCount: number;
|
|
229
229
|
isHidden: boolean;
|
|
230
230
|
}>;
|
|
231
|
+
export declare function updateMarketplaceListingDetails(userId: string, input: {
|
|
232
|
+
listingId: string;
|
|
233
|
+
title?: string;
|
|
234
|
+
description?: string | null;
|
|
235
|
+
visibility?: "SCHOOL" | "PUBLIC";
|
|
236
|
+
tags?: string[];
|
|
237
|
+
}): Promise<{
|
|
238
|
+
school: {
|
|
239
|
+
id: string;
|
|
240
|
+
name: string;
|
|
241
|
+
} | null;
|
|
242
|
+
author: {
|
|
243
|
+
id: string;
|
|
244
|
+
username: string;
|
|
245
|
+
profile: {
|
|
246
|
+
displayName: string | null;
|
|
247
|
+
} | null;
|
|
248
|
+
};
|
|
249
|
+
} & {
|
|
250
|
+
type: import(".prisma/client").$Enums.MarketplaceListingType;
|
|
251
|
+
payload: Prisma.JsonValue;
|
|
252
|
+
id: string;
|
|
253
|
+
createdAt: Date;
|
|
254
|
+
updatedAt: Date;
|
|
255
|
+
schoolId: string | null;
|
|
256
|
+
tags: string[];
|
|
257
|
+
description: string | null;
|
|
258
|
+
title: string;
|
|
259
|
+
worksheetId: string | null;
|
|
260
|
+
markSchemeId: string | null;
|
|
261
|
+
authorId: string;
|
|
262
|
+
fileId: string | null;
|
|
263
|
+
visibility: import(".prisma/client").$Enums.MarketplaceVisibility;
|
|
264
|
+
reportCount: number;
|
|
265
|
+
isHidden: boolean;
|
|
266
|
+
}>;
|
|
231
267
|
export declare function hideMarketplaceListing(userId: string, listingId: string, isHidden: boolean): Promise<{
|
|
232
268
|
school: {
|
|
233
269
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace.d.ts","sourceRoot":"/","sources":["services/marketplace.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,MAAM,EAEP,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"marketplace.d.ts","sourceRoot":"/","sources":["services/marketplace.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* worksheets, and files. Exercise/poll types are out of scope for B1 v1.
|
|
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]="
|
|
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]="89284a2e-a306-525a-955c-e752537ee131")}catch(e){}}();
|
|
7
7
|
import { TRPCError } from "@trpc/server";
|
|
8
8
|
import { v4 as uuidv4 } from "uuid";
|
|
9
9
|
import { prisma } from "../lib/prisma.js";
|
|
10
10
|
import { copyFile } from "../lib/googleCloudStorage.js";
|
|
11
11
|
import { classTeacherOrSchoolAdminWhere } from "../models/access.js";
|
|
12
12
|
import { findOrCreateScopeRoot } from "../models/cloudStorage.js";
|
|
13
|
-
import { createMarketplaceListing, deleteMarketplaceListing, findMarketplaceListingById, incrementMarketplaceReportCount, searchMarketplaceListings, setMarketplaceListingHidden, } from "../models/marketplace.js";
|
|
13
|
+
import { createMarketplaceListing, deleteMarketplaceListing, findMarketplaceListingById, incrementMarketplaceReportCount, searchMarketplaceListings, setMarketplaceListingHidden, updateMarketplaceListing, } from "../models/marketplace.js";
|
|
14
14
|
import { findActiveSchoolAdminMembership, findSchoolMembership, listUserSchoolMemberships, } from "../models/school.js";
|
|
15
15
|
import { duplicateWorksheetWithClient } from "../models/worksheet.js";
|
|
16
16
|
function normalizeTags(tags) {
|
|
@@ -514,6 +514,33 @@ export async function reportMarketplaceListing(userId, listingId) {
|
|
|
514
514
|
// C10 light stub — increment only; no reporter dedupe table yet.
|
|
515
515
|
return incrementMarketplaceReportCount(listingId);
|
|
516
516
|
}
|
|
517
|
+
export async function updateMarketplaceListingDetails(userId, input) {
|
|
518
|
+
const listing = await findMarketplaceListingById(input.listingId);
|
|
519
|
+
if (!listing) {
|
|
520
|
+
throw new TRPCError({ code: "NOT_FOUND", message: "Listing not found" });
|
|
521
|
+
}
|
|
522
|
+
const isAuthor = listing.authorId === userId;
|
|
523
|
+
const isSchoolAdmin = listing.schoolId != null &&
|
|
524
|
+
Boolean(await findActiveSchoolAdminMembership(listing.schoolId, userId));
|
|
525
|
+
if (!isAuthor && !isSchoolAdmin) {
|
|
526
|
+
throw new TRPCError({
|
|
527
|
+
code: "FORBIDDEN",
|
|
528
|
+
message: "Only the author or a school admin can edit this listing",
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
if (input.visibility === "SCHOOL" && listing.schoolId == null) {
|
|
532
|
+
throw new TRPCError({
|
|
533
|
+
code: "BAD_REQUEST",
|
|
534
|
+
message: "Listing has no school; it cannot use school visibility",
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
return updateMarketplaceListing(input.listingId, {
|
|
538
|
+
title: input.title,
|
|
539
|
+
description: input.description,
|
|
540
|
+
visibility: input.visibility,
|
|
541
|
+
tags: input.tags ? normalizeTags(input.tags) : undefined,
|
|
542
|
+
});
|
|
543
|
+
}
|
|
517
544
|
export async function hideMarketplaceListing(userId, listingId, isHidden) {
|
|
518
545
|
const listing = await findMarketplaceListingById(listingId);
|
|
519
546
|
if (!listing) {
|
|
@@ -628,4 +655,4 @@ export async function listPublishableSources(userId, input) {
|
|
|
628
655
|
return { markSchemes, worksheets, files };
|
|
629
656
|
}
|
|
630
657
|
//# sourceMappingURL=marketplace.js.map
|
|
631
|
-
//# debugId=
|
|
658
|
+
//# debugId=89284a2e-a306-525a-955c-e752537ee131
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace.js","sources":["services/marketplace.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Marketplace service — publish / search / import for shareable markschemes,\n * worksheets, and files. Exercise/poll types are out of scope for B1 v1.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport type {\n MarketplaceListingType,\n MarketplaceVisibility,\n Prisma,\n WorksheetQuestionType,\n} from \"@prisma/client\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { copyFile } from \"../lib/googleCloudStorage.js\";\nimport { classTeacherOrSchoolAdminWhere } from \"../models/access.js\";\nimport { findOrCreateScopeRoot } from \"../models/cloudStorage.js\";\nimport {\n createMarketplaceListing,\n deleteMarketplaceListing,\n findMarketplaceListingById,\n incrementMarketplaceReportCount,\n searchMarketplaceListings,\n setMarketplaceListingHidden,\n} from \"../models/marketplace.js\";\nimport {\n findActiveSchoolAdminMembership,\n findSchoolMembership,\n listUserSchoolMemberships,\n} from \"../models/school.js\";\nimport { duplicateWorksheetWithClient } from \"../models/worksheet.js\";\n\ntype MarkSchemePayload = {\n kind: \"MARKSCHEME\";\n name: string | null;\n structured: string;\n};\n\ntype WorksheetQuestionPayload = {\n type: WorksheetQuestionType;\n question: string;\n answer: string;\n options: Prisma.JsonValue;\n markScheme: Prisma.JsonValue;\n points: number;\n order: number | null;\n};\n\ntype WorksheetPayload = {\n kind: \"WORKSHEET\";\n name: string;\n questions: WorksheetQuestionPayload[];\n};\n\ntype FilePayload = {\n kind: \"FILE\";\n name: string;\n type: string;\n size: number | null;\n path: string;\n};\n\ntype ListingPayload = MarkSchemePayload | WorksheetPayload | FilePayload;\n\nfunction normalizeTags(tags?: string[]) {\n if (!tags?.length) return [];\n const seen = new Set<string>();\n const out: string[] = [];\n for (const raw of tags) {\n const tag = raw.trim().replace(/\\s+/g, \" \").slice(0, 40);\n if (!tag) continue;\n const key = tag.toLowerCase();\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(tag);\n if (out.length >= 12) break;\n }\n return out;\n}\n\nasync function requireActiveSchoolMember(schoolId: string, userId: string) {\n const membership = await findSchoolMembership(schoolId, userId);\n if (!membership || membership.status !== \"ACTIVE\") {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You are not a member of this school\",\n });\n }\n return membership;\n}\n\nasync function assertCanTeachClass(classId: string, userId: string) {\n const cls = await prisma.class.findFirst({\n where: { id: classId, ...classTeacherOrSchoolAdminWhere(userId) },\n select: { id: true, schoolId: true, departmentId: true },\n });\n if (!cls) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to use this class\",\n });\n }\n return cls;\n}\n\nasync function assertCanAccessListing(\n listing: NonNullable<Awaited<ReturnType<typeof findMarketplaceListingById>>>,\n userId: string\n) {\n if (listing.authorId === userId) return;\n if (listing.isHidden) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n if (listing.visibility === \"PUBLIC\") return;\n if (!listing.schoolId) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Listing is not available\" });\n }\n await requireActiveSchoolMember(listing.schoolId, userId);\n}\n\nfunction asPayload(raw: Prisma.JsonValue): ListingPayload {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Listing payload is invalid\",\n });\n }\n const kind = (raw as { kind?: string }).kind;\n if (kind === \"MARKSCHEME\" || kind === \"WORKSHEET\" || kind === \"FILE\") {\n return raw as ListingPayload;\n }\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Listing payload is invalid\",\n });\n}\n\nexport async function listMarketplace(\n userId: string,\n input: {\n type?: MarketplaceListingType;\n search?: string;\n tags?: string[];\n schoolId?: string;\n cursor?: string;\n limit?: number;\n }\n) {\n const memberships = await listUserSchoolMemberships(userId);\n if (\n input.schoolId &&\n !memberships.some((m) => m.schoolId === input.schoolId)\n ) {\n return { items: [], nextCursor: undefined };\n }\n const schoolIds = input.schoolId\n ? [input.schoolId]\n : memberships.map((m) => m.schoolId);\n\n return searchMarketplaceListings({\n schoolIds,\n scopeSchoolId: input.schoolId,\n type: input.type,\n search: input.search,\n tags: input.tags,\n cursor: input.cursor,\n limit: input.limit ?? 20,\n authorId: userId,\n });\n}\n\nexport async function getMarketplaceListing(userId: string, listingId: string) {\n const listing = await findMarketplaceListingById(listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n await assertCanAccessListing(listing, userId);\n return listing;\n}\n\nexport async function publishMarkSchemeListing(\n userId: string,\n input: {\n markSchemeId: string;\n title: string;\n description?: string;\n visibility: MarketplaceVisibility;\n schoolId?: string;\n tags?: string[];\n }\n) {\n const markScheme = await prisma.markScheme.findUnique({\n where: { id: input.markSchemeId },\n select: {\n id: true,\n name: true,\n structured: true,\n classId: true,\n departmentId: true,\n class: { select: { schoolId: true } },\n department: { select: { schoolId: true } },\n },\n });\n if (!markScheme) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Mark scheme not found\" });\n }\n\n let schoolId =\n input.schoolId ??\n markScheme.class?.schoolId ??\n markScheme.department?.schoolId ??\n null;\n\n if (markScheme.classId) {\n await assertCanTeachClass(markScheme.classId, userId);\n } else if (markScheme.departmentId && schoolId) {\n const admin = await findActiveSchoolAdminMembership(schoolId, userId);\n if (!admin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can publish department mark schemes\",\n });\n }\n } else {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Mark scheme is not scoped to a class or department\",\n });\n }\n\n if (input.visibility === \"SCHOOL\") {\n if (!schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"schoolId is required for SCHOOL visibility\",\n });\n }\n await requireActiveSchoolMember(schoolId, userId);\n } else if (schoolId) {\n await requireActiveSchoolMember(schoolId, userId);\n }\n\n const payload: MarkSchemePayload = {\n kind: \"MARKSCHEME\",\n name: markScheme.name,\n structured: markScheme.structured,\n };\n\n return createMarketplaceListing({\n type: \"MARKSCHEME\",\n title: input.title.trim(),\n description: input.description?.trim() || null,\n authorId: userId,\n schoolId,\n visibility: input.visibility,\n markSchemeId: markScheme.id,\n payload,\n tags: normalizeTags(input.tags),\n });\n}\n\nexport async function publishWorksheetListing(\n userId: string,\n input: {\n worksheetId: string;\n title: string;\n description?: string;\n visibility: MarketplaceVisibility;\n schoolId?: string;\n tags?: string[];\n }\n) {\n const worksheet = await prisma.worksheet.findFirst({\n where: {\n id: input.worksheetId,\n class: classTeacherOrSchoolAdminWhere(userId),\n },\n include: {\n questions: { orderBy: { order: \"asc\" } },\n class: { select: { schoolId: true } },\n },\n });\n if (!worksheet) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found or you don't have permission to publish it\",\n });\n }\n\n const schoolId = input.schoolId ?? worksheet.class?.schoolId ?? null;\n if (input.visibility === \"SCHOOL\") {\n if (!schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"schoolId is required for SCHOOL visibility\",\n });\n }\n await requireActiveSchoolMember(schoolId, userId);\n } else if (schoolId) {\n await requireActiveSchoolMember(schoolId, userId);\n }\n\n const payload: WorksheetPayload = {\n kind: \"WORKSHEET\",\n name: worksheet.name,\n questions: worksheet.questions.map((q) => ({\n type: q.type,\n question: q.question,\n answer: q.answer,\n options: q.options ?? {},\n markScheme: q.markScheme ?? {},\n points: q.points,\n order: q.order,\n })),\n };\n\n return createMarketplaceListing({\n type: \"WORKSHEET\",\n title: input.title.trim(),\n description: input.description?.trim() || null,\n authorId: userId,\n schoolId,\n visibility: input.visibility,\n worksheetId: worksheet.id,\n payload,\n tags: normalizeTags(input.tags),\n });\n}\n\nexport async function publishFileListing(\n userId: string,\n input: {\n fileId: string;\n title: string;\n description?: string;\n visibility: MarketplaceVisibility;\n schoolId?: string;\n tags?: string[];\n }\n) {\n const file = await prisma.file.findUnique({\n where: { id: input.fileId },\n select: {\n id: true,\n name: true,\n type: true,\n size: true,\n path: true,\n userId: true,\n folderId: true,\n uploadStatus: true,\n folder: {\n select: {\n classId: true,\n schoolStorageId: true,\n personalOwnerId: true,\n class: { select: { schoolId: true } },\n },\n },\n },\n });\n if (!file || file.uploadStatus === \"FAILED\" || file.uploadStatus === \"CANCELLED\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"File not found\" });\n }\n\n const isOwner = file.userId === userId;\n const isPersonal = file.folder?.personalOwnerId === userId;\n let canPublish = isOwner || isPersonal;\n let schoolId = input.schoolId ?? file.folder?.schoolStorageId ?? file.folder?.class?.schoolId ?? null;\n\n if (!canPublish && file.folder?.classId) {\n await assertCanTeachClass(file.folder.classId, userId);\n canPublish = true;\n }\n if (!canPublish && file.folder?.schoolStorageId) {\n const admin = await findActiveSchoolAdminMembership(\n file.folder.schoolStorageId,\n userId\n );\n if (!admin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to publish this file\",\n });\n }\n canPublish = true;\n schoolId = schoolId ?? file.folder.schoolStorageId;\n }\n if (!canPublish) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to publish this file\",\n });\n }\n\n if (input.visibility === \"SCHOOL\") {\n if (!schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"schoolId is required for SCHOOL visibility\",\n });\n }\n await requireActiveSchoolMember(schoolId, userId);\n } else if (schoolId) {\n await requireActiveSchoolMember(schoolId, userId);\n }\n\n const payload: FilePayload = {\n kind: \"FILE\",\n name: file.name,\n type: file.type,\n size: file.size,\n path: file.path,\n };\n\n return createMarketplaceListing({\n type: \"FILE\",\n title: input.title.trim(),\n description: input.description?.trim() || null,\n authorId: userId,\n schoolId,\n visibility: input.visibility,\n fileId: file.id,\n payload,\n tags: normalizeTags(input.tags),\n });\n}\n\n/**\n * Import a listing into the caller's workspace:\n * - MARKSCHEME → class mark scheme (or department template when departmentId given)\n * - WORKSHEET → class worksheet copy\n * - FILE → personal / class / school folder copy (GCS object copied)\n */\nexport async function importMarketplaceListing(\n userId: string,\n input: {\n listingId: string;\n classId?: string;\n departmentId?: string;\n folderId?: string;\n name?: string;\n }\n) {\n const listing = await findMarketplaceListingById(input.listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n await assertCanAccessListing(listing, userId);\n\n const payload = asPayload(listing.payload);\n const name = input.name?.trim();\n\n if (listing.type === \"MARKSCHEME\") {\n if (payload.kind !== \"MARKSCHEME\") {\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Mark scheme payload mismatch\",\n });\n }\n if (input.departmentId) {\n const department = await prisma.department.findUnique({\n where: { id: input.departmentId },\n select: { id: true, schoolId: true },\n });\n if (!department) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Department not found\" });\n }\n const admin = await findActiveSchoolAdminMembership(\n department.schoolId,\n userId\n );\n if (!admin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can import into a department\",\n });\n }\n return {\n type: \"MARKSCHEME\" as const,\n markScheme: await prisma.markScheme.create({\n data: {\n department: { connect: { id: department.id } },\n name: name || payload.name || listing.title,\n structured: payload.structured,\n },\n select: { id: true, name: true, departmentId: true, classId: true },\n }),\n };\n }\n if (!input.classId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"classId is required to import a mark scheme\",\n });\n }\n await assertCanTeachClass(input.classId, userId);\n return {\n type: \"MARKSCHEME\" as const,\n markScheme: await prisma.markScheme.create({\n data: {\n class: { connect: { id: input.classId } },\n name: name || payload.name || listing.title,\n structured: payload.structured,\n },\n select: { id: true, name: true, departmentId: true, classId: true },\n }),\n };\n }\n\n if (listing.type === \"WORKSHEET\") {\n if (payload.kind !== \"WORKSHEET\") {\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Worksheet payload mismatch\",\n });\n }\n if (!input.classId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"classId is required to import a worksheet\",\n });\n }\n await assertCanTeachClass(input.classId, userId);\n\n // Prefer live source clone when still available; otherwise rebuild from snapshot.\n if (listing.worksheetId) {\n const created = await prisma.$transaction((tx) =>\n duplicateWorksheetWithClient(\n tx,\n listing.worksheetId!,\n input.classId!,\n name || payload.name || listing.title\n )\n );\n if (created) {\n return { type: \"WORKSHEET\" as const, worksheet: created };\n }\n }\n\n const created = await prisma.worksheet.create({\n data: {\n classId: input.classId,\n name: name || payload.name || listing.title,\n questions: {\n create: payload.questions.map((q) => ({\n type: q.type,\n question: q.question,\n answer: q.answer,\n options: (q.options as Prisma.InputJsonValue) ?? {},\n markScheme: (q.markScheme as Prisma.InputJsonValue) ?? {},\n points: q.points,\n order: q.order,\n })),\n },\n },\n select: { id: true, name: true, classId: true },\n });\n return { type: \"WORKSHEET\" as const, worksheet: created };\n }\n\n if (listing.type === \"FILE\") {\n if (payload.kind !== \"FILE\") {\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"File payload mismatch\",\n });\n }\n\n let targetFolderId = input.folderId;\n if (!targetFolderId) {\n if (input.classId) {\n await assertCanTeachClass(input.classId, userId);\n const root = await findOrCreateScopeRoot({\n kind: \"CLASS\",\n classId: input.classId,\n });\n targetFolderId = root.id;\n } else {\n const root = await findOrCreateScopeRoot({\n kind: \"PERSONAL\",\n userId,\n });\n targetFolderId = root.id;\n }\n } else {\n const folder = await prisma.folder.findUnique({\n where: { id: targetFolderId },\n select: {\n id: true,\n classId: true,\n schoolStorageId: true,\n personalOwnerId: true,\n },\n });\n if (!folder) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Folder not found\" });\n }\n if (folder.personalOwnerId && folder.personalOwnerId !== userId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to import into this folder\",\n });\n }\n if (folder.classId) {\n await assertCanTeachClass(folder.classId, userId);\n }\n if (folder.schoolStorageId) {\n const admin = await findActiveSchoolAdminMembership(\n folder.schoolStorageId,\n userId\n );\n if (!admin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can import into school storage\",\n });\n }\n }\n }\n\n const ext = payload.name.includes(\".\")\n ? payload.name.slice(payload.name.lastIndexOf(\".\"))\n : \"\";\n const newPath = `marketplace/${uuidv4()}${ext}`;\n await copyFile(payload.path, newPath);\n\n const created = await prisma.file.create({\n data: {\n name: name || payload.name || listing.title,\n type: payload.type,\n size: payload.size ?? undefined,\n path: newPath,\n userId,\n folderId: targetFolderId,\n uploadStatus: \"COMPLETED\",\n uploadedAt: new Date(),\n },\n select: { id: true, name: true, folderId: true, path: true, type: true },\n });\n return { type: \"FILE\" as const, file: created };\n }\n\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Unsupported listing type\",\n });\n}\n\nexport async function reportMarketplaceListing(\n userId: string,\n listingId: string\n) {\n const listing = await findMarketplaceListingById(listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n await assertCanAccessListing(listing, userId);\n // C10 light stub — increment only; no reporter dedupe table yet.\n return incrementMarketplaceReportCount(listingId);\n}\n\nexport async function hideMarketplaceListing(\n userId: string,\n listingId: string,\n isHidden: boolean\n) {\n const listing = await findMarketplaceListingById(listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n const isAuthor = listing.authorId === userId;\n const isSchoolAdmin =\n listing.schoolId != null &&\n Boolean(await findActiveSchoolAdminMembership(listing.schoolId, userId));\n if (!isAuthor && !isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the author or a school admin can hide this listing\",\n });\n }\n return setMarketplaceListingHidden(listingId, isHidden);\n}\n\nexport async function unpublishMarketplaceListing(\n userId: string,\n listingId: string\n) {\n const listing = await findMarketplaceListingById(listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n if (listing.authorId !== userId) {\n const isSchoolAdmin =\n listing.schoolId != null &&\n Boolean(await findActiveSchoolAdminMembership(listing.schoolId, userId));\n if (!isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the author or a school admin can unpublish this listing\",\n });\n }\n await setMarketplaceListingHidden(listingId, true);\n return { success: true as const, deleted: false };\n }\n const result = await deleteMarketplaceListing(listingId, userId);\n return { success: true as const, deleted: result.count > 0 };\n}\n\n/** Publishable sources for the current user (for the publish dialog). */\nexport async function listPublishableSources(\n userId: string,\n input: { classId?: string; schoolId?: string }\n) {\n const classFilter = input.classId\n ? { id: input.classId, ...classTeacherOrSchoolAdminWhere(userId) }\n : classTeacherOrSchoolAdminWhere(userId);\n\n const [markSchemes, worksheets, files] = await Promise.all([\n prisma.markScheme.findMany({\n where: {\n OR: [\n { class: classFilter },\n ...(input.schoolId\n ? [\n {\n department: {\n schoolId: input.schoolId,\n school: {\n memberships: {\n some: {\n userId,\n role: \"ADMIN\" as const,\n status: \"ACTIVE\" as const,\n },\n },\n },\n },\n },\n ]\n : []),\n ],\n },\n select: {\n id: true,\n name: true,\n classId: true,\n departmentId: true,\n class: { select: { name: true } },\n department: { select: { name: true } },\n },\n take: 50,\n orderBy: { id: \"desc\" },\n }),\n prisma.worksheet.findMany({\n where: { class: classFilter },\n select: {\n id: true,\n name: true,\n classId: true,\n class: { select: { name: true } },\n _count: { select: { questions: true } },\n },\n take: 50,\n orderBy: { updatedAt: \"desc\" },\n }),\n prisma.file.findMany({\n where: {\n uploadStatus: \"COMPLETED\",\n OR: [\n { userId },\n { folder: { personalOwnerId: userId } },\n ...(input.classId\n ? [{ folder: { classId: input.classId, class: classFilter } }]\n : [{ folder: { class: classFilter } }]),\n ],\n },\n select: {\n id: true,\n name: true,\n type: true,\n size: true,\n folderId: true,\n },\n take: 50,\n orderBy: { uploadedAt: \"desc\" },\n }),\n ]);\n\n return { markSchemes, worksheets, files };\n}\n"],"names":[],"mappings":"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","debug_id":"b0ba201b-83d8-5de3-a820-a6105cef2863"}
|
|
1
|
+
{"version":3,"file":"marketplace.js","sources":["services/marketplace.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Marketplace service — publish / search / import for shareable markschemes,\n * worksheets, and files. Exercise/poll types are out of scope for B1 v1.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport type {\n MarketplaceListingType,\n MarketplaceVisibility,\n Prisma,\n WorksheetQuestionType,\n} from \"@prisma/client\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { copyFile } from \"../lib/googleCloudStorage.js\";\nimport { classTeacherOrSchoolAdminWhere } from \"../models/access.js\";\nimport { findOrCreateScopeRoot } from \"../models/cloudStorage.js\";\nimport {\n createMarketplaceListing,\n deleteMarketplaceListing,\n findMarketplaceListingById,\n incrementMarketplaceReportCount,\n searchMarketplaceListings,\n setMarketplaceListingHidden,\n updateMarketplaceListing,\n} from \"../models/marketplace.js\";\nimport {\n findActiveSchoolAdminMembership,\n findSchoolMembership,\n listUserSchoolMemberships,\n} from \"../models/school.js\";\nimport { duplicateWorksheetWithClient } from \"../models/worksheet.js\";\n\ntype MarkSchemePayload = {\n kind: \"MARKSCHEME\";\n name: string | null;\n structured: string;\n};\n\ntype WorksheetQuestionPayload = {\n type: WorksheetQuestionType;\n question: string;\n answer: string;\n options: Prisma.JsonValue;\n markScheme: Prisma.JsonValue;\n points: number;\n order: number | null;\n};\n\ntype WorksheetPayload = {\n kind: \"WORKSHEET\";\n name: string;\n questions: WorksheetQuestionPayload[];\n};\n\ntype FilePayload = {\n kind: \"FILE\";\n name: string;\n type: string;\n size: number | null;\n path: string;\n};\n\ntype ListingPayload = MarkSchemePayload | WorksheetPayload | FilePayload;\n\nfunction normalizeTags(tags?: string[]) {\n if (!tags?.length) return [];\n const seen = new Set<string>();\n const out: string[] = [];\n for (const raw of tags) {\n const tag = raw.trim().replace(/\\s+/g, \" \").slice(0, 40);\n if (!tag) continue;\n const key = tag.toLowerCase();\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(tag);\n if (out.length >= 12) break;\n }\n return out;\n}\n\nasync function requireActiveSchoolMember(schoolId: string, userId: string) {\n const membership = await findSchoolMembership(schoolId, userId);\n if (!membership || membership.status !== \"ACTIVE\") {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You are not a member of this school\",\n });\n }\n return membership;\n}\n\nasync function assertCanTeachClass(classId: string, userId: string) {\n const cls = await prisma.class.findFirst({\n where: { id: classId, ...classTeacherOrSchoolAdminWhere(userId) },\n select: { id: true, schoolId: true, departmentId: true },\n });\n if (!cls) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to use this class\",\n });\n }\n return cls;\n}\n\nasync function assertCanAccessListing(\n listing: NonNullable<Awaited<ReturnType<typeof findMarketplaceListingById>>>,\n userId: string\n) {\n if (listing.authorId === userId) return;\n if (listing.isHidden) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n if (listing.visibility === \"PUBLIC\") return;\n if (!listing.schoolId) {\n throw new TRPCError({ code: \"FORBIDDEN\", message: \"Listing is not available\" });\n }\n await requireActiveSchoolMember(listing.schoolId, userId);\n}\n\nfunction asPayload(raw: Prisma.JsonValue): ListingPayload {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Listing payload is invalid\",\n });\n }\n const kind = (raw as { kind?: string }).kind;\n if (kind === \"MARKSCHEME\" || kind === \"WORKSHEET\" || kind === \"FILE\") {\n return raw as ListingPayload;\n }\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Listing payload is invalid\",\n });\n}\n\nexport async function listMarketplace(\n userId: string,\n input: {\n type?: MarketplaceListingType;\n search?: string;\n tags?: string[];\n schoolId?: string;\n cursor?: string;\n limit?: number;\n }\n) {\n const memberships = await listUserSchoolMemberships(userId);\n if (\n input.schoolId &&\n !memberships.some((m) => m.schoolId === input.schoolId)\n ) {\n return { items: [], nextCursor: undefined };\n }\n const schoolIds = input.schoolId\n ? [input.schoolId]\n : memberships.map((m) => m.schoolId);\n\n return searchMarketplaceListings({\n schoolIds,\n scopeSchoolId: input.schoolId,\n type: input.type,\n search: input.search,\n tags: input.tags,\n cursor: input.cursor,\n limit: input.limit ?? 20,\n authorId: userId,\n });\n}\n\nexport async function getMarketplaceListing(userId: string, listingId: string) {\n const listing = await findMarketplaceListingById(listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n await assertCanAccessListing(listing, userId);\n return listing;\n}\n\nexport async function publishMarkSchemeListing(\n userId: string,\n input: {\n markSchemeId: string;\n title: string;\n description?: string;\n visibility: MarketplaceVisibility;\n schoolId?: string;\n tags?: string[];\n }\n) {\n const markScheme = await prisma.markScheme.findUnique({\n where: { id: input.markSchemeId },\n select: {\n id: true,\n name: true,\n structured: true,\n classId: true,\n departmentId: true,\n class: { select: { schoolId: true } },\n department: { select: { schoolId: true } },\n },\n });\n if (!markScheme) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Mark scheme not found\" });\n }\n\n let schoolId =\n input.schoolId ??\n markScheme.class?.schoolId ??\n markScheme.department?.schoolId ??\n null;\n\n if (markScheme.classId) {\n await assertCanTeachClass(markScheme.classId, userId);\n } else if (markScheme.departmentId && schoolId) {\n const admin = await findActiveSchoolAdminMembership(schoolId, userId);\n if (!admin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can publish department mark schemes\",\n });\n }\n } else {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Mark scheme is not scoped to a class or department\",\n });\n }\n\n if (input.visibility === \"SCHOOL\") {\n if (!schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"schoolId is required for SCHOOL visibility\",\n });\n }\n await requireActiveSchoolMember(schoolId, userId);\n } else if (schoolId) {\n await requireActiveSchoolMember(schoolId, userId);\n }\n\n const payload: MarkSchemePayload = {\n kind: \"MARKSCHEME\",\n name: markScheme.name,\n structured: markScheme.structured,\n };\n\n return createMarketplaceListing({\n type: \"MARKSCHEME\",\n title: input.title.trim(),\n description: input.description?.trim() || null,\n authorId: userId,\n schoolId,\n visibility: input.visibility,\n markSchemeId: markScheme.id,\n payload,\n tags: normalizeTags(input.tags),\n });\n}\n\nexport async function publishWorksheetListing(\n userId: string,\n input: {\n worksheetId: string;\n title: string;\n description?: string;\n visibility: MarketplaceVisibility;\n schoolId?: string;\n tags?: string[];\n }\n) {\n const worksheet = await prisma.worksheet.findFirst({\n where: {\n id: input.worksheetId,\n class: classTeacherOrSchoolAdminWhere(userId),\n },\n include: {\n questions: { orderBy: { order: \"asc\" } },\n class: { select: { schoolId: true } },\n },\n });\n if (!worksheet) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found or you don't have permission to publish it\",\n });\n }\n\n const schoolId = input.schoolId ?? worksheet.class?.schoolId ?? null;\n if (input.visibility === \"SCHOOL\") {\n if (!schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"schoolId is required for SCHOOL visibility\",\n });\n }\n await requireActiveSchoolMember(schoolId, userId);\n } else if (schoolId) {\n await requireActiveSchoolMember(schoolId, userId);\n }\n\n const payload: WorksheetPayload = {\n kind: \"WORKSHEET\",\n name: worksheet.name,\n questions: worksheet.questions.map((q) => ({\n type: q.type,\n question: q.question,\n answer: q.answer,\n options: q.options ?? {},\n markScheme: q.markScheme ?? {},\n points: q.points,\n order: q.order,\n })),\n };\n\n return createMarketplaceListing({\n type: \"WORKSHEET\",\n title: input.title.trim(),\n description: input.description?.trim() || null,\n authorId: userId,\n schoolId,\n visibility: input.visibility,\n worksheetId: worksheet.id,\n payload,\n tags: normalizeTags(input.tags),\n });\n}\n\nexport async function publishFileListing(\n userId: string,\n input: {\n fileId: string;\n title: string;\n description?: string;\n visibility: MarketplaceVisibility;\n schoolId?: string;\n tags?: string[];\n }\n) {\n const file = await prisma.file.findUnique({\n where: { id: input.fileId },\n select: {\n id: true,\n name: true,\n type: true,\n size: true,\n path: true,\n userId: true,\n folderId: true,\n uploadStatus: true,\n folder: {\n select: {\n classId: true,\n schoolStorageId: true,\n personalOwnerId: true,\n class: { select: { schoolId: true } },\n },\n },\n },\n });\n if (!file || file.uploadStatus === \"FAILED\" || file.uploadStatus === \"CANCELLED\") {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"File not found\" });\n }\n\n const isOwner = file.userId === userId;\n const isPersonal = file.folder?.personalOwnerId === userId;\n let canPublish = isOwner || isPersonal;\n let schoolId = input.schoolId ?? file.folder?.schoolStorageId ?? file.folder?.class?.schoolId ?? null;\n\n if (!canPublish && file.folder?.classId) {\n await assertCanTeachClass(file.folder.classId, userId);\n canPublish = true;\n }\n if (!canPublish && file.folder?.schoolStorageId) {\n const admin = await findActiveSchoolAdminMembership(\n file.folder.schoolStorageId,\n userId\n );\n if (!admin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to publish this file\",\n });\n }\n canPublish = true;\n schoolId = schoolId ?? file.folder.schoolStorageId;\n }\n if (!canPublish) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to publish this file\",\n });\n }\n\n if (input.visibility === \"SCHOOL\") {\n if (!schoolId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"schoolId is required for SCHOOL visibility\",\n });\n }\n await requireActiveSchoolMember(schoolId, userId);\n } else if (schoolId) {\n await requireActiveSchoolMember(schoolId, userId);\n }\n\n const payload: FilePayload = {\n kind: \"FILE\",\n name: file.name,\n type: file.type,\n size: file.size,\n path: file.path,\n };\n\n return createMarketplaceListing({\n type: \"FILE\",\n title: input.title.trim(),\n description: input.description?.trim() || null,\n authorId: userId,\n schoolId,\n visibility: input.visibility,\n fileId: file.id,\n payload,\n tags: normalizeTags(input.tags),\n });\n}\n\n/**\n * Import a listing into the caller's workspace:\n * - MARKSCHEME → class mark scheme (or department template when departmentId given)\n * - WORKSHEET → class worksheet copy\n * - FILE → personal / class / school folder copy (GCS object copied)\n */\nexport async function importMarketplaceListing(\n userId: string,\n input: {\n listingId: string;\n classId?: string;\n departmentId?: string;\n folderId?: string;\n name?: string;\n }\n) {\n const listing = await findMarketplaceListingById(input.listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n await assertCanAccessListing(listing, userId);\n\n const payload = asPayload(listing.payload);\n const name = input.name?.trim();\n\n if (listing.type === \"MARKSCHEME\") {\n if (payload.kind !== \"MARKSCHEME\") {\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Mark scheme payload mismatch\",\n });\n }\n if (input.departmentId) {\n const department = await prisma.department.findUnique({\n where: { id: input.departmentId },\n select: { id: true, schoolId: true },\n });\n if (!department) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Department not found\" });\n }\n const admin = await findActiveSchoolAdminMembership(\n department.schoolId,\n userId\n );\n if (!admin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can import into a department\",\n });\n }\n return {\n type: \"MARKSCHEME\" as const,\n markScheme: await prisma.markScheme.create({\n data: {\n department: { connect: { id: department.id } },\n name: name || payload.name || listing.title,\n structured: payload.structured,\n },\n select: { id: true, name: true, departmentId: true, classId: true },\n }),\n };\n }\n if (!input.classId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"classId is required to import a mark scheme\",\n });\n }\n await assertCanTeachClass(input.classId, userId);\n return {\n type: \"MARKSCHEME\" as const,\n markScheme: await prisma.markScheme.create({\n data: {\n class: { connect: { id: input.classId } },\n name: name || payload.name || listing.title,\n structured: payload.structured,\n },\n select: { id: true, name: true, departmentId: true, classId: true },\n }),\n };\n }\n\n if (listing.type === \"WORKSHEET\") {\n if (payload.kind !== \"WORKSHEET\") {\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Worksheet payload mismatch\",\n });\n }\n if (!input.classId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"classId is required to import a worksheet\",\n });\n }\n await assertCanTeachClass(input.classId, userId);\n\n // Prefer live source clone when still available; otherwise rebuild from snapshot.\n if (listing.worksheetId) {\n const created = await prisma.$transaction((tx) =>\n duplicateWorksheetWithClient(\n tx,\n listing.worksheetId!,\n input.classId!,\n name || payload.name || listing.title\n )\n );\n if (created) {\n return { type: \"WORKSHEET\" as const, worksheet: created };\n }\n }\n\n const created = await prisma.worksheet.create({\n data: {\n classId: input.classId,\n name: name || payload.name || listing.title,\n questions: {\n create: payload.questions.map((q) => ({\n type: q.type,\n question: q.question,\n answer: q.answer,\n options: (q.options as Prisma.InputJsonValue) ?? {},\n markScheme: (q.markScheme as Prisma.InputJsonValue) ?? {},\n points: q.points,\n order: q.order,\n })),\n },\n },\n select: { id: true, name: true, classId: true },\n });\n return { type: \"WORKSHEET\" as const, worksheet: created };\n }\n\n if (listing.type === \"FILE\") {\n if (payload.kind !== \"FILE\") {\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"File payload mismatch\",\n });\n }\n\n let targetFolderId = input.folderId;\n if (!targetFolderId) {\n if (input.classId) {\n await assertCanTeachClass(input.classId, userId);\n const root = await findOrCreateScopeRoot({\n kind: \"CLASS\",\n classId: input.classId,\n });\n targetFolderId = root.id;\n } else {\n const root = await findOrCreateScopeRoot({\n kind: \"PERSONAL\",\n userId,\n });\n targetFolderId = root.id;\n }\n } else {\n const folder = await prisma.folder.findUnique({\n where: { id: targetFolderId },\n select: {\n id: true,\n classId: true,\n schoolStorageId: true,\n personalOwnerId: true,\n },\n });\n if (!folder) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Folder not found\" });\n }\n if (folder.personalOwnerId && folder.personalOwnerId !== userId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You don't have permission to import into this folder\",\n });\n }\n if (folder.classId) {\n await assertCanTeachClass(folder.classId, userId);\n }\n if (folder.schoolStorageId) {\n const admin = await findActiveSchoolAdminMembership(\n folder.schoolStorageId,\n userId\n );\n if (!admin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only school admins can import into school storage\",\n });\n }\n }\n }\n\n const ext = payload.name.includes(\".\")\n ? payload.name.slice(payload.name.lastIndexOf(\".\"))\n : \"\";\n const newPath = `marketplace/${uuidv4()}${ext}`;\n await copyFile(payload.path, newPath);\n\n const created = await prisma.file.create({\n data: {\n name: name || payload.name || listing.title,\n type: payload.type,\n size: payload.size ?? undefined,\n path: newPath,\n userId,\n folderId: targetFolderId,\n uploadStatus: \"COMPLETED\",\n uploadedAt: new Date(),\n },\n select: { id: true, name: true, folderId: true, path: true, type: true },\n });\n return { type: \"FILE\" as const, file: created };\n }\n\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Unsupported listing type\",\n });\n}\n\nexport async function reportMarketplaceListing(\n userId: string,\n listingId: string\n) {\n const listing = await findMarketplaceListingById(listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n await assertCanAccessListing(listing, userId);\n // C10 light stub — increment only; no reporter dedupe table yet.\n return incrementMarketplaceReportCount(listingId);\n}\n\nexport async function updateMarketplaceListingDetails(\n userId: string,\n input: {\n listingId: string;\n title?: string;\n description?: string | null;\n visibility?: \"SCHOOL\" | \"PUBLIC\";\n tags?: string[];\n }\n) {\n const listing = await findMarketplaceListingById(input.listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n const isAuthor = listing.authorId === userId;\n const isSchoolAdmin =\n listing.schoolId != null &&\n Boolean(await findActiveSchoolAdminMembership(listing.schoolId, userId));\n if (!isAuthor && !isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the author or a school admin can edit this listing\",\n });\n }\n if (input.visibility === \"SCHOOL\" && listing.schoolId == null) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Listing has no school; it cannot use school visibility\",\n });\n }\n return updateMarketplaceListing(input.listingId, {\n title: input.title,\n description: input.description,\n visibility: input.visibility,\n tags: input.tags ? normalizeTags(input.tags) : undefined,\n });\n}\n\nexport async function hideMarketplaceListing(\n userId: string,\n listingId: string,\n isHidden: boolean\n) {\n const listing = await findMarketplaceListingById(listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n const isAuthor = listing.authorId === userId;\n const isSchoolAdmin =\n listing.schoolId != null &&\n Boolean(await findActiveSchoolAdminMembership(listing.schoolId, userId));\n if (!isAuthor && !isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the author or a school admin can hide this listing\",\n });\n }\n return setMarketplaceListingHidden(listingId, isHidden);\n}\n\nexport async function unpublishMarketplaceListing(\n userId: string,\n listingId: string\n) {\n const listing = await findMarketplaceListingById(listingId);\n if (!listing) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Listing not found\" });\n }\n if (listing.authorId !== userId) {\n const isSchoolAdmin =\n listing.schoolId != null &&\n Boolean(await findActiveSchoolAdminMembership(listing.schoolId, userId));\n if (!isSchoolAdmin) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only the author or a school admin can unpublish this listing\",\n });\n }\n await setMarketplaceListingHidden(listingId, true);\n return { success: true as const, deleted: false };\n }\n const result = await deleteMarketplaceListing(listingId, userId);\n return { success: true as const, deleted: result.count > 0 };\n}\n\n/** Publishable sources for the current user (for the publish dialog). */\nexport async function listPublishableSources(\n userId: string,\n input: { classId?: string; schoolId?: string }\n) {\n const classFilter = input.classId\n ? { id: input.classId, ...classTeacherOrSchoolAdminWhere(userId) }\n : classTeacherOrSchoolAdminWhere(userId);\n\n const [markSchemes, worksheets, files] = await Promise.all([\n prisma.markScheme.findMany({\n where: {\n OR: [\n { class: classFilter },\n ...(input.schoolId\n ? [\n {\n department: {\n schoolId: input.schoolId,\n school: {\n memberships: {\n some: {\n userId,\n role: \"ADMIN\" as const,\n status: \"ACTIVE\" as const,\n },\n },\n },\n },\n },\n ]\n : []),\n ],\n },\n select: {\n id: true,\n name: true,\n classId: true,\n departmentId: true,\n class: { select: { name: true } },\n department: { select: { name: true } },\n },\n take: 50,\n orderBy: { id: \"desc\" },\n }),\n prisma.worksheet.findMany({\n where: { class: classFilter },\n select: {\n id: true,\n name: true,\n classId: true,\n class: { select: { name: true } },\n _count: { select: { questions: true } },\n },\n take: 50,\n orderBy: { updatedAt: \"desc\" },\n }),\n prisma.file.findMany({\n where: {\n uploadStatus: \"COMPLETED\",\n OR: [\n { userId },\n { folder: { personalOwnerId: userId } },\n ...(input.classId\n ? [{ folder: { classId: input.classId, class: classFilter } }]\n : [{ folder: { class: classFilter } }]),\n ],\n },\n select: {\n id: true,\n name: true,\n type: true,\n size: true,\n folderId: true,\n },\n take: 50,\n orderBy: { uploadedAt: \"desc\" },\n }),\n ]);\n\n return { markSchemes, worksheets, files };\n}\n"],"names":[],"mappings":"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","debug_id":"89284a2e-a306-525a-955c-e752537ee131"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Broadcasts real-time updates via Pusher.
|
|
4
4
|
*/
|
|
5
5
|
import type { AppTransactionClient } from "../lib/prisma.js";
|
|
6
|
+
import { type AiMessageFeedback } from "@prisma/client";
|
|
6
7
|
export declare function ensureMessageHasContentOrAttachments(content: string, fileIds?: string[]): void;
|
|
7
8
|
export declare function claimMessageAttachments(tx: AppTransactionClient, userId: string, conversationId: string, messageId: string, fileIds?: string[]): Promise<void>;
|
|
8
9
|
export declare function getMessageUploadUrls(userId: string, input: {
|
|
@@ -43,6 +44,7 @@ export declare function listMessages(userId: string, input: {
|
|
|
43
44
|
} | null;
|
|
44
45
|
};
|
|
45
46
|
status: import(".prisma/client").$Enums.JobStatus | null;
|
|
47
|
+
aiFeedback: import(".prisma/client").$Enums.AiMessageFeedback | null;
|
|
46
48
|
attachments: {
|
|
47
49
|
path: string;
|
|
48
50
|
type: string;
|
|
@@ -133,14 +135,6 @@ export declare function deleteMessage(userId: string, messageId: string): Promis
|
|
|
133
135
|
success: boolean;
|
|
134
136
|
messageId: string;
|
|
135
137
|
}>;
|
|
136
|
-
/** Mark an AI-suggested item as created. Stores in message meta for fast reads. */
|
|
137
|
-
export declare function markSuggestionCreated(userId: string, input: {
|
|
138
|
-
messageId: string;
|
|
139
|
-
type: "assignment" | "worksheet" | "section";
|
|
140
|
-
index: number;
|
|
141
|
-
}): Promise<{
|
|
142
|
-
success: boolean;
|
|
143
|
-
}>;
|
|
144
138
|
export declare function markAsRead(userId: string, conversationId: string): Promise<{
|
|
145
139
|
success: boolean;
|
|
146
140
|
}>;
|
|
@@ -151,4 +145,26 @@ export declare function getUnreadCount(userId: string, conversationId: string):
|
|
|
151
145
|
unreadCount: number;
|
|
152
146
|
unreadMentionCount: number;
|
|
153
147
|
}>;
|
|
148
|
+
/**
|
|
149
|
+
* Regenerate an AI response in a lab or Newton chat.
|
|
150
|
+
*
|
|
151
|
+
* The existing AI bubble is reused (not deleted): the row flips back to
|
|
152
|
+
* PENDING with cleared content/meta/feedback so the message id stays stable
|
|
153
|
+
* for the client, then the matching pipeline refills it. Only the latest
|
|
154
|
+
* message in the conversation can be regenerated — the pipelines build
|
|
155
|
+
* their context from the messages preceding the placeholder.
|
|
156
|
+
*/
|
|
157
|
+
export declare function regenerateAIResponse(userId: string, messageId: string): Promise<{
|
|
158
|
+
success: boolean;
|
|
159
|
+
messageId: string;
|
|
160
|
+
}>;
|
|
161
|
+
/** Record (or clear) thumbs up/down feedback on an AI message. */
|
|
162
|
+
export declare function setAIMessageFeedback(userId: string, input: {
|
|
163
|
+
messageId: string;
|
|
164
|
+
feedback: AiMessageFeedback | null;
|
|
165
|
+
}): Promise<{
|
|
166
|
+
success: boolean;
|
|
167
|
+
messageId: string;
|
|
168
|
+
feedback: import(".prisma/client").$Enums.AiMessageFeedback | null;
|
|
169
|
+
}>;
|
|
154
170
|
//# sourceMappingURL=message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"/","sources":["services/message.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"/","sources":["services/message.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAAa,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAqBnE,wBAAgB,oCAAoC,CAClD,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,MAAM,EAAO,QAQvB;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,oBAAoB,EACxB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,MAAM,EAAO,iBA2BvB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD,8DAmBF;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;;;GAuCF;AAED,oEAAoE;AACpE,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkCyB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;;GAMlD;AAED,oFAAoF;AACpF,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkIF;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;;;;;;;;;;;;;;;;GAqHF;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;GAuDpE;AAGD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;;GA+BtE;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM;;GAgCvB;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM;;;GA8BvB;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;GA4I3E;AAED,kEAAkE;AAClE,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACpC;;;;GA0CF"}
|