@studious-lms/server 1.5.0 → 1.7.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/dist/index.js +15 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/config/cors.d.ts.map +1 -1
- package/dist/lib/config/cors.js +3 -2
- package/dist/lib/config/cors.js.map +1 -1
- package/dist/lib/pusher.d.ts +7 -1
- package/dist/lib/pusher.d.ts.map +1 -1
- package/dist/lib/pusher.js +9 -3
- package/dist/lib/pusher.js.map +1 -1
- package/dist/models/attendance.d.ts +16 -7
- package/dist/models/attendance.d.ts.map +1 -1
- package/dist/models/attendance.js +17 -2
- package/dist/models/attendance.js.map +1 -1
- package/dist/models/conversation.d.ts +33 -17
- package/dist/models/conversation.d.ts.map +1 -1
- package/dist/models/conversation.js +50 -2
- package/dist/models/conversation.js.map +1 -1
- package/dist/pipelines/aiLabChat.d.ts +20 -9
- package/dist/pipelines/aiLabChat.d.ts.map +1 -1
- package/dist/pipelines/aiLabChat.js +62 -74
- package/dist/pipelines/aiLabChat.js.map +1 -1
- package/dist/pipelines/aiNewtonChat.d.ts +13 -4
- package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
- package/dist/pipelines/aiNewtonChat.js +39 -27
- package/dist/pipelines/aiNewtonChat.js.map +1 -1
- package/dist/pipelines/pdfToWorksheet.d.ts +31 -2
- package/dist/pipelines/pdfToWorksheet.d.ts.map +1 -1
- package/dist/pipelines/pdfToWorksheet.js +160 -28
- package/dist/pipelines/pdfToWorksheet.js.map +1 -1
- package/dist/routers/_app.d.ts +48 -4
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +64 -4
- package/dist/routers/assignment.js.map +1 -1
- package/dist/routers/conversation.d.ts +15 -0
- package/dist/routers/conversation.d.ts.map +1 -1
- package/dist/routers/conversation.js +6 -3
- package/dist/routers/conversation.js.map +1 -1
- package/dist/routers/labChat.d.ts +1 -0
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/message.d.ts +3 -0
- package/dist/routers/message.d.ts.map +1 -1
- package/dist/routers/newtonChat.d.ts +1 -0
- package/dist/routers/newtonChat.d.ts.map +1 -1
- package/dist/routers/worksheet.d.ts +4 -2
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/routers/worksheet.js +16 -6
- package/dist/routers/worksheet.js.map +1 -1
- package/dist/services/announcement.js +4 -4
- package/dist/services/announcement.js.map +1 -1
- package/dist/services/assignment.d.ts.map +1 -1
- package/dist/services/assignment.js +16 -6
- package/dist/services/assignment.js.map +1 -1
- package/dist/services/attendance.d.ts.map +1 -1
- package/dist/services/attendance.js +68 -4
- package/dist/services/attendance.js.map +1 -1
- package/dist/services/conversation.d.ts +16 -0
- package/dist/services/conversation.d.ts.map +1 -1
- package/dist/services/conversation.js +22 -3
- package/dist/services/conversation.js.map +1 -1
- package/dist/services/labChat.d.ts +8 -1
- package/dist/services/labChat.d.ts.map +1 -1
- package/dist/services/labChat.js +101 -42
- package/dist/services/labChat.js.map +1 -1
- package/dist/services/message.d.ts +3 -0
- package/dist/services/message.d.ts.map +1 -1
- package/dist/services/message.js +8 -2
- package/dist/services/message.js.map +1 -1
- package/dist/services/newtonChat.d.ts +1 -0
- package/dist/services/newtonChat.d.ts.map +1 -1
- package/dist/services/newtonChat.js +40 -17
- package/dist/services/newtonChat.js.map +1 -1
- package/dist/services/worksheet.d.ts +15 -6
- package/dist/services/worksheet.d.ts.map +1 -1
- package/dist/services/worksheet.js +58 -12
- package/dist/services/worksheet.js.map +1 -1
- package/dist/utils/inference.d.ts +50 -1
- package/dist/utils/inference.d.ts.map +1 -1
- package/dist/utils/inference.js +167 -2
- package/dist/utils/inference.js.map +1 -1
- package/dist/workers/index.js +13 -3
- package/dist/workers/index.js.map +1 -1
- package/dist/workers/processors/aiLabChat.d.ts +7 -0
- package/dist/workers/processors/aiLabChat.d.ts.map +1 -0
- package/dist/workers/processors/aiLabChat.js +52 -0
- package/dist/workers/processors/aiLabChat.js.map +1 -0
- package/dist/workers/processors/aiNewtonChat.d.ts +7 -0
- package/dist/workers/processors/aiNewtonChat.d.ts.map +1 -0
- package/dist/workers/processors/aiNewtonChat.js +57 -0
- package/dist/workers/processors/aiNewtonChat.js.map +1 -0
- package/dist/workers/processors/createRunJobWorker.d.ts +46 -0
- package/dist/workers/processors/createRunJobWorker.d.ts.map +1 -0
- package/dist/workers/processors/createRunJobWorker.js +118 -0
- package/dist/workers/processors/createRunJobWorker.js.map +1 -0
- package/dist/workers/processors/gradeWorksheet.d.ts +6 -0
- package/dist/workers/processors/gradeWorksheet.d.ts.map +1 -0
- package/dist/workers/processors/gradeWorksheet.js +19 -0
- package/dist/workers/processors/gradeWorksheet.js.map +1 -0
- package/dist/workers/processors/pdfToWorksheet.d.ts +5 -6
- package/dist/workers/processors/pdfToWorksheet.d.ts.map +1 -1
- package/dist/workers/processors/pdfToWorksheet.js +15 -95
- package/dist/workers/processors/pdfToWorksheet.js.map +1 -1
- package/dist/workers/processors/studentProgressChat.d.ts +8 -0
- package/dist/workers/processors/studentProgressChat.d.ts.map +1 -0
- package/dist/workers/processors/studentProgressChat.js +27 -0
- package/dist/workers/processors/studentProgressChat.js.map +1 -0
- package/dist/workers/queues.d.ts +20 -4
- package/dist/workers/queues.d.ts.map +1 -1
- package/dist/workers/queues.js +3 -3
- package/dist/workers/queues.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +12 -1
- package/src/lib/config/cors.ts +1 -0
- package/src/lib/pusher.ts +7 -1
- package/src/models/attendance.ts +15 -0
- package/src/models/conversation.ts +54 -0
- package/src/pipelines/aiLabChat.ts +70 -78
- package/src/pipelines/aiNewtonChat.ts +47 -31
- package/src/pipelines/pdfToWorksheet.ts +224 -32
- package/src/routers/assignment.ts +74 -3
- package/src/routers/conversation.ts +7 -0
- package/src/routers/worksheet.ts +25 -4
- package/src/services/announcement.ts +2 -2
- package/src/services/assignment.ts +17 -4
- package/src/services/attendance.ts +87 -2
- package/src/services/conversation.ts +30 -0
- package/src/services/labChat.ts +106 -46
- package/src/services/message.ts +6 -0
- package/src/services/newtonChat.ts +45 -25
- package/src/services/worksheet.ts +71 -10
- package/src/utils/inference.ts +209 -1
- package/src/workers/index.ts +11 -1
- package/src/workers/processors/aiLabChat.ts +65 -0
- package/src/workers/processors/aiNewtonChat.ts +75 -0
- package/src/workers/processors/createRunJobWorker.ts +164 -0
- package/src/workers/processors/gradeWorksheet.ts +16 -0
- package/src/workers/processors/pdfToWorksheet.ts +12 -114
- package/src/workers/processors/studentProgressChat.ts +28 -0
- package/src/workers/queues.ts +20 -5
- package/tests/integration/routers/attendance.test.ts +60 -1
- package/tests/integration/routers/conversation.test.ts +121 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="124f1e50-30ba-5eca-8264-ef797f621b18")}catch(e){}}();
|
|
3
3
|
import express from 'express';
|
|
4
4
|
import { createServer } from 'http';
|
|
5
5
|
import { Server } from 'socket.io';
|
|
@@ -155,7 +155,19 @@ app.post('/api/pusher/auth', async (req, res) => {
|
|
|
155
155
|
return res.status(403).json({ error: 'Not a member of this conversation' });
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
|
-
if (channel_name.startsWith('private-worksheet-')) {
|
|
158
|
+
if (channel_name.startsWith('private-worksheet-job-')) {
|
|
159
|
+
const worksheetId = channel_name.replace('private-worksheet-job-', '');
|
|
160
|
+
const worksheet = await prisma.worksheet.findFirst({
|
|
161
|
+
where: {
|
|
162
|
+
id: worksheetId,
|
|
163
|
+
class: { teachers: { some: { id: user.id } } },
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
if (!worksheet) {
|
|
167
|
+
return res.status(403).json({ error: 'No access to this worksheet job' });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else if (channel_name.startsWith('private-worksheet-')) {
|
|
159
171
|
const worksheetId = channel_name.replace('private-worksheet-', '');
|
|
160
172
|
const worksheet = await prisma.studentWorksheetResponse.findFirst({
|
|
161
173
|
where: { id: worksheetId, OR: [
|
|
@@ -556,4 +568,4 @@ const gracefulShutdown = (signal) => {
|
|
|
556
568
|
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
|
557
569
|
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
558
570
|
//# sourceMappingURL=index.js.map
|
|
559
|
-
//# debugId=
|
|
571
|
+
//# debugId=124f1e50-30ba-5eca-8264-ef797f621b18
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["index.ts"],"sourceRoot":"/","sourcesContent":["import express from 'express';\nimport type { Request, Response } from 'express';\nimport { createServer } from 'http';\nimport { Server } from 'socket.io';\nimport cors from 'cors';\nimport dotenv from 'dotenv';\nimport { createExpressMiddleware } from '@trpc/server/adapters/express';\nimport { appRouter } from './routers/_app.js';\nimport { createTRPCContext, createCallerFactory } from './trpc.js';\nimport { findUserBySessionToken } from './models/auth.js';\nimport { logger } from './utils/logger.js';\nimport { setupSocketHandlers } from './socket/handlers.js';\nimport { bucket } from './lib/googleCloudStorage.js';\nimport { validateDirectUploadIntent } from './lib/fileUpload.js';\nimport { prisma } from './lib/prisma.js';\nimport { pusher } from './lib/pusher.js';\nimport { connectRedis, disconnectRedis } from './lib/redis.js';\nimport { createCorsOriginMatcher } from './lib/config/cors.js';\n\nimport { authLimiter, generalLimiter, helmetConfig, uploadLimiter } from './middleware/security.js';\n\nimport * as Sentry from \"@sentry/node\";\nimport { env } from './lib/config/env.js';\nimport compression from 'compression';\nimport { v4 as uuidv4 } from 'uuid';\n\n\nimport \"./instrument.js\";\nimport { openAIClient } from './utils/inference.js';\n\nconst app = express();\n\napp.set('trust proxy', 1);\n\napp.use(helmetConfig);\napp.use(compression());\napp.use(express.json());\napp.use(express.urlencoded({ extended: true }));\n\napp.use((req, res, next) => {\n const requestId = uuidv4();\n res.setHeader('X-Request-ID', requestId);\n next();\n});\n\nconst { allowedOrigins, allowedOriginPatterns, isAllowedOrigin } = createCorsOriginMatcher(env);\n\n// CORS middleware\napp.use(cors({\n origin: (origin, callback) => {\n if (!origin || isAllowedOrigin(origin)) {\n callback(null, true);\n return;\n }\n\n logger.warn('CORS origin rejected', { origin, allowedOrigins });\n callback(null, false);\n },\n credentials: true,\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-user'],\n preflightContinue: false,\n optionsSuccessStatus: 204,\n}));\n\napp.use(generalLimiter);\n\n// CORS debugging middleware\napp.use((req, res, next) => {\n if (req.method === 'OPTIONS' || req.path.includes('trpc')) {\n logger.info('CORS Request', {\n method: req.method,\n path: req.path,\n origin: req.headers.origin,\n userAgent: req.headers['user-agent']\n });\n }\n next();\n});\n\n// Response time logging middleware\napp.use((req, res, next) => {\n const start = Date.now();\n res.on('finish', () => {\n const duration = Date.now() - start;\n logger.info('Request completed', {\n method: req.method,\n path: req.path,\n statusCode: res.statusCode,\n duration: `${duration}ms`\n });\n });\n next();\n});\n\n// app.use(\"/panel\", async (_, res) => {\n// if (env.NODE_ENV !== \"development\") {\n// return res.status(404).send(\"Not Found\");\n// }\n\n// // Dynamically import renderTrpcPanel only in development\n// const { renderTrpcPanel } = await import(\"trpc-ui\");\n\n// return res.send(\n// renderTrpcPanel(appRouter, {\n// url: \"/trpc\", // Base url of your trpc server\n// meta: {\n// title: \"Studious Backend\",\n// description:\n// \"This is the backend for the Studious application.\",\n// },\n// })\n// );\n// });\n\n\n// Create HTTP server\nconst httpServer = createServer(app);\n\napp.get('/', async (req, res) => {\n res.status(200).json({ \n status: 'OK',\n timestamp: new Date().toISOString(),\n uptime: process.uptime(),\n version: process.env.npm_package_version,\n environment: process.env.NODE_ENV,\n appUrl: process.env.NEXT_PUBLIC_APP_URL,\n });\n});\n\napp.get('/health', async (req, res) => {\n\n try {\n // Check database connectivity\n await prisma.$queryRaw`SELECT 1`;\n \n res.status(200).json({ \n status: 'OK',\n timestamp: new Date().toISOString(),\n uptime: process.uptime(),\n database: 'connected'\n });\n } catch (error) {\n res.status(503).json({ \n status: 'ERROR',\n database: 'disconnected',\n error: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n});\n\n// Pusher channel auth (for private-* and presence-* channels)\n// Token from: x-user header, or cookie (same-origin requests send cookies automatically)\napp.post('/api/pusher/auth', async (req, res) => {\n try {\n let token = req.headers['x-user'] as string | undefined;\n if (!token && req.headers.cookie) {\n const cookieName = env.PUSHER_AUTH_COOKIE_NAME || 'token';\n const match = req.headers.cookie.match(new RegExp(`${cookieName}=([^;]+)`));\n token = match?.[1]?.trim();\n }\n const { socket_id, channel_name } = req.body as { socket_id?: string; channel_name?: string };\n\n if (!socket_id || !channel_name) {\n return res.status(400).json({ error: 'socket_id and channel_name required' });\n }\n\n if (!token) {\n return res.status(401).json({ error: 'Authentication required' });\n }\n\n const user = await findUserBySessionToken(token);\n\n if (!user) {\n return res.status(401).json({ error: 'Invalid or expired session' });\n }\n\n // Verify channel access for private-conversation-* channels\n if (channel_name.startsWith('private-conversation-')) {\n const conversationId = channel_name.replace('private-conversation-', '');\n const member = await prisma.conversationMember.findFirst({\n where: { conversationId, userId: user.id },\n });\n \n if (!member) {\n return res.status(403).json({ error: 'Not a member of this conversation' });\n }\n }\n\n if (channel_name.startsWith('private-worksheet-')) {\n const worksheetId = channel_name.replace('private-worksheet-', '');\n const worksheet = await prisma.studentWorksheetResponse.findFirst({\n where: { id: worksheetId, OR: [\n { studentId: user.id },\n { submission: { assignment: { class: { teachers: { some: { id: user.id } } } } } },\n ] },\n });\n if (!worksheet) {\n return res.status(403).json({ error: 'No access to this worksheet' });\n }\n }\n\n if (channel_name.startsWith('private-teacher-')) {\n const classId = channel_name.replace('private-teacher-', '');\n const isTeacher = await prisma.class.findFirst({\n where: { id: classId, teachers: { some: { id: user.id } } },\n });\n if (!isTeacher) {\n return res.status(403).json({ error: 'Not a teacher of this class' });\n }\n }\n\n // Verify channel access for private-class-* channels\n // if (channel_name.startsWith('private-class-')) {\n // const classId = channel_name.replace('private-class-', '');\n // const isMember = await prisma.class.findFirst({\n // where: {\n // id: classId,\n // OR: [\n // { students: { some: { id: user.id } } },\n // { teachers: { some: { id: user.id } } },\n // ],\n // },\n // });\n // if (!isMember) {\n // return res.status(403).json({ error: 'Not a member of this class' });\n // }\n // }\n\n if (channel_name.startsWith('presence-')) {\n const authResponse = pusher.authorizeChannel(socket_id, channel_name, {\n user_id: user.id,\n user_info: { username: user.username },\n });\n return res.json(authResponse);\n }\n\n const authResponse = pusher.authorizeChannel(socket_id, channel_name);\n return res.json(authResponse);\n } catch (error) {\n logger.error('Pusher auth error', { error });\n return res.status(500).json({ error: 'Authentication failed' });\n }\n});\n\n// Setup Socket.IO\nconst io = new Server(httpServer, {\n cors: {\n origin: (origin, callback) => {\n callback(null, !origin || isAllowedOrigin(origin));\n },\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n credentials: true,\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'Access-Control-Allow-Origin', 'x-user']\n },\n transports: ['websocket', 'polling'],\n pingTimeout: 60000,\n pingInterval: 25000,\n connectTimeout: 45000,\n path: '/socket.io/',\n allowEIO3: true\n});\n\n// Add server-level logging\nio.engine.on('connection_error', (err: Error) => {\n logger.error('Socket connection error', { error: err.message });\n});\n\n// Setup socket handlers\nsetupSocketHandlers(io);\n\n// File serving endpoint for secure file access\napp.get('/api/files/:fileId', async (req, res) => {\n try {\n const fileId = decodeURIComponent(req.params.fileId);\n // console.log('File request:', { fileId, originalPath: req.params.fileId });\n \n // Get user from request headers\n const userHeader = req.headers['x-user'];\n if (!userHeader) {\n return res.status(401).json({ error: 'Authentication required' });\n }\n\n const token = typeof userHeader === 'string' ? userHeader : userHeader[0];\n\n // Find user by session token\n const user = await findUserBySessionToken(token);\n\n if (!user) {\n return res.status(401).json({ error: 'Invalid or expired session' });\n }\n\n // Find file in database by path\n const fileRecord = await prisma.file.findFirst({\n where: { id: fileId },\n include: {\n user: true,\n assignment: {\n include: {\n class: {\n include: {\n students: true,\n teachers: true\n }\n }\n }\n },\n submission: {\n include: {\n student: true,\n assignment: {\n include: {\n class: {\n include: {\n teachers: true\n }\n }\n }\n }\n }\n },\n annotations: {\n include: {\n student: true,\n assignment: {\n include: {\n class: {\n include: {\n teachers: true\n }\n }\n }\n }\n }\n },\n folder: {\n include: {\n class: {\n include: {\n students: true,\n teachers: true\n }\n }\n }\n },\n classDraft: {\n include: {\n students: true,\n teachers: true\n }\n }\n }\n });\n\n if (!fileRecord) {\n return res.status(404).json({ error: 'File not found in database' });\n }\n\n // Check if user has permission to access this file\n let hasPermission = false;\n\n // Check if user created the file\n if (fileRecord.userId === user.id) {\n hasPermission = true;\n }\n\n // Check if file is related to a class where user is a member\n if (!hasPermission) {\n // Check assignment files\n if (fileRecord.assignment?.class) {\n const classData = fileRecord.assignment.class;\n const isStudent = classData.students.some(student => student.id === user.id);\n const isTeacher = classData.teachers.some(teacher => teacher.id === user.id);\n if (isStudent || isTeacher) {\n hasPermission = true;\n }\n }\n\n if (!hasPermission && fileRecord.annotations) {\n const annotation = fileRecord.annotations;\n if (annotation.studentId === user.id) {\n hasPermission = true;\n } else if (annotation.assignment?.class?.teachers.some(teacher => teacher.id === user.id)) {\n hasPermission = true;\n }\n }\n\n // Check submission files (student can access their own submissions, teachers can access all submissions in their class)\n if (!hasPermission && fileRecord.submission) {\n const submission = fileRecord.submission;\n if (submission.studentId === user.id) {\n hasPermission = true; // Student accessing their own submission\n } else if (submission.assignment?.class?.teachers.some(teacher => teacher.id === user.id)) {\n hasPermission = true; // Teacher accessing submission in their class\n }\n }\n\n // Check folder files\n if (!hasPermission && fileRecord.folder?.class) {\n const classData = fileRecord.folder.class;\n const isStudent = classData.students.some(student => student.id === user.id);\n const isTeacher = classData.teachers.some(teacher => teacher.id === user.id);\n if (isStudent || isTeacher) {\n hasPermission = true;\n }\n }\n\n // Check class draft files\n if (!hasPermission && fileRecord.classDraft) {\n const classData = fileRecord.classDraft;\n const isStudent = classData.students.some(student => student.id === user.id);\n const isTeacher = classData.teachers.some(teacher => teacher.id === user.id);\n if (isStudent || isTeacher) {\n hasPermission = true;\n }\n }\n }\n\n if (!hasPermission) {\n return res.status(403).json({ error: 'Access denied - insufficient permissions' });\n }\n \n const filePath = fileRecord.path;\n \n // Get file from Google Cloud Storage\n const file = bucket.file(filePath);\n const [exists] = await file.exists();\n \n if (!exists) {\n return res.status(404).json({ error: 'File not found in storage', filePath });\n }\n \n // Get file metadata\n const [metadata] = await file.getMetadata();\n \n // Set appropriate headers\n res.set({\n 'Content-Type': metadata.contentType || 'application/octet-stream',\n 'Content-Length': metadata.size,\n 'Cache-Control': 'public, max-age=31536000', // 1 year cache\n 'ETag': metadata.etag,\n });\n \n // Stream file to response\n const stream = file.createReadStream();\n stream.pipe(res);\n \n stream.on('error', (error) => {\n logger.error('Error streaming file:', {error});\n if (!res.headersSent) {\n res.status(500).json({ error: 'Error streaming file' });\n }\n });\n \n } catch (error) {\n logger.error('Error serving file:', {error});\n res.status(500).json({ error: 'Internal server error' });\n }\n});\n\napp.use('/trpc/auth.login', authLimiter);\napp.use('/trpc/auth.register', authLimiter);\n\nasync function getAuthenticatedRequestUser(req: Request) {\n const userHeader = req.headers['x-user'];\n const tokenFromUserHeader = typeof userHeader === 'string' ? userHeader : userHeader?.[0];\n const authorizationHeader = req.headers.authorization;\n const tokenFromAuthorization =\n typeof authorizationHeader === 'string' && authorizationHeader.startsWith('Bearer ')\n ? authorizationHeader.slice(7)\n : null;\n\n let token = tokenFromUserHeader ?? tokenFromAuthorization;\n\n if (!token && req.headers.cookie) {\n const cookieName = env.PUSHER_AUTH_COOKIE_NAME || 'token';\n const match = req.headers.cookie.match(new RegExp(cookieName + '=([^;]+)'));\n token = match?.[1]?.trim() ?? null;\n }\n\n if (!token) {\n return null;\n }\n\n return findUserBySessionToken(token);\n}\n\nfunction getUploadSessionId(req: Request) {\n const queryValue = req.query.uploadSessionId;\n if (typeof queryValue === 'string' && queryValue.trim()) {\n return queryValue;\n }\n\n const headerValue = req.headers['x-upload-session-id'];\n return typeof headerValue === 'string' ? headerValue : headerValue?.[0];\n}\n\n// File upload endpoint for secure file uploads (supports both POST and PUT)\napp.post('/api/upload/:filePath', async (req, res) => {\n await handleFileUpload(req, res);\n});\n\napp.put('/api/upload/:filePath', uploadLimiter, async (req, res) => {\n await handleFileUpload(req, res);\n});\n\nasync function handleFileUpload(req: Request, res: Response) {\n try {\n const filePath = decodeURIComponent(req.params.filePath);\n\n // Set CORS headers for upload endpoint\n const origin = req.headers.origin;\n \n if (origin && !isAllowedOrigin(origin)) {\n return res.status(403).json({ error: 'Origin not allowed' });\n }\n\n if (origin) {\n res.header('Access-Control-Allow-Origin', origin);\n }\n \n res.header('Access-Control-Allow-Credentials', 'true');\n \n const contentType = req.headers['content-type'] || 'application/octet-stream';\n const file = bucket.file(filePath);\n\n const writeStream = file.createWriteStream({\n metadata: {\n contentType,\n },\n });\n \n writeStream.on('error', (error) => {\n logger.error('Error uploading file:', {error, filePath});\n if (!res.headersSent) {\n res.status(500).json({ error: 'Error uploading file' });\n }\n });\n \n writeStream.on('finish', () => {\n res.status(200).json({ \n success: true, \n filePath,\n message: 'File uploaded successfully' \n });\n });\n \n req.pipe(writeStream);\n \n } catch (error) {\n logger.error('Error handling file upload:', {error});\n const code = typeof error === 'object' && error && 'code' in error ? error.code : null;\n const message = error instanceof Error ? error.message : 'Internal server error';\n\n if (code === 'FORBIDDEN') {\n return res.status(403).json({ error: message });\n }\n\n if (code === 'BAD_REQUEST') {\n return res.status(400).json({ error: message });\n }\n\n res.status(500).json({ error: 'Internal server error' });\n }\n}\n\n// Create caller\nconst createCaller = createCallerFactory(appRouter);\n\n// Fallback OPTIONS handler — prevents tRPC from rejecting preflight requests\n// when the cors middleware passes through without ending the response.\napp.options('/trpc/*', (req, res) => {\n const origin = req.headers.origin;\n if (origin && isAllowedOrigin(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, x-user');\n }\n res.sendStatus(204);\n});\n\n// Setup tRPC middleware\napp.use(\n '/trpc',\n createExpressMiddleware({\n router: appRouter,\n createContext: async ({ req, res }: { req: Request; res: Response }) => {\n return createTRPCContext({ req, res });\n },\n })\n);\n\n// IMPORTANT: Sentry error handler must be added AFTER all other middleware and routes\n// but BEFORE any other error handlers\nSentry.setupExpressErrorHandler(app);\n\n// app.use(function onError(err, req, res, next) {\n// // The error id is attached to `res.sentry` to be returned\n// // and optionally displayed to the user for support.\n// res.statusCode = 500;\n// res.end(res.sentry + \"\\n\");\n// });\n\n\nconst PORT = env.PORT || 3001;\n\nconnectRedis().then(() => {\n httpServer.listen(PORT, () => {\n logger.info(`Server running on port ${PORT}`, {\n port: PORT,\n services: ['tRPC', 'Socket.IO', env.REDIS_URL ? 'Redis' : null].filter(Boolean),\n });\n });\n}); \n\n// log all env variables\nlogger.info('Configurations', {\n NODE_ENV: env.NODE_ENV,\n PORT: env.PORT,\n NEXT_PUBLIC_APP_URL: env.NEXT_PUBLIC_APP_URL,\n LOG_MODE: env.LOG_MODE,\n});\n\n// Log CORS configuration\nlogger.info('CORS Configuration', {\n allowedOrigins,\n allowedOriginPatterns: allowedOriginPatterns.map((pattern) => pattern.source),\n});\n\nconst gracefulShutdown = (signal: string) => {\n logger.info(`Received ${signal}, shutting down gracefully`);\n \n httpServer.close(() => {\n logger.info('HTTP server closed');\n \n io.close(() => {\n logger.info('Socket.IO server closed');\n\n disconnectRedis().then(() =>\n prisma.$disconnect().then(() => {\n logger.info('Database connections closed');\n process.exit(0);\n }).catch((err) => {\n logger.error('Error disconnecting from database', { error: err });\n process.exit(1);\n })\n );\n });\n });\n \n // Force shutdown after 10 seconds\n setTimeout(() => {\n logger.error('Forced shutdown after timeout');\n process.exit(1);\n }, 10000);\n};\n\nprocess.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\nprocess.on('SIGINT', () => gracefulShutdown('SIGINT'));\n"],"names":[],"mappings":"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","debug_id":"9bbca9a1-393f-54b1-b11b-b9bb88da004f"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["index.ts"],"sourceRoot":"/","sourcesContent":["import express from 'express';\nimport type { Request, Response } from 'express';\nimport { createServer } from 'http';\nimport { Server } from 'socket.io';\nimport cors from 'cors';\nimport dotenv from 'dotenv';\nimport { createExpressMiddleware } from '@trpc/server/adapters/express';\nimport { appRouter } from './routers/_app.js';\nimport { createTRPCContext, createCallerFactory } from './trpc.js';\nimport { findUserBySessionToken } from './models/auth.js';\nimport { logger } from './utils/logger.js';\nimport { setupSocketHandlers } from './socket/handlers.js';\nimport { bucket } from './lib/googleCloudStorage.js';\nimport { validateDirectUploadIntent } from './lib/fileUpload.js';\nimport { prisma } from './lib/prisma.js';\nimport { pusher } from './lib/pusher.js';\nimport { connectRedis, disconnectRedis } from './lib/redis.js';\nimport { createCorsOriginMatcher } from './lib/config/cors.js';\n\nimport { authLimiter, generalLimiter, helmetConfig, uploadLimiter } from './middleware/security.js';\n\nimport * as Sentry from \"@sentry/node\";\nimport { env } from './lib/config/env.js';\nimport compression from 'compression';\nimport { v4 as uuidv4 } from 'uuid';\n\n\nimport \"./instrument.js\";\nimport { openAIClient } from './utils/inference.js';\n\nconst app = express();\n\napp.set('trust proxy', 1);\n\napp.use(helmetConfig);\napp.use(compression());\napp.use(express.json());\napp.use(express.urlencoded({ extended: true }));\n\napp.use((req, res, next) => {\n const requestId = uuidv4();\n res.setHeader('X-Request-ID', requestId);\n next();\n});\n\nconst { allowedOrigins, allowedOriginPatterns, isAllowedOrigin } = createCorsOriginMatcher(env);\n\n// CORS middleware\napp.use(cors({\n origin: (origin, callback) => {\n if (!origin || isAllowedOrigin(origin)) {\n callback(null, true);\n return;\n }\n\n logger.warn('CORS origin rejected', { origin, allowedOrigins });\n callback(null, false);\n },\n credentials: true,\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-user'],\n preflightContinue: false,\n optionsSuccessStatus: 204,\n}));\n\napp.use(generalLimiter);\n\n// CORS debugging middleware\napp.use((req, res, next) => {\n if (req.method === 'OPTIONS' || req.path.includes('trpc')) {\n logger.info('CORS Request', {\n method: req.method,\n path: req.path,\n origin: req.headers.origin,\n userAgent: req.headers['user-agent']\n });\n }\n next();\n});\n\n// Response time logging middleware\napp.use((req, res, next) => {\n const start = Date.now();\n res.on('finish', () => {\n const duration = Date.now() - start;\n logger.info('Request completed', {\n method: req.method,\n path: req.path,\n statusCode: res.statusCode,\n duration: `${duration}ms`\n });\n });\n next();\n});\n\n// app.use(\"/panel\", async (_, res) => {\n// if (env.NODE_ENV !== \"development\") {\n// return res.status(404).send(\"Not Found\");\n// }\n\n// // Dynamically import renderTrpcPanel only in development\n// const { renderTrpcPanel } = await import(\"trpc-ui\");\n\n// return res.send(\n// renderTrpcPanel(appRouter, {\n// url: \"/trpc\", // Base url of your trpc server\n// meta: {\n// title: \"Studious Backend\",\n// description:\n// \"This is the backend for the Studious application.\",\n// },\n// })\n// );\n// });\n\n\n// Create HTTP server\nconst httpServer = createServer(app);\n\napp.get('/', async (req, res) => {\n res.status(200).json({ \n status: 'OK',\n timestamp: new Date().toISOString(),\n uptime: process.uptime(),\n version: process.env.npm_package_version,\n environment: process.env.NODE_ENV,\n appUrl: process.env.NEXT_PUBLIC_APP_URL,\n });\n});\n\napp.get('/health', async (req, res) => {\n\n try {\n // Check database connectivity\n await prisma.$queryRaw`SELECT 1`;\n \n res.status(200).json({ \n status: 'OK',\n timestamp: new Date().toISOString(),\n uptime: process.uptime(),\n database: 'connected'\n });\n } catch (error) {\n res.status(503).json({ \n status: 'ERROR',\n database: 'disconnected',\n error: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n});\n\n// Pusher channel auth (for private-* and presence-* channels)\n// Token from: x-user header, or cookie (same-origin requests send cookies automatically)\napp.post('/api/pusher/auth', async (req, res) => {\n try {\n let token = req.headers['x-user'] as string | undefined;\n if (!token && req.headers.cookie) {\n const cookieName = env.PUSHER_AUTH_COOKIE_NAME || 'token';\n const match = req.headers.cookie.match(new RegExp(`${cookieName}=([^;]+)`));\n token = match?.[1]?.trim();\n }\n const { socket_id, channel_name } = req.body as { socket_id?: string; channel_name?: string };\n\n if (!socket_id || !channel_name) {\n return res.status(400).json({ error: 'socket_id and channel_name required' });\n }\n\n if (!token) {\n return res.status(401).json({ error: 'Authentication required' });\n }\n\n const user = await findUserBySessionToken(token);\n\n if (!user) {\n return res.status(401).json({ error: 'Invalid or expired session' });\n }\n\n // Verify channel access for private-conversation-* channels\n if (channel_name.startsWith('private-conversation-')) {\n const conversationId = channel_name.replace('private-conversation-', '');\n const member = await prisma.conversationMember.findFirst({\n where: { conversationId, userId: user.id },\n });\n \n if (!member) {\n return res.status(403).json({ error: 'Not a member of this conversation' });\n }\n }\n\n if (channel_name.startsWith('private-worksheet-job-')) {\n const worksheetId = channel_name.replace('private-worksheet-job-', '');\n const worksheet = await prisma.worksheet.findFirst({\n where: {\n id: worksheetId,\n class: { teachers: { some: { id: user.id } } },\n },\n });\n if (!worksheet) {\n return res.status(403).json({ error: 'No access to this worksheet job' });\n }\n } else if (channel_name.startsWith('private-worksheet-')) {\n const worksheetId = channel_name.replace('private-worksheet-', '');\n const worksheet = await prisma.studentWorksheetResponse.findFirst({\n where: { id: worksheetId, OR: [\n { studentId: user.id },\n { submission: { assignment: { class: { teachers: { some: { id: user.id } } } } } },\n ] },\n });\n if (!worksheet) {\n return res.status(403).json({ error: 'No access to this worksheet' });\n }\n }\n\n if (channel_name.startsWith('private-teacher-')) {\n const classId = channel_name.replace('private-teacher-', '');\n const isTeacher = await prisma.class.findFirst({\n where: { id: classId, teachers: { some: { id: user.id } } },\n });\n if (!isTeacher) {\n return res.status(403).json({ error: 'Not a teacher of this class' });\n }\n }\n\n // Verify channel access for private-class-* channels\n // if (channel_name.startsWith('private-class-')) {\n // const classId = channel_name.replace('private-class-', '');\n // const isMember = await prisma.class.findFirst({\n // where: {\n // id: classId,\n // OR: [\n // { students: { some: { id: user.id } } },\n // { teachers: { some: { id: user.id } } },\n // ],\n // },\n // });\n // if (!isMember) {\n // return res.status(403).json({ error: 'Not a member of this class' });\n // }\n // }\n\n if (channel_name.startsWith('presence-')) {\n const authResponse = pusher.authorizeChannel(socket_id, channel_name, {\n user_id: user.id,\n user_info: { username: user.username },\n });\n return res.json(authResponse);\n }\n\n const authResponse = pusher.authorizeChannel(socket_id, channel_name);\n return res.json(authResponse);\n } catch (error) {\n logger.error('Pusher auth error', { error });\n return res.status(500).json({ error: 'Authentication failed' });\n }\n});\n\n// Setup Socket.IO\nconst io = new Server(httpServer, {\n cors: {\n origin: (origin, callback) => {\n callback(null, !origin || isAllowedOrigin(origin));\n },\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n credentials: true,\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'Access-Control-Allow-Origin', 'x-user']\n },\n transports: ['websocket', 'polling'],\n pingTimeout: 60000,\n pingInterval: 25000,\n connectTimeout: 45000,\n path: '/socket.io/',\n allowEIO3: true\n});\n\n// Add server-level logging\nio.engine.on('connection_error', (err: Error) => {\n logger.error('Socket connection error', { error: err.message });\n});\n\n// Setup socket handlers\nsetupSocketHandlers(io);\n\n// File serving endpoint for secure file access\napp.get('/api/files/:fileId', async (req, res) => {\n try {\n const fileId = decodeURIComponent(req.params.fileId);\n // console.log('File request:', { fileId, originalPath: req.params.fileId });\n \n // Get user from request headers\n const userHeader = req.headers['x-user'];\n if (!userHeader) {\n return res.status(401).json({ error: 'Authentication required' });\n }\n\n const token = typeof userHeader === 'string' ? userHeader : userHeader[0];\n\n // Find user by session token\n const user = await findUserBySessionToken(token);\n\n if (!user) {\n return res.status(401).json({ error: 'Invalid or expired session' });\n }\n\n // Find file in database by path\n const fileRecord = await prisma.file.findFirst({\n where: { id: fileId },\n include: {\n user: true,\n assignment: {\n include: {\n class: {\n include: {\n students: true,\n teachers: true\n }\n }\n }\n },\n submission: {\n include: {\n student: true,\n assignment: {\n include: {\n class: {\n include: {\n teachers: true\n }\n }\n }\n }\n }\n },\n annotations: {\n include: {\n student: true,\n assignment: {\n include: {\n class: {\n include: {\n teachers: true\n }\n }\n }\n }\n }\n },\n folder: {\n include: {\n class: {\n include: {\n students: true,\n teachers: true\n }\n }\n }\n },\n classDraft: {\n include: {\n students: true,\n teachers: true\n }\n }\n }\n });\n\n if (!fileRecord) {\n return res.status(404).json({ error: 'File not found in database' });\n }\n\n // Check if user has permission to access this file\n let hasPermission = false;\n\n // Check if user created the file\n if (fileRecord.userId === user.id) {\n hasPermission = true;\n }\n\n // Check if file is related to a class where user is a member\n if (!hasPermission) {\n // Check assignment files\n if (fileRecord.assignment?.class) {\n const classData = fileRecord.assignment.class;\n const isStudent = classData.students.some(student => student.id === user.id);\n const isTeacher = classData.teachers.some(teacher => teacher.id === user.id);\n if (isStudent || isTeacher) {\n hasPermission = true;\n }\n }\n\n if (!hasPermission && fileRecord.annotations) {\n const annotation = fileRecord.annotations;\n if (annotation.studentId === user.id) {\n hasPermission = true;\n } else if (annotation.assignment?.class?.teachers.some(teacher => teacher.id === user.id)) {\n hasPermission = true;\n }\n }\n\n // Check submission files (student can access their own submissions, teachers can access all submissions in their class)\n if (!hasPermission && fileRecord.submission) {\n const submission = fileRecord.submission;\n if (submission.studentId === user.id) {\n hasPermission = true; // Student accessing their own submission\n } else if (submission.assignment?.class?.teachers.some(teacher => teacher.id === user.id)) {\n hasPermission = true; // Teacher accessing submission in their class\n }\n }\n\n // Check folder files\n if (!hasPermission && fileRecord.folder?.class) {\n const classData = fileRecord.folder.class;\n const isStudent = classData.students.some(student => student.id === user.id);\n const isTeacher = classData.teachers.some(teacher => teacher.id === user.id);\n if (isStudent || isTeacher) {\n hasPermission = true;\n }\n }\n\n // Check class draft files\n if (!hasPermission && fileRecord.classDraft) {\n const classData = fileRecord.classDraft;\n const isStudent = classData.students.some(student => student.id === user.id);\n const isTeacher = classData.teachers.some(teacher => teacher.id === user.id);\n if (isStudent || isTeacher) {\n hasPermission = true;\n }\n }\n }\n\n if (!hasPermission) {\n return res.status(403).json({ error: 'Access denied - insufficient permissions' });\n }\n \n const filePath = fileRecord.path;\n \n // Get file from Google Cloud Storage\n const file = bucket.file(filePath);\n const [exists] = await file.exists();\n \n if (!exists) {\n return res.status(404).json({ error: 'File not found in storage', filePath });\n }\n \n // Get file metadata\n const [metadata] = await file.getMetadata();\n \n // Set appropriate headers\n res.set({\n 'Content-Type': metadata.contentType || 'application/octet-stream',\n 'Content-Length': metadata.size,\n 'Cache-Control': 'public, max-age=31536000', // 1 year cache\n 'ETag': metadata.etag,\n });\n \n // Stream file to response\n const stream = file.createReadStream();\n stream.pipe(res);\n \n stream.on('error', (error) => {\n logger.error('Error streaming file:', {error});\n if (!res.headersSent) {\n res.status(500).json({ error: 'Error streaming file' });\n }\n });\n \n } catch (error) {\n logger.error('Error serving file:', {error});\n res.status(500).json({ error: 'Internal server error' });\n }\n});\n\napp.use('/trpc/auth.login', authLimiter);\napp.use('/trpc/auth.register', authLimiter);\n\nasync function getAuthenticatedRequestUser(req: Request) {\n const userHeader = req.headers['x-user'];\n const tokenFromUserHeader = typeof userHeader === 'string' ? userHeader : userHeader?.[0];\n const authorizationHeader = req.headers.authorization;\n const tokenFromAuthorization =\n typeof authorizationHeader === 'string' && authorizationHeader.startsWith('Bearer ')\n ? authorizationHeader.slice(7)\n : null;\n\n let token = tokenFromUserHeader ?? tokenFromAuthorization;\n\n if (!token && req.headers.cookie) {\n const cookieName = env.PUSHER_AUTH_COOKIE_NAME || 'token';\n const match = req.headers.cookie.match(new RegExp(cookieName + '=([^;]+)'));\n token = match?.[1]?.trim() ?? null;\n }\n\n if (!token) {\n return null;\n }\n\n return findUserBySessionToken(token);\n}\n\nfunction getUploadSessionId(req: Request) {\n const queryValue = req.query.uploadSessionId;\n if (typeof queryValue === 'string' && queryValue.trim()) {\n return queryValue;\n }\n\n const headerValue = req.headers['x-upload-session-id'];\n return typeof headerValue === 'string' ? headerValue : headerValue?.[0];\n}\n\n// File upload endpoint for secure file uploads (supports both POST and PUT)\napp.post('/api/upload/:filePath', async (req, res) => {\n await handleFileUpload(req, res);\n});\n\napp.put('/api/upload/:filePath', uploadLimiter, async (req, res) => {\n await handleFileUpload(req, res);\n});\n\nasync function handleFileUpload(req: Request, res: Response) {\n try {\n const filePath = decodeURIComponent(req.params.filePath);\n\n // Set CORS headers for upload endpoint\n const origin = req.headers.origin;\n \n if (origin && !isAllowedOrigin(origin)) {\n return res.status(403).json({ error: 'Origin not allowed' });\n }\n\n if (origin) {\n res.header('Access-Control-Allow-Origin', origin);\n }\n \n res.header('Access-Control-Allow-Credentials', 'true');\n \n const contentType = req.headers['content-type'] || 'application/octet-stream';\n const file = bucket.file(filePath);\n\n const writeStream = file.createWriteStream({\n metadata: {\n contentType,\n },\n });\n \n writeStream.on('error', (error) => {\n logger.error('Error uploading file:', {error, filePath});\n if (!res.headersSent) {\n res.status(500).json({ error: 'Error uploading file' });\n }\n });\n \n writeStream.on('finish', () => {\n res.status(200).json({ \n success: true, \n filePath,\n message: 'File uploaded successfully' \n });\n });\n \n req.pipe(writeStream);\n \n } catch (error) {\n logger.error('Error handling file upload:', {error});\n const code = typeof error === 'object' && error && 'code' in error ? error.code : null;\n const message = error instanceof Error ? error.message : 'Internal server error';\n\n if (code === 'FORBIDDEN') {\n return res.status(403).json({ error: message });\n }\n\n if (code === 'BAD_REQUEST') {\n return res.status(400).json({ error: message });\n }\n\n res.status(500).json({ error: 'Internal server error' });\n }\n}\n\n// Create caller\nconst createCaller = createCallerFactory(appRouter);\n\n// Fallback OPTIONS handler — prevents tRPC from rejecting preflight requests\n// when the cors middleware passes through without ending the response.\napp.options('/trpc/*', (req, res) => {\n const origin = req.headers.origin;\n if (origin && isAllowedOrigin(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, x-user');\n }\n res.sendStatus(204);\n});\n\n// Setup tRPC middleware\napp.use(\n '/trpc',\n createExpressMiddleware({\n router: appRouter,\n createContext: async ({ req, res }: { req: Request; res: Response }) => {\n return createTRPCContext({ req, res });\n },\n })\n);\n\n// IMPORTANT: Sentry error handler must be added AFTER all other middleware and routes\n// but BEFORE any other error handlers\nSentry.setupExpressErrorHandler(app);\n\n// app.use(function onError(err, req, res, next) {\n// // The error id is attached to `res.sentry` to be returned\n// // and optionally displayed to the user for support.\n// res.statusCode = 500;\n// res.end(res.sentry + \"\\n\");\n// });\n\n\nconst PORT = env.PORT || 3001;\n\nconnectRedis().then(() => {\n httpServer.listen(PORT, () => {\n logger.info(`Server running on port ${PORT}`, {\n port: PORT,\n services: ['tRPC', 'Socket.IO', env.REDIS_URL ? 'Redis' : null].filter(Boolean),\n });\n });\n}); \n\n// log all env variables\nlogger.info('Configurations', {\n NODE_ENV: env.NODE_ENV,\n PORT: env.PORT,\n NEXT_PUBLIC_APP_URL: env.NEXT_PUBLIC_APP_URL,\n LOG_MODE: env.LOG_MODE,\n});\n\n// Log CORS configuration\nlogger.info('CORS Configuration', {\n allowedOrigins,\n allowedOriginPatterns: allowedOriginPatterns.map((pattern) => pattern.source),\n});\n\nconst gracefulShutdown = (signal: string) => {\n logger.info(`Received ${signal}, shutting down gracefully`);\n \n httpServer.close(() => {\n logger.info('HTTP server closed');\n \n io.close(() => {\n logger.info('Socket.IO server closed');\n\n disconnectRedis().then(() =>\n prisma.$disconnect().then(() => {\n logger.info('Database connections closed');\n process.exit(0);\n }).catch((err) => {\n logger.error('Error disconnecting from database', { error: err });\n process.exit(1);\n })\n );\n });\n });\n \n // Force shutdown after 10 seconds\n setTimeout(() => {\n logger.error('Forced shutdown after timeout');\n process.exit(1);\n }, 10000);\n};\n\nprocess.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\nprocess.on('SIGINT', () => gracefulShutdown('SIGINT'));\n"],"names":[],"mappings":"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","debug_id":"124f1e50-30ba-5eca-8264-ef797f621b18"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cors.d.ts","sourceRoot":"/","sources":["lib/config/cors.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,EAAE,aAAa,GAAG,YAAY,GAAG,MAAM,CAAC;IACjD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC,CAAC;
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"/","sources":["lib/config/cors.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,EAAE,aAAa,GAAG,YAAY,GAAG,MAAM,CAAC;IACjD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC,CAAC;AAwCF,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,aACX,CAAC;AAiBvC,eAAO,MAAM,uBAAuB,GAAI,WAAW,MAAM,aAC6B,CAAC;AAEvF,eAAO,MAAM,4BAA4B,GAAI,WAAW,MAAM,YAO7D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,KAAK,OAAO;;;+BAYhB,MAAM;CAczC,CAAC"}
|
package/dist/lib/config/cors.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="42d58483-c9e6-56b4-9302-da84343ffeeb")}catch(e){}}();
|
|
3
3
|
const productionOrigins = [
|
|
4
4
|
'https://www.studious.sh',
|
|
5
5
|
'https://studious.sh',
|
|
6
|
+
'https://dev.studious.sh',
|
|
6
7
|
];
|
|
7
8
|
const nonProductionOrigins = [
|
|
8
9
|
'http://localhost:3000',
|
|
@@ -75,4 +76,4 @@ export const createCorsOriginMatcher = (env) => {
|
|
|
75
76
|
};
|
|
76
77
|
};
|
|
77
78
|
//# sourceMappingURL=cors.js.map
|
|
78
|
-
//# debugId=
|
|
79
|
+
//# debugId=42d58483-c9e6-56b4-9302-da84343ffeeb
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cors.js","sources":["lib/config/cors.ts"],"sourceRoot":"/","sourcesContent":["type CorsEnv = {\n NODE_ENV?: 'development' | 'production' | 'test';\n NEXT_PUBLIC_APP_URL?: string;\n CORS_ALLOWED_ORIGINS?: string;\n CORS_ALLOWED_ORIGIN_PATTERNS?: string;\n};\n\nconst productionOrigins = [\n 'https://www.studious.sh',\n 'https://studious.sh',\n];\n\nconst nonProductionOrigins = [\n 'http://localhost:3000',\n 'http://localhost:3001',\n 'http://127.0.0.1:3000',\n 'http://127.0.0.1:3001',\n];\n\n/** Any preview / prod deployment on *.vercel.app (HTTPS only). */\nconst vercelAppOriginPattern = /^https:\\/\\/[a-z0-9][a-z0-9.-]*\\.vercel\\.app$/i;\n\nconst MAX_PATTERN_LENGTH = 200;\n// This heuristic only targets common nested-quantifier cases like `(a+)+`.\n// It does not catch every risky construct (for example `.*.*` or deep alternation nesting),\n// so `parseCorsOriginPatterns` should still be limited to operator-controlled, anchored patterns.\nconst SUSPICIOUS_QUANTIFIER_PATTERN = /(\\([^)]*[+*{][^)]*\\)|\\[[^\\]]+[+*{][^\\]]*\\])[+*{]/;\n\nconst parseList = (value?: string) =>\n value\n ?.split(',')\n .map((item) => item.trim())\n .filter(Boolean) ?? [];\n\nconst isDefined = <T>(value: T | undefined | null): value is T => Boolean(value);\n\nconst toCorsOrigin = (value: string) => {\n try {\n return new URL(value).origin;\n } catch {\n return value.replace(/\\/+$/, '');\n }\n};\n\nexport const parseCorsOrigins = (origins?: string) =>\n parseList(origins).map(toCorsOrigin);\n\nconst validateCorsOriginPattern = (pattern: string) => {\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new Error(`CORS pattern exceeds maximum length of ${MAX_PATTERN_LENGTH}`);\n }\n\n // Prefer short, anchored patterns and avoid other complex regex features even if they pass this check.\n if (SUSPICIOUS_QUANTIFIER_PATTERN.test(pattern)) {\n throw new Error(\"CORS pattern contains nested or ambiguous quantifiers\");\n }\n\n return pattern;\n};\n\n// Patterns are operator-controlled and matched against bounded URL origins, so ReDoS risk is low.\n// Syntax validation does not guarantee safety; prefer anchored patterns and avoid nested quantifiers.\nexport const parseCorsOriginPatterns = (patterns?: string) =>\n parseList(patterns).map((pattern) => new RegExp(validateCorsOriginPattern(pattern)));\n\nexport const isValidCorsOriginPatternList = (patterns?: string) => {\n try {\n parseCorsOriginPatterns(patterns);\n return true;\n } catch {\n return false;\n }\n};\n\nexport const createCorsOriginMatcher = (env: CorsEnv) => {\n const allowedOrigins = Array.from(new Set([\n ...(env.NODE_ENV === 'production' ? productionOrigins : nonProductionOrigins),\n env.NEXT_PUBLIC_APP_URL ? toCorsOrigin(env.NEXT_PUBLIC_APP_URL) : undefined,\n ...parseCorsOrigins(env.CORS_ALLOWED_ORIGINS),\n ].filter(isDefined)));\n\n const allowedOriginPatterns = [\n vercelAppOriginPattern,\n ...parseCorsOriginPatterns(env.CORS_ALLOWED_ORIGIN_PATTERNS),\n ];\n\n const isAllowedOrigin = (origin?: string) => {\n const corsOrigin = origin ? toCorsOrigin(origin) : undefined;\n\n return Boolean(corsOrigin && (\n allowedOrigins.includes(corsOrigin) ||\n allowedOriginPatterns.some((pattern) => pattern.test(corsOrigin))\n ));\n };\n\n return {\n allowedOrigins,\n allowedOriginPatterns,\n isAllowedOrigin,\n };\n};\n"],"names":[],"mappings":";;AAOA,MAAM,iBAAiB,GAAG;IACxB,yBAAyB;IACzB,qBAAqB;
|
|
1
|
+
{"version":3,"file":"cors.js","sources":["lib/config/cors.ts"],"sourceRoot":"/","sourcesContent":["type CorsEnv = {\n NODE_ENV?: 'development' | 'production' | 'test';\n NEXT_PUBLIC_APP_URL?: string;\n CORS_ALLOWED_ORIGINS?: string;\n CORS_ALLOWED_ORIGIN_PATTERNS?: string;\n};\n\nconst productionOrigins = [\n 'https://www.studious.sh',\n 'https://studious.sh',\n 'https://dev.studious.sh',\n];\n\nconst nonProductionOrigins = [\n 'http://localhost:3000',\n 'http://localhost:3001',\n 'http://127.0.0.1:3000',\n 'http://127.0.0.1:3001',\n];\n\n/** Any preview / prod deployment on *.vercel.app (HTTPS only). */\nconst vercelAppOriginPattern = /^https:\\/\\/[a-z0-9][a-z0-9.-]*\\.vercel\\.app$/i;\n\nconst MAX_PATTERN_LENGTH = 200;\n// This heuristic only targets common nested-quantifier cases like `(a+)+`.\n// It does not catch every risky construct (for example `.*.*` or deep alternation nesting),\n// so `parseCorsOriginPatterns` should still be limited to operator-controlled, anchored patterns.\nconst SUSPICIOUS_QUANTIFIER_PATTERN = /(\\([^)]*[+*{][^)]*\\)|\\[[^\\]]+[+*{][^\\]]*\\])[+*{]/;\n\nconst parseList = (value?: string) =>\n value\n ?.split(',')\n .map((item) => item.trim())\n .filter(Boolean) ?? [];\n\nconst isDefined = <T>(value: T | undefined | null): value is T => Boolean(value);\n\nconst toCorsOrigin = (value: string) => {\n try {\n return new URL(value).origin;\n } catch {\n return value.replace(/\\/+$/, '');\n }\n};\n\nexport const parseCorsOrigins = (origins?: string) =>\n parseList(origins).map(toCorsOrigin);\n\nconst validateCorsOriginPattern = (pattern: string) => {\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new Error(`CORS pattern exceeds maximum length of ${MAX_PATTERN_LENGTH}`);\n }\n\n // Prefer short, anchored patterns and avoid other complex regex features even if they pass this check.\n if (SUSPICIOUS_QUANTIFIER_PATTERN.test(pattern)) {\n throw new Error(\"CORS pattern contains nested or ambiguous quantifiers\");\n }\n\n return pattern;\n};\n\n// Patterns are operator-controlled and matched against bounded URL origins, so ReDoS risk is low.\n// Syntax validation does not guarantee safety; prefer anchored patterns and avoid nested quantifiers.\nexport const parseCorsOriginPatterns = (patterns?: string) =>\n parseList(patterns).map((pattern) => new RegExp(validateCorsOriginPattern(pattern)));\n\nexport const isValidCorsOriginPatternList = (patterns?: string) => {\n try {\n parseCorsOriginPatterns(patterns);\n return true;\n } catch {\n return false;\n }\n};\n\nexport const createCorsOriginMatcher = (env: CorsEnv) => {\n const allowedOrigins = Array.from(new Set([\n ...(env.NODE_ENV === 'production' ? productionOrigins : nonProductionOrigins),\n env.NEXT_PUBLIC_APP_URL ? toCorsOrigin(env.NEXT_PUBLIC_APP_URL) : undefined,\n ...parseCorsOrigins(env.CORS_ALLOWED_ORIGINS),\n ].filter(isDefined)));\n\n const allowedOriginPatterns = [\n vercelAppOriginPattern,\n ...parseCorsOriginPatterns(env.CORS_ALLOWED_ORIGIN_PATTERNS),\n ];\n\n const isAllowedOrigin = (origin?: string) => {\n const corsOrigin = origin ? toCorsOrigin(origin) : undefined;\n\n return Boolean(corsOrigin && (\n allowedOrigins.includes(corsOrigin) ||\n allowedOriginPatterns.some((pattern) => pattern.test(corsOrigin))\n ));\n };\n\n return {\n allowedOrigins,\n allowedOriginPatterns,\n isAllowedOrigin,\n };\n};\n"],"names":[],"mappings":"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","debug_id":"42d58483-c9e6-56b4-9302-da84343ffeeb"}
|
package/dist/lib/pusher.d.ts
CHANGED
|
@@ -3,5 +3,11 @@ declare const pusher: Pusher;
|
|
|
3
3
|
declare const chatChannel: (conversationId: string) => string;
|
|
4
4
|
declare const worksheetChannel: (worksheetResponseId: string) => string;
|
|
5
5
|
declare const teacherChannel: (classId: string) => string;
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Per-worksheet job channel used for asynchronous worksheet creation
|
|
8
|
+
* (e.g. PDF → worksheet conversion). Distinct prefix from the student
|
|
9
|
+
* worksheet-response channel so both can co-exist without auth collisions.
|
|
10
|
+
*/
|
|
11
|
+
declare const worksheetJobChannel: (worksheetId: string) => string;
|
|
12
|
+
export { pusher, chatChannel, worksheetChannel, teacherChannel, worksheetJobChannel };
|
|
7
13
|
//# sourceMappingURL=pusher.d.ts.map
|
package/dist/lib/pusher.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pusher.d.ts","sourceRoot":"/","sources":["lib/pusher.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,QAAA,MAAM,MAAM,QAMV,CAAC;AAEH,QAAA,MAAM,WAAW,GAAI,gBAAgB,MAAM,WAA6C,CAAC;AACzF,QAAA,MAAM,gBAAgB,GAAI,qBAAqB,MAAM,WAA+C,CAAC;AACrG,QAAA,MAAM,cAAc,GAAI,SAAS,MAAM,WAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"pusher.d.ts","sourceRoot":"/","sources":["lib/pusher.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,QAAA,MAAM,MAAM,QAMV,CAAC;AAEH,QAAA,MAAM,WAAW,GAAI,gBAAgB,MAAM,WAA6C,CAAC;AACzF,QAAA,MAAM,gBAAgB,GAAI,qBAAqB,MAAM,WAA+C,CAAC;AACrG,QAAA,MAAM,cAAc,GAAI,SAAS,MAAM,WAAiC,CAAC;AACzE;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,GAAI,aAAa,MAAM,WAA2C,CAAC;AAE5F,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC"}
|
package/dist/lib/pusher.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="08f263b0-d8bd-5fa5-a596-069621decf88")}catch(e){}}();
|
|
3
3
|
import Pusher from 'pusher';
|
|
4
4
|
import { env } from './config/env.js';
|
|
5
5
|
const pusher = new Pusher({
|
|
@@ -12,6 +12,12 @@ const pusher = new Pusher({
|
|
|
12
12
|
const chatChannel = (conversationId) => `private-conversation-${conversationId}`;
|
|
13
13
|
const worksheetChannel = (worksheetResponseId) => `private-worksheet-${worksheetResponseId}`;
|
|
14
14
|
const teacherChannel = (classId) => `private-teacher-${classId}`;
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Per-worksheet job channel used for asynchronous worksheet creation
|
|
17
|
+
* (e.g. PDF → worksheet conversion). Distinct prefix from the student
|
|
18
|
+
* worksheet-response channel so both can co-exist without auth collisions.
|
|
19
|
+
*/
|
|
20
|
+
const worksheetJobChannel = (worksheetId) => `private-worksheet-job-${worksheetId}`;
|
|
21
|
+
export { pusher, chatChannel, worksheetChannel, teacherChannel, worksheetJobChannel };
|
|
16
22
|
//# sourceMappingURL=pusher.js.map
|
|
17
|
-
//# debugId=
|
|
23
|
+
//# debugId=08f263b0-d8bd-5fa5-a596-069621decf88
|
package/dist/lib/pusher.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pusher.js","sources":["lib/pusher.ts"],"sourceRoot":"/","sourcesContent":["import Pusher from 'pusher';\nimport { env } from './config/env.js';\n\nconst pusher = new Pusher({\n appId: env.PUSHER_APP_ID,\n key: env.PUSHER_KEY,\n secret: env.PUSHER_SECRET,\n cluster: env.PUSHER_CLUSTER,\n useTLS: env.NODE_ENV !== 'development',\n});\n\nconst chatChannel = (conversationId: string) => `private-conversation-${conversationId}`;\nconst worksheetChannel = (worksheetResponseId: string) => `private-worksheet-${worksheetResponseId}`;\nconst teacherChannel = (classId: string) => `private-teacher-${classId}`;\n\nexport { pusher, chatChannel, worksheetChannel, teacherChannel };\n"],"names":[],"mappings":";;AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;IACxB,KAAK,EAAE,GAAG,CAAC,aAAa;IACxB,GAAG,EAAE,GAAG,CAAC,UAAU;IACnB,MAAM,EAAE,GAAG,CAAC,aAAa;IACzB,OAAO,EAAE,GAAG,CAAC,cAAc;IAC3B,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,aAAa;CACvC,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,CAAC,cAAsB,EAAE,EAAE,CAAC,wBAAwB,cAAc,EAAE,CAAC;AACzF,MAAM,gBAAgB,GAAG,CAAC,mBAA2B,EAAE,EAAE,CAAC,qBAAqB,mBAAmB,EAAE,CAAC;AACrG,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,mBAAmB,OAAO,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"pusher.js","sources":["lib/pusher.ts"],"sourceRoot":"/","sourcesContent":["import Pusher from 'pusher';\nimport { env } from './config/env.js';\n\nconst pusher = new Pusher({\n appId: env.PUSHER_APP_ID,\n key: env.PUSHER_KEY,\n secret: env.PUSHER_SECRET,\n cluster: env.PUSHER_CLUSTER,\n useTLS: env.NODE_ENV !== 'development',\n});\n\nconst chatChannel = (conversationId: string) => `private-conversation-${conversationId}`;\nconst worksheetChannel = (worksheetResponseId: string) => `private-worksheet-${worksheetResponseId}`;\nconst teacherChannel = (classId: string) => `private-teacher-${classId}`;\n/**\n * Per-worksheet job channel used for asynchronous worksheet creation\n * (e.g. PDF → worksheet conversion). Distinct prefix from the student\n * worksheet-response channel so both can co-exist without auth collisions.\n */\nconst worksheetJobChannel = (worksheetId: string) => `private-worksheet-job-${worksheetId}`;\n\nexport { pusher, chatChannel, worksheetChannel, teacherChannel, worksheetJobChannel };\n"],"names":[],"mappings":";;AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;IACxB,KAAK,EAAE,GAAG,CAAC,aAAa;IACxB,GAAG,EAAE,GAAG,CAAC,UAAU;IACnB,MAAM,EAAE,GAAG,CAAC,aAAa;IACzB,OAAO,EAAE,GAAG,CAAC,cAAc;IAC3B,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,aAAa;CACvC,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,CAAC,cAAsB,EAAE,EAAE,CAAC,wBAAwB,cAAc,EAAE,CAAC;AACzF,MAAM,gBAAgB,GAAG,CAAC,mBAA2B,EAAE,EAAE,CAAC,qBAAqB,mBAAmB,EAAE,CAAC;AACrG,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,mBAAmB,OAAO,EAAE,CAAC;AACzE;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,CAAC,WAAmB,EAAE,EAAE,CAAC,yBAAyB,WAAW,EAAE,CAAC;AAE5F,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC","debug_id":"08f263b0-d8bd-5fa5-a596-069621decf88"}
|
|
@@ -24,11 +24,9 @@ export declare function findClassWithStudents(classId: string): import(".prisma/
|
|
|
24
24
|
export declare function findClassWithTeacher(classId: string, teacherId: string): import(".prisma/client").Prisma.Prisma__ClassClient<{
|
|
25
25
|
name: string;
|
|
26
26
|
id: string;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
section: string;
|
|
31
|
-
syllabus: string | null;
|
|
27
|
+
students: {
|
|
28
|
+
id: string;
|
|
29
|
+
}[];
|
|
32
30
|
} | null, null, import("@prisma/client/runtime/library.js").DefaultArgs, {
|
|
33
31
|
datasources: {
|
|
34
32
|
db: {
|
|
@@ -62,12 +60,23 @@ export declare function findAttendanceByEventId(eventId: string): import(".prism
|
|
|
62
60
|
};
|
|
63
61
|
}>;
|
|
64
62
|
/** @returns Attendance for class and event (eventId null = class-level). */
|
|
65
|
-
export declare function findAttendanceByClassAndEvent(classId: string, eventId: string | null): import(".prisma/client").Prisma.Prisma__AttendanceClient<{
|
|
63
|
+
export declare function findAttendanceByClassAndEvent(classId: string, eventId: string | null): import(".prisma/client").Prisma.Prisma__AttendanceClient<({
|
|
64
|
+
event: {
|
|
65
|
+
name: string | null;
|
|
66
|
+
id: string;
|
|
67
|
+
} | null;
|
|
68
|
+
late: {
|
|
69
|
+
id: string;
|
|
70
|
+
}[];
|
|
71
|
+
absent: {
|
|
72
|
+
id: string;
|
|
73
|
+
}[];
|
|
74
|
+
} & {
|
|
66
75
|
id: string;
|
|
67
76
|
classId: string;
|
|
68
77
|
eventId: string | null;
|
|
69
78
|
date: Date;
|
|
70
|
-
} | null, null, import("@prisma/client/runtime/library.js").DefaultArgs, {
|
|
79
|
+
}) | null, null, import("@prisma/client/runtime/library.js").DefaultArgs, {
|
|
71
80
|
datasources: {
|
|
72
81
|
db: {
|
|
73
82
|
url: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attendance.d.ts","sourceRoot":"/","sources":["models/attendance.ts"],"names":[],"mappings":"AAkFA,mDAAmD;AACnD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;GAuBpD;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"attendance.d.ts","sourceRoot":"/","sources":["models/attendance.ts"],"names":[],"mappings":"AAkFA,mDAAmD;AACnD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;GAuBpD;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;;;;;;;;;;GAYtE;AAED,mCAAmC;AACnC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM;;;;;;;;;;KAIlD;AAED,+CAA+C;AAC/C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM;;;;;;;;;;;GAItD;AAED,4EAA4E;AAC5E,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;;GAiBpF;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MASnE;AAED,mCAAmC;AACnC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgBA;AAED,8CAA8C;AAC9C,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;;;;;;;;;;;GAQA;AAED,mDAAmD;AACnD,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAWvE"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Attendance model – attendance records, present/late/absent students per event.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
5
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a57d4718-2b2b-536c-90dc-37d792317353")}catch(e){}}();
|
|
6
6
|
import { prisma } from "../lib/prisma.js";
|
|
7
7
|
import { classTeacherOrSchoolAdminWhere } from "./access.js";
|
|
8
8
|
const attendanceInclude = {
|
|
@@ -111,6 +111,11 @@ export function findClassWithTeacher(classId, teacherId) {
|
|
|
111
111
|
id: classId,
|
|
112
112
|
...classTeacherOrSchoolAdminWhere(teacherId),
|
|
113
113
|
},
|
|
114
|
+
select: {
|
|
115
|
+
id: true,
|
|
116
|
+
name: true,
|
|
117
|
+
students: { select: { id: true } },
|
|
118
|
+
},
|
|
114
119
|
});
|
|
115
120
|
}
|
|
116
121
|
/** @returns Events for a class. */
|
|
@@ -132,6 +137,16 @@ export function findAttendanceByClassAndEvent(classId, eventId) {
|
|
|
132
137
|
classId,
|
|
133
138
|
eventId,
|
|
134
139
|
},
|
|
140
|
+
include: {
|
|
141
|
+
event: {
|
|
142
|
+
select: {
|
|
143
|
+
id: true,
|
|
144
|
+
name: true,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
late: { select: { id: true } },
|
|
148
|
+
absent: { select: { id: true } },
|
|
149
|
+
},
|
|
135
150
|
});
|
|
136
151
|
}
|
|
137
152
|
/** @returns Attendance records for class, optionally filtered by event. */
|
|
@@ -186,4 +201,4 @@ export function updateAttendance(id, data) {
|
|
|
186
201
|
});
|
|
187
202
|
}
|
|
188
203
|
//# sourceMappingURL=attendance.js.map
|
|
189
|
-
//# debugId=
|
|
204
|
+
//# debugId=a57d4718-2b2b-536c-90dc-37d792317353
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attendance.js","sources":["models/attendance.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Attendance model – attendance records, present/late/absent students per event.\n */\nimport { prisma } from \"../lib/prisma.js\";\nimport { classTeacherOrSchoolAdminWhere } from \"./access.js\";\n\nconst attendanceInclude = {\n event: {\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n color: true,\n },\n },\n present: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n bio: true,\n location: true,\n website: true,\n },\n },\n },\n },\n late: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n bio: true,\n location: true,\n website: true,\n },\n },\n },\n },\n absent: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n bio: true,\n location: true,\n website: true,\n },\n },\n },\n },\n} as const;\n\nconst attendanceUpdateInclude = {\n event: {\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n },\n },\n present: { select: { id: true, username: true } },\n late: { select: { id: true, username: true } },\n absent: { select: { id: true, username: true } },\n} as const;\n\n/** @returns Class with students for attendance. */\nexport function findClassWithStudents(classId: string) {\n return prisma.class.findUnique({\n where: { id: classId },\n select: {\n id: true,\n students: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n bio: true,\n location: true,\n website: true,\n },\n },\n },\n },\n },\n });\n}\n\n/** @returns Class if user is a teacher or school admin. */\nexport function findClassWithTeacher(classId: string, teacherId: string) {\n return prisma.class.findFirst({\n where: {\n id: classId,\n ...classTeacherOrSchoolAdminWhere(teacherId),\n },\n });\n}\n\n/** @returns Events for a class. */\nexport function findEventsByClassId(classId: string) {\n return prisma.event.findMany({\n where: { classId },\n });\n}\n\n/** @returns Attendance record for an event. */\nexport function findAttendanceByEventId(eventId: string) {\n return prisma.attendance.findFirst({\n where: { eventId },\n });\n}\n\n/** @returns Attendance for class and event (eventId null = class-level). */\nexport function findAttendanceByClassAndEvent(classId: string, eventId: string | null) {\n return prisma.attendance.findFirst({\n where: {\n classId,\n eventId,\n },\n });\n}\n\n/** @returns Attendance records for class, optionally filtered by event. */\nexport function findManyAttendance(classId: string, eventId?: string) {\n return prisma.attendance.findMany({\n where: {\n classId,\n ...(eventId ? { eventId } : {}),\n },\n include: attendanceInclude,\n orderBy: { date: \"desc\" },\n });\n}\n\n/** Create an attendance record. */\nexport function createAttendance(data: {\n classId: string;\n eventId?: string | null;\n presentIds: string[];\n lateIds?: string[];\n absentIds?: string[];\n}) {\n return prisma.attendance.create({\n data: {\n classId: data.classId,\n eventId: data.eventId ?? undefined,\n date: new Date(),\n present: { connect: data.presentIds.map((id) => ({ id })) },\n late: data.lateIds?.length\n ? { connect: data.lateIds.map((id) => ({ id })) }\n : undefined,\n absent: data.absentIds?.length\n ? { connect: data.absentIds.map((id) => ({ id })) }\n : undefined,\n },\n include: attendanceUpdateInclude,\n });\n}\n\n/** Create attendance for a specific event. */\nexport function createAttendanceForEvent(data: {\n classId: string;\n eventId: string;\n presentIds: string[];\n}) {\n return prisma.attendance.create({\n data: {\n class: { connect: { id: data.classId } },\n event: { connect: { id: data.eventId } },\n present: { connect: data.presentIds.map((id) => ({ id })) },\n },\n });\n}\n\n/** Update attendance present/late/absent lists. */\nexport function updateAttendance(\n id: string,\n data: { presentIds: string[]; lateIds: string[]; absentIds: string[] }\n) {\n return prisma.attendance.update({\n where: { id },\n data: {\n present: { set: data.presentIds.map((id) => ({ id })) },\n late: { set: data.lateIds.map((id) => ({ id })) },\n absent: { set: data.absentIds.map((id) => ({ id })) },\n },\n include: attendanceUpdateInclude,\n });\n}\n"],"names":[],"mappings":"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","debug_id":"311ac412-3d37-5b5d-9c46-79a70ef935e2"}
|
|
1
|
+
{"version":3,"file":"attendance.js","sources":["models/attendance.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Attendance model – attendance records, present/late/absent students per event.\n */\nimport { prisma } from \"../lib/prisma.js\";\nimport { classTeacherOrSchoolAdminWhere } from \"./access.js\";\n\nconst attendanceInclude = {\n event: {\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n color: true,\n },\n },\n present: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n bio: true,\n location: true,\n website: true,\n },\n },\n },\n },\n late: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n bio: true,\n location: true,\n website: true,\n },\n },\n },\n },\n absent: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n bio: true,\n location: true,\n website: true,\n },\n },\n },\n },\n} as const;\n\nconst attendanceUpdateInclude = {\n event: {\n select: {\n id: true,\n name: true,\n startTime: true,\n endTime: true,\n location: true,\n },\n },\n present: { select: { id: true, username: true } },\n late: { select: { id: true, username: true } },\n absent: { select: { id: true, username: true } },\n} as const;\n\n/** @returns Class with students for attendance. */\nexport function findClassWithStudents(classId: string) {\n return prisma.class.findUnique({\n where: { id: classId },\n select: {\n id: true,\n students: {\n select: {\n id: true,\n username: true,\n profile: {\n select: {\n displayName: true,\n profilePicture: true,\n profilePictureThumbnail: true,\n bio: true,\n location: true,\n website: true,\n },\n },\n },\n },\n },\n });\n}\n\n/** @returns Class if user is a teacher or school admin. */\nexport function findClassWithTeacher(classId: string, teacherId: string) {\n return prisma.class.findFirst({\n where: {\n id: classId,\n ...classTeacherOrSchoolAdminWhere(teacherId),\n },\n select: {\n id: true,\n name: true,\n students: { select: { id: true } },\n },\n });\n}\n\n/** @returns Events for a class. */\nexport function findEventsByClassId(classId: string) {\n return prisma.event.findMany({\n where: { classId },\n });\n}\n\n/** @returns Attendance record for an event. */\nexport function findAttendanceByEventId(eventId: string) {\n return prisma.attendance.findFirst({\n where: { eventId },\n });\n}\n\n/** @returns Attendance for class and event (eventId null = class-level). */\nexport function findAttendanceByClassAndEvent(classId: string, eventId: string | null) {\n return prisma.attendance.findFirst({\n where: {\n classId,\n eventId,\n },\n include: {\n event: {\n select: {\n id: true,\n name: true,\n },\n },\n late: { select: { id: true } },\n absent: { select: { id: true } },\n },\n });\n}\n\n/** @returns Attendance records for class, optionally filtered by event. */\nexport function findManyAttendance(classId: string, eventId?: string) {\n return prisma.attendance.findMany({\n where: {\n classId,\n ...(eventId ? { eventId } : {}),\n },\n include: attendanceInclude,\n orderBy: { date: \"desc\" },\n });\n}\n\n/** Create an attendance record. */\nexport function createAttendance(data: {\n classId: string;\n eventId?: string | null;\n presentIds: string[];\n lateIds?: string[];\n absentIds?: string[];\n}) {\n return prisma.attendance.create({\n data: {\n classId: data.classId,\n eventId: data.eventId ?? undefined,\n date: new Date(),\n present: { connect: data.presentIds.map((id) => ({ id })) },\n late: data.lateIds?.length\n ? { connect: data.lateIds.map((id) => ({ id })) }\n : undefined,\n absent: data.absentIds?.length\n ? { connect: data.absentIds.map((id) => ({ id })) }\n : undefined,\n },\n include: attendanceUpdateInclude,\n });\n}\n\n/** Create attendance for a specific event. */\nexport function createAttendanceForEvent(data: {\n classId: string;\n eventId: string;\n presentIds: string[];\n}) {\n return prisma.attendance.create({\n data: {\n class: { connect: { id: data.classId } },\n event: { connect: { id: data.eventId } },\n present: { connect: data.presentIds.map((id) => ({ id })) },\n },\n });\n}\n\n/** Update attendance present/late/absent lists. */\nexport function updateAttendance(\n id: string,\n data: { presentIds: string[]; lateIds: string[]; absentIds: string[] }\n) {\n return prisma.attendance.update({\n where: { id },\n data: {\n present: { set: data.presentIds.map((id) => ({ id })) },\n late: { set: data.lateIds.map((id) => ({ id })) },\n absent: { set: data.absentIds.map((id) => ({ id })) },\n },\n include: attendanceUpdateInclude,\n });\n}\n"],"names":[],"mappings":"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","debug_id":"a57d4718-2b2b-536c-90dc-37d792317353"}
|
|
@@ -4,42 +4,42 @@ export declare function findConversationsByUserId(userId: string): import(".pris
|
|
|
4
4
|
id: string;
|
|
5
5
|
title: string;
|
|
6
6
|
} | null;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
messages: ({
|
|
8
|
+
sender: {
|
|
9
9
|
id: string;
|
|
10
10
|
username: string;
|
|
11
11
|
profile: {
|
|
12
12
|
displayName: string | null;
|
|
13
|
-
profilePicture: string | null;
|
|
14
13
|
} | null;
|
|
15
14
|
};
|
|
16
15
|
} & {
|
|
16
|
+
status: import(".prisma/client").$Enums.JobStatus | null;
|
|
17
|
+
meta: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
17
18
|
id: string;
|
|
18
|
-
|
|
19
|
-
userId: string;
|
|
19
|
+
createdAt: Date;
|
|
20
20
|
conversationId: string;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
lastViewedMentionAt: Date | null;
|
|
21
|
+
content: string;
|
|
22
|
+
senderId: string;
|
|
23
|
+
runJobId: string | null;
|
|
25
24
|
})[];
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
members: ({
|
|
26
|
+
user: {
|
|
28
27
|
id: string;
|
|
29
28
|
username: string;
|
|
30
29
|
profile: {
|
|
31
30
|
displayName: string | null;
|
|
31
|
+
profilePicture: string | null;
|
|
32
32
|
} | null;
|
|
33
33
|
};
|
|
34
34
|
} & {
|
|
35
|
-
status: import(".prisma/client").$Enums.JobStatus | null;
|
|
36
|
-
meta: import("@prisma/client/runtime/library.js").JsonValue | null;
|
|
37
35
|
id: string;
|
|
38
|
-
|
|
36
|
+
role: import(".prisma/client").$Enums.ConversationRole;
|
|
37
|
+
userId: string;
|
|
39
38
|
conversationId: string;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
joinedAt: Date;
|
|
40
|
+
hiddenAt: Date | null;
|
|
41
|
+
lastViewedAt: Date | null;
|
|
42
|
+
lastViewedMentionAt: Date | null;
|
|
43
43
|
})[];
|
|
44
44
|
} & {
|
|
45
45
|
type: import(".prisma/client").$Enums.ConversationType;
|
|
@@ -64,6 +64,22 @@ export declare function findUserByUsername(username: string): import(".prisma/cl
|
|
|
64
64
|
};
|
|
65
65
|
};
|
|
66
66
|
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Search users who share at least one active school membership with the
|
|
69
|
+
* requester and match the query by username or profile display name.
|
|
70
|
+
*
|
|
71
|
+
* The requester is always excluded so the result set can be used directly as
|
|
72
|
+
* conversation member suggestions.
|
|
73
|
+
*/
|
|
74
|
+
export declare function searchInstitutionConversationMembers(userId: string, query: string, limit: number): Promise<{
|
|
75
|
+
id: string;
|
|
76
|
+
username: string;
|
|
77
|
+
profile: {
|
|
78
|
+
displayName: string | null;
|
|
79
|
+
profilePicture: string | null;
|
|
80
|
+
profilePictureThumbnail: string | null;
|
|
81
|
+
} | null;
|
|
82
|
+
}[]>;
|
|
67
83
|
/** @returns User's DM conversations. */
|
|
68
84
|
export declare function findDmConversationsByUserId(userId: string): import(".prisma/client").Prisma.PrismaPromise<({
|
|
69
85
|
members: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"/","sources":["models/conversation.ts"],"names":[],"mappings":"AAmCA,mEAAmE;AACnE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAQvD;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,IAAI,yDASb;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,IAAI,yDAYb;AAED,qDAAqD;AACrD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM;;;;;;;;;GAKlD;AAED,wCAAwC;AACxC,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;MAUzD;AAED,0CAA0C;AAC1C,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE;;;KAW9D;AAED,sDAAsD;AACtD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BA;AAED,iDAAiD;AACjD,wBAAgB,6BAA6B,CAC3C,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuBf;AAED,sCAAsC;AACtC,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;;;;;;;;;;;;;;;GAQA;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;GAS5E;AAED,2CAA2C;AAC3C,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;GAM9E"}
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"/","sources":["models/conversation.ts"],"names":[],"mappings":"AAmCA,mEAAmE;AACnE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAQvD;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,IAAI,yDASb;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,IAAI,yDAYb;AAED,qDAAqD;AACrD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM;;;;;;;;;GAKlD;AAED;;;;;;GAMG;AACH,wBAAsB,oCAAoC,CACxD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM;;;;;;;;KA0Cd;AAED,wCAAwC;AACxC,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;MAUzD;AAED,0CAA0C;AAC1C,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE;;;KAW9D;AAED,sDAAsD;AACtD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BA;AAED,iDAAiD;AACjD,wBAAgB,6BAA6B,CAC3C,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuBf;AAED,sCAAsC;AACtC,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;;;;;;;;;;;;;;;GAQA;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;GAS5E;AAED,2CAA2C;AAC3C,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;GAM9E"}
|