@studious-lms/server 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/.coderabbit.yaml +4 -1
  2. package/.env.example +6 -0
  3. package/.env.test.example +2 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +101 -76
  6. package/dist/index.js.map +1 -1
  7. package/dist/lib/config/cors.d.ts +16 -0
  8. package/dist/lib/config/cors.d.ts.map +1 -0
  9. package/dist/lib/config/cors.js +75 -0
  10. package/dist/lib/config/cors.js.map +1 -0
  11. package/dist/lib/config/env.d.ts +14 -0
  12. package/dist/lib/config/env.d.ts.map +1 -1
  13. package/dist/lib/config/env.js +9 -2
  14. package/dist/lib/config/env.js.map +1 -1
  15. package/dist/lib/fileUpload.d.ts +10 -2
  16. package/dist/lib/fileUpload.d.ts.map +1 -1
  17. package/dist/lib/fileUpload.js +38 -6
  18. package/dist/lib/fileUpload.js.map +1 -1
  19. package/dist/lib/prisma.d.ts +14 -2
  20. package/dist/lib/prisma.d.ts.map +1 -1
  21. package/dist/lib/prisma.js +27 -8
  22. package/dist/lib/prisma.js.map +1 -1
  23. package/dist/middleware/auth.d.ts.map +1 -1
  24. package/dist/middleware/auth.js +18 -5
  25. package/dist/middleware/auth.js.map +1 -1
  26. package/dist/middleware/security.d.ts.map +1 -1
  27. package/dist/middleware/security.js +3 -3
  28. package/dist/middleware/security.js.map +1 -1
  29. package/dist/models/agenda.d.ts +16 -16
  30. package/dist/models/announcement.d.ts +59 -23
  31. package/dist/models/announcement.d.ts.map +1 -1
  32. package/dist/models/assignment.d.ts +363 -276
  33. package/dist/models/assignment.d.ts.map +1 -1
  34. package/dist/models/attendance.d.ts +63 -21
  35. package/dist/models/attendance.d.ts.map +1 -1
  36. package/dist/models/auth.d.ts +115 -26
  37. package/dist/models/auth.d.ts.map +1 -1
  38. package/dist/models/auth.js +53 -30
  39. package/dist/models/auth.js.map +1 -1
  40. package/dist/models/class.d.ts +115 -65
  41. package/dist/models/class.d.ts.map +1 -1
  42. package/dist/models/class.js +16 -4
  43. package/dist/models/class.js.map +1 -1
  44. package/dist/models/comment.d.ts +52 -16
  45. package/dist/models/comment.d.ts.map +1 -1
  46. package/dist/models/conversation.d.ts +46 -16
  47. package/dist/models/conversation.d.ts.map +1 -1
  48. package/dist/models/event.d.ts +107 -53
  49. package/dist/models/event.d.ts.map +1 -1
  50. package/dist/models/file.d.ts +213 -165
  51. package/dist/models/file.d.ts.map +1 -1
  52. package/dist/models/folder.d.ts +161 -77
  53. package/dist/models/folder.d.ts.map +1 -1
  54. package/dist/models/labChat.d.ts +73 -31
  55. package/dist/models/labChat.d.ts.map +1 -1
  56. package/dist/models/marketing.d.ts +25 -7
  57. package/dist/models/marketing.d.ts.map +1 -1
  58. package/dist/models/message.d.ts +31 -13
  59. package/dist/models/message.d.ts.map +1 -1
  60. package/dist/models/newtonChat.d.ts +34 -10
  61. package/dist/models/newtonChat.d.ts.map +1 -1
  62. package/dist/models/notification.d.ts +29 -10
  63. package/dist/models/notification.d.ts.map +1 -1
  64. package/dist/models/notification.js +13 -9
  65. package/dist/models/notification.js.map +1 -1
  66. package/dist/models/section.d.ts +71 -23
  67. package/dist/models/section.d.ts.map +1 -1
  68. package/dist/models/user.d.ts +27 -9
  69. package/dist/models/user.d.ts.map +1 -1
  70. package/dist/models/worksheet.d.ts +606 -106
  71. package/dist/models/worksheet.d.ts.map +1 -1
  72. package/dist/models/worksheet.js +168 -2
  73. package/dist/models/worksheet.js.map +1 -1
  74. package/dist/pipelines/aiLabChat.d.ts +22 -2
  75. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  76. package/dist/pipelines/aiLabChat.js +133 -95
  77. package/dist/pipelines/aiLabChat.js.map +1 -1
  78. package/dist/pipelines/aiLabChatContract.d.ts +25 -25
  79. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
  80. package/dist/pipelines/aiNewtonChat.js +25 -14
  81. package/dist/pipelines/aiNewtonChat.js.map +1 -1
  82. package/dist/pipelines/gradeWorksheet.d.ts +8 -8
  83. package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
  84. package/dist/pipelines/gradeWorksheet.js +12 -5
  85. package/dist/pipelines/gradeWorksheet.js.map +1 -1
  86. package/dist/pipelines/labChatPrompt.d.ts +27 -0
  87. package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
  88. package/dist/pipelines/labChatPrompt.js +143 -69
  89. package/dist/pipelines/labChatPrompt.js.map +1 -1
  90. package/dist/routers/_app.d.ts +1579 -1257
  91. package/dist/routers/_app.d.ts.map +1 -1
  92. package/dist/routers/agenda.d.ts +16 -16
  93. package/dist/routers/announcement.d.ts +19 -19
  94. package/dist/routers/assignment.d.ts +307 -291
  95. package/dist/routers/assignment.d.ts.map +1 -1
  96. package/dist/routers/assignment.js +3 -2
  97. package/dist/routers/assignment.js.map +1 -1
  98. package/dist/routers/attendance.d.ts +7 -7
  99. package/dist/routers/auth.d.ts +1 -1
  100. package/dist/routers/class.d.ts +79 -72
  101. package/dist/routers/class.d.ts.map +1 -1
  102. package/dist/routers/class.js +3 -3
  103. package/dist/routers/class.js.map +1 -1
  104. package/dist/routers/comment.d.ts +6 -6
  105. package/dist/routers/conversation.d.ts +11 -11
  106. package/dist/routers/event.d.ts +35 -35
  107. package/dist/routers/file.d.ts +12 -12
  108. package/dist/routers/folder.d.ts +54 -54
  109. package/dist/routers/labChat.d.ts +18 -12
  110. package/dist/routers/labChat.d.ts.map +1 -1
  111. package/dist/routers/labChat.js +5 -3
  112. package/dist/routers/labChat.js.map +1 -1
  113. package/dist/routers/marketing.d.ts +2 -2
  114. package/dist/routers/message.d.ts +33 -2
  115. package/dist/routers/message.d.ts.map +1 -1
  116. package/dist/routers/message.js +27 -4
  117. package/dist/routers/message.js.map +1 -1
  118. package/dist/routers/newtonChat.d.ts +7 -1
  119. package/dist/routers/newtonChat.d.ts.map +1 -1
  120. package/dist/routers/newtonChat.js +5 -4
  121. package/dist/routers/newtonChat.js.map +1 -1
  122. package/dist/routers/notifications.d.ts +13 -6
  123. package/dist/routers/notifications.d.ts.map +1 -1
  124. package/dist/routers/notifications.js +4 -4
  125. package/dist/routers/notifications.js.map +1 -1
  126. package/dist/routers/section.d.ts +7 -7
  127. package/dist/routers/studentProgress.d.ts +86 -0
  128. package/dist/routers/studentProgress.d.ts.map +1 -1
  129. package/dist/routers/studentProgress.js +14 -4
  130. package/dist/routers/studentProgress.js.map +1 -1
  131. package/dist/routers/user.d.ts +1 -1
  132. package/dist/routers/worksheet.d.ts +64 -62
  133. package/dist/routers/worksheet.d.ts.map +1 -1
  134. package/dist/routers/worksheet.js +18 -16
  135. package/dist/routers/worksheet.js.map +1 -1
  136. package/dist/seedDatabase.d.ts +1 -1
  137. package/dist/services/agenda.d.ts +16 -16
  138. package/dist/services/announcement.d.ts +8 -8
  139. package/dist/services/assignment.d.ts +299 -283
  140. package/dist/services/assignment.d.ts.map +1 -1
  141. package/dist/services/assignment.js +24 -5
  142. package/dist/services/assignment.js.map +1 -1
  143. package/dist/services/attendance.d.ts +7 -7
  144. package/dist/services/auth.d.ts +2 -2
  145. package/dist/services/auth.d.ts.map +1 -1
  146. package/dist/services/auth.js +19 -12
  147. package/dist/services/auth.js.map +1 -1
  148. package/dist/services/class.d.ts +74 -68
  149. package/dist/services/class.d.ts.map +1 -1
  150. package/dist/services/class.js +6 -3
  151. package/dist/services/class.js.map +1 -1
  152. package/dist/services/comment.d.ts +6 -6
  153. package/dist/services/conversation.d.ts +11 -11
  154. package/dist/services/event.d.ts +31 -31
  155. package/dist/services/file.d.ts +12 -12
  156. package/dist/services/file.d.ts.map +1 -1
  157. package/dist/services/file.js +7 -2
  158. package/dist/services/file.js.map +1 -1
  159. package/dist/services/folder.d.ts +52 -52
  160. package/dist/services/labChat.d.ts +18 -12
  161. package/dist/services/labChat.d.ts.map +1 -1
  162. package/dist/services/labChat.js +30 -18
  163. package/dist/services/labChat.js.map +1 -1
  164. package/dist/services/marketing.d.ts +2 -2
  165. package/dist/services/message.d.ts +30 -0
  166. package/dist/services/message.d.ts.map +1 -1
  167. package/dist/services/message.js +97 -21
  168. package/dist/services/message.js.map +1 -1
  169. package/dist/services/newtonChat.d.ts +6 -1
  170. package/dist/services/newtonChat.d.ts.map +1 -1
  171. package/dist/services/newtonChat.js +36 -18
  172. package/dist/services/newtonChat.js.map +1 -1
  173. package/dist/services/notification.d.ts +16 -9
  174. package/dist/services/notification.d.ts.map +1 -1
  175. package/dist/services/notification.js +24 -9
  176. package/dist/services/notification.js.map +1 -1
  177. package/dist/services/section.d.ts +6 -6
  178. package/dist/services/studentProgress.d.ts +75 -0
  179. package/dist/services/studentProgress.d.ts.map +1 -1
  180. package/dist/services/studentProgress.js +300 -107
  181. package/dist/services/studentProgress.js.map +1 -1
  182. package/dist/services/worksheet.d.ts +64 -64
  183. package/dist/services/worksheet.d.ts.map +1 -1
  184. package/dist/services/worksheet.js +138 -54
  185. package/dist/services/worksheet.js.map +1 -1
  186. package/dist/trpc.d.ts.map +1 -1
  187. package/dist/trpc.js +11 -17
  188. package/dist/trpc.js.map +1 -1
  189. package/dist/utils/inference.d.ts +9 -12
  190. package/dist/utils/inference.d.ts.map +1 -1
  191. package/dist/utils/inference.js +135 -95
  192. package/dist/utils/inference.js.map +1 -1
  193. package/package.json +1 -1
  194. package/prisma/migrations/20260410124000_add_submission_recommendation_state/migration.sql +14 -0
  195. package/prisma/migrations/20260415103500_add_session_type/migration.sql +33 -0
  196. package/prisma/migrations/20260415133000_add_ai_usage_logs/migration.sql +19 -0
  197. package/prisma/schema.prisma +41 -1
  198. package/scripts/test-pre-push.ts +6 -2
  199. package/src/index.ts +119 -79
  200. package/src/lib/config/cors.ts +96 -0
  201. package/src/lib/config/env.ts +12 -1
  202. package/src/lib/fileUpload.ts +55 -5
  203. package/src/lib/prisma.ts +25 -6
  204. package/src/middleware/auth.ts +19 -4
  205. package/src/middleware/security.ts +1 -1
  206. package/src/models/auth.ts +59 -29
  207. package/src/models/class.ts +15 -4
  208. package/src/models/notification.ts +13 -7
  209. package/src/models/worksheet.ts +202 -0
  210. package/src/pipelines/aiLabChat.ts +183 -104
  211. package/src/pipelines/aiNewtonChat.ts +24 -14
  212. package/src/pipelines/gradeWorksheet.ts +10 -2
  213. package/src/pipelines/labChatPrompt.ts +196 -68
  214. package/src/routers/assignment.ts +1 -0
  215. package/src/routers/class.ts +2 -2
  216. package/src/routers/labChat.ts +3 -1
  217. package/src/routers/message.ts +38 -1
  218. package/src/routers/newtonChat.ts +4 -2
  219. package/src/routers/notifications.ts +2 -2
  220. package/src/routers/studentProgress.ts +25 -1
  221. package/src/routers/worksheet.ts +31 -19
  222. package/src/services/assignment.ts +30 -2
  223. package/src/services/auth.ts +26 -12
  224. package/src/services/class.ts +4 -1
  225. package/src/services/file.ts +6 -0
  226. package/src/services/labChat.ts +42 -18
  227. package/src/services/message.ts +163 -18
  228. package/src/services/newtonChat.ts +49 -18
  229. package/src/services/notification.ts +27 -8
  230. package/src/services/studentProgress.ts +425 -121
  231. package/src/services/worksheet.ts +191 -51
  232. package/src/trpc.ts +12 -18
  233. package/src/utils/inference.ts +205 -112
  234. package/tests/globalSetup.ts +13 -4
  235. package/tests/lib/cors.test.ts +103 -0
  236. package/tests/pipelines/aiLabChat.test.ts +64 -84
  237. package/tests/routers/auth.test.ts +120 -17
  238. package/tests/routers/class.test.ts +7 -1
  239. package/tests/routers/message.test.ts +236 -9
  240. package/tests/routers/newtonChat.test.ts +81 -0
  241. package/tests/routers/notification.test.ts +12 -0
  242. package/tests/routers/studentProgress.test.ts +2 -31
  243. package/tests/routers/worksheet.test.ts +194 -0
  244. package/tests/setup.ts +22 -5
  245. package/tests/utils/aiLabChatPrompt.test.ts +114 -6
  246. package/tests/utils/inference.test.ts +218 -0
  247. package/tests/utils/studentProgress.test.ts +361 -0
  248. package/vitest.unit.config.ts +1 -0
@@ -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]="d9abebcd-0879-54b7-8f35-66b5ee7a0544")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e27a3dc9-6e2a-5b94-b404-01bf23ea1d5f")}catch(e){}}();
3
3
  import helmet from 'helmet';
4
4
  import rateLimit from 'express-rate-limit';
5
5
  const isDevelopment = process.env.NODE_ENV === 'development';
@@ -17,7 +17,7 @@ const rateLimitHandler = (req, res) => {
17
17
  };
18
18
  // General API rate limiter - applies to all routes
19
19
  export const generalLimiter = rateLimit({
20
- windowMs: 10 * 60, // 10 minutes
20
+ windowMs: 10 * 60 * 1000, // 10 minutes
21
21
  max: 100, // Limit each IP to 100 requests per windowMs
22
22
  message: 'Too many requests from this IP, please try again later.',
23
23
  standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
@@ -74,4 +74,4 @@ export const helmetConfig = helmet({
74
74
  },
75
75
  });
76
76
  //# sourceMappingURL=security.js.map
77
- //# debugId=d9abebcd-0879-54b7-8f35-66b5ee7a0544
77
+ //# debugId=e27a3dc9-6e2a-5b94-b404-01bf23ea1d5f
@@ -1 +1 @@
1
- {"version":3,"file":"security.js","sources":["middleware/security.ts"],"sourceRoot":"/","sourcesContent":["import helmet from 'helmet';\nimport rateLimit from 'express-rate-limit';\nimport type { Request, Response } from 'express';\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\n// Custom handler for rate limit errors that returns JSON\n// This format can be intercepted on the frontend with:\n// error.data?.code === 'TOO_MANY_REQUESTS' || error.data?.httpStatus === 429\nconst rateLimitHandler = (req: Request, res: Response) => {\n // Return JSON structure that can be intercepted on frontend with:\n // error.data?.code === 'TOO_MANY_REQUESTS' || error.data?.httpStatus === 429\n // When tRPC wraps this, the response body becomes error.data, so we put code/httpStatus at top level\n res.status(429).json({\n code: 'TOO_MANY_REQUESTS',\n message: 'Too many requests, please try again later.',\n });\n};\n\n// General API rate limiter - applies to all routes\nexport const generalLimiter = rateLimit({\n windowMs: 10 * 60, // 10 minutes\n max: 100, // Limit each IP to 100 requests per windowMs\n message: 'Too many requests from this IP, please try again later.',\n standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers\n legacyHeaders: false, // Disable the `X-RateLimit-*` headers\n handler: rateLimitHandler,\n skip: (req) => {\n // Skip rate limiting for health checks\n return req.path === '/health' || req.method === 'OPTIONS';\n },\n});\n\n// Stricter rate limiter for authentication endpoints\nexport const authLimiter = rateLimit({\n windowMs: 5 * 60 * 1000, // 5 minutes\n max: 5, // Limit each IP to 5 login attempts per windowMs\n message: 'Too many authentication attempts, please try again later.',\n standardHeaders: true,\n legacyHeaders: false,\n skipSuccessfulRequests: true, // Don't count successful requests\n handler: rateLimitHandler,\n});\n\n// File upload rate limiter\nexport const uploadLimiter = rateLimit({\n windowMs: 30 * 60 * 1000, // 30 minutes\n max: 50, // Limit each IP to 50 uploads per hour\n message: 'Too many file uploads, please try again later.',\n standardHeaders: true,\n legacyHeaders: false,\n handler: rateLimitHandler,\n});\n\n// Helmet configuration\nexport const helmetConfig = helmet({\n contentSecurityPolicy: {\n directives: {\n defaultSrc: [\"'self'\"],\n styleSrc: [\"'self'\", \"'unsafe-inline'\"], // Allow inline styles for tRPC panel\n // Allow inline scripts only in development (for tRPC panel)\n // In production, keep strict CSP without unsafe-inline\n scriptSrc: isDevelopment \n ? [\"'self'\", \"'unsafe-inline'\"] \n : [\"'self'\"],\n imgSrc: [\"'self'\", \"data:\", \"https:\"], // Allow images from any HTTPS source\n connectSrc: [\"'self'\", \"https://*.sentry.io\"], // Allow Sentry connections\n fontSrc: [\"'self'\", \"data:\"],\n objectSrc: [\"'none'\"],\n mediaSrc: [\"'self'\"],\n frameSrc: [\"'none'\"],\n },\n },\n crossOriginEmbedderPolicy: false, // Disable if you need to embed resources\n hsts: {\n maxAge: 31536000, // 1 year\n includeSubDomains: true,\n preload: true,\n },\n});"],"names":[],"mappings":";;AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAG3C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;AAE7D,yDAAyD;AACzD,uDAAuD;AACvD,6EAA6E;AAC7E,MAAM,gBAAgB,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACvD,kEAAkE;IAClE,6EAA6E;IAC7E,qGAAqG;IACrG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,4CAA4C;KACtD,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,mDAAmD;AACnD,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;IACtC,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,aAAa;IAChC,GAAG,EAAE,GAAG,EAAE,6CAA6C;IACvD,OAAO,EAAE,yDAAyD;IAClE,eAAe,EAAE,IAAI,EAAE,sDAAsD;IAC7E,aAAa,EAAE,KAAK,EAAE,sCAAsC;IAC5D,OAAO,EAAE,gBAAgB;IACzB,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;QACZ,uCAAuC;QACvC,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC;IAC5D,CAAC;CACF,CAAC,CAAC;AAEH,qDAAqD;AACrD,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;IACnC,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACrC,GAAG,EAAE,CAAC,EAAE,iDAAiD;IACzD,OAAO,EAAE,2DAA2D;IACpE,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,KAAK;IACpB,sBAAsB,EAAE,IAAI,EAAE,kCAAkC;IAChE,OAAO,EAAE,gBAAgB;CAC1B,CAAC,CAAC;AAEH,2BAA2B;AAC3B,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;IACrC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACvC,GAAG,EAAE,EAAE,EAAE,uCAAuC;IAChD,OAAO,EAAE,gDAAgD;IACzD,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,KAAK;IACpB,OAAO,EAAE,gBAAgB;CAC1B,CAAC,CAAC;AAEH,uBAAuB;AACvB,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC;IACjC,qBAAqB,EAAE;QACrB,UAAU,EAAE;YACV,UAAU,EAAE,CAAC,QAAQ,CAAC;YACtB,QAAQ,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAAE,qCAAqC;YAC9E,4DAA4D;YAC5D,uDAAuD;YACvD,SAAS,EAAE,aAAa;gBACtB,CAAC,CAAC,CAAC,QAAQ,EAAE,iBAAiB,CAAC;gBAC/B,CAAC,CAAC,CAAC,QAAQ,CAAC;YACd,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,qCAAqC;YAC5E,UAAU,EAAE,CAAC,QAAQ,EAAE,qBAAqB,CAAC,EAAE,2BAA2B;YAC1E,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;YAC5B,SAAS,EAAE,CAAC,QAAQ,CAAC;YACrB,QAAQ,EAAE,CAAC,QAAQ,CAAC;YACpB,QAAQ,EAAE,CAAC,QAAQ,CAAC;SACrB;KACF;IACD,yBAAyB,EAAE,KAAK,EAAE,yCAAyC;IAC3E,IAAI,EAAE;QACJ,MAAM,EAAE,QAAQ,EAAE,SAAS;QAC3B,iBAAiB,EAAE,IAAI;QACvB,OAAO,EAAE,IAAI;KACd;CACF,CAAC,CAAC","debug_id":"d9abebcd-0879-54b7-8f35-66b5ee7a0544"}
1
+ {"version":3,"file":"security.js","sources":["middleware/security.ts"],"sourceRoot":"/","sourcesContent":["import helmet from 'helmet';\nimport rateLimit from 'express-rate-limit';\nimport type { Request, Response } from 'express';\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\n// Custom handler for rate limit errors that returns JSON\n// This format can be intercepted on the frontend with:\n// error.data?.code === 'TOO_MANY_REQUESTS' || error.data?.httpStatus === 429\nconst rateLimitHandler = (req: Request, res: Response) => {\n // Return JSON structure that can be intercepted on frontend with:\n // error.data?.code === 'TOO_MANY_REQUESTS' || error.data?.httpStatus === 429\n // When tRPC wraps this, the response body becomes error.data, so we put code/httpStatus at top level\n res.status(429).json({\n code: 'TOO_MANY_REQUESTS',\n message: 'Too many requests, please try again later.',\n });\n};\n\n// General API rate limiter - applies to all routes\nexport const generalLimiter = rateLimit({\n windowMs: 10 * 60 * 1000, // 10 minutes\n max: 100, // Limit each IP to 100 requests per windowMs\n message: 'Too many requests from this IP, please try again later.',\n standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers\n legacyHeaders: false, // Disable the `X-RateLimit-*` headers\n handler: rateLimitHandler,\n skip: (req) => {\n // Skip rate limiting for health checks\n return req.path === '/health' || req.method === 'OPTIONS';\n },\n});\n\n// Stricter rate limiter for authentication endpoints\nexport const authLimiter = rateLimit({\n windowMs: 5 * 60 * 1000, // 5 minutes\n max: 5, // Limit each IP to 5 login attempts per windowMs\n message: 'Too many authentication attempts, please try again later.',\n standardHeaders: true,\n legacyHeaders: false,\n skipSuccessfulRequests: true, // Don't count successful requests\n handler: rateLimitHandler,\n});\n\n// File upload rate limiter\nexport const uploadLimiter = rateLimit({\n windowMs: 30 * 60 * 1000, // 30 minutes\n max: 50, // Limit each IP to 50 uploads per hour\n message: 'Too many file uploads, please try again later.',\n standardHeaders: true,\n legacyHeaders: false,\n handler: rateLimitHandler,\n});\n\n// Helmet configuration\nexport const helmetConfig = helmet({\n contentSecurityPolicy: {\n directives: {\n defaultSrc: [\"'self'\"],\n styleSrc: [\"'self'\", \"'unsafe-inline'\"], // Allow inline styles for tRPC panel\n // Allow inline scripts only in development (for tRPC panel)\n // In production, keep strict CSP without unsafe-inline\n scriptSrc: isDevelopment \n ? [\"'self'\", \"'unsafe-inline'\"] \n : [\"'self'\"],\n imgSrc: [\"'self'\", \"data:\", \"https:\"], // Allow images from any HTTPS source\n connectSrc: [\"'self'\", \"https://*.sentry.io\"], // Allow Sentry connections\n fontSrc: [\"'self'\", \"data:\"],\n objectSrc: [\"'none'\"],\n mediaSrc: [\"'self'\"],\n frameSrc: [\"'none'\"],\n },\n },\n crossOriginEmbedderPolicy: false, // Disable if you need to embed resources\n hsts: {\n maxAge: 31536000, // 1 year\n includeSubDomains: true,\n preload: true,\n },\n});"],"names":[],"mappings":";;AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAG3C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;AAE7D,yDAAyD;AACzD,uDAAuD;AACvD,6EAA6E;AAC7E,MAAM,gBAAgB,GAAG,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACvD,kEAAkE;IAClE,6EAA6E;IAC7E,qGAAqG;IACrG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,4CAA4C;KACtD,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,mDAAmD;AACnD,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;IACtC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACvC,GAAG,EAAE,GAAG,EAAE,6CAA6C;IACvD,OAAO,EAAE,yDAAyD;IAClE,eAAe,EAAE,IAAI,EAAE,sDAAsD;IAC7E,aAAa,EAAE,KAAK,EAAE,sCAAsC;IAC5D,OAAO,EAAE,gBAAgB;IACzB,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;QACZ,uCAAuC;QACvC,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC;IAC5D,CAAC;CACF,CAAC,CAAC;AAEH,qDAAqD;AACrD,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;IACnC,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACrC,GAAG,EAAE,CAAC,EAAE,iDAAiD;IACzD,OAAO,EAAE,2DAA2D;IACpE,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,KAAK;IACpB,sBAAsB,EAAE,IAAI,EAAE,kCAAkC;IAChE,OAAO,EAAE,gBAAgB;CAC1B,CAAC,CAAC;AAEH,2BAA2B;AAC3B,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;IACrC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACvC,GAAG,EAAE,EAAE,EAAE,uCAAuC;IAChD,OAAO,EAAE,gDAAgD;IACzD,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,KAAK;IACpB,OAAO,EAAE,gBAAgB;CAC1B,CAAC,CAAC;AAEH,uBAAuB;AACvB,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC;IACjC,qBAAqB,EAAE;QACrB,UAAU,EAAE;YACV,UAAU,EAAE,CAAC,QAAQ,CAAC;YACtB,QAAQ,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAAE,qCAAqC;YAC9E,4DAA4D;YAC5D,uDAAuD;YACvD,SAAS,EAAE,aAAa;gBACtB,CAAC,CAAC,CAAC,QAAQ,EAAE,iBAAiB,CAAC;gBAC/B,CAAC,CAAC,CAAC,QAAQ,CAAC;YACd,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,qCAAqC;YAC5E,UAAU,EAAE,CAAC,QAAQ,EAAE,qBAAqB,CAAC,EAAE,2BAA2B;YAC1E,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;YAC5B,SAAS,EAAE,CAAC,QAAQ,CAAC;YACrB,QAAQ,EAAE,CAAC,QAAQ,CAAC;YACpB,QAAQ,EAAE,CAAC,QAAQ,CAAC;SACrB;KACF;IACD,yBAAyB,EAAE,KAAK,EAAE,yCAAyC;IAC3E,IAAI,EAAE;QACJ,MAAM,EAAE,QAAQ,EAAE,SAAS;QAC3B,iBAAiB,EAAE,IAAI;QACvB,OAAO,EAAE,IAAI;KACd;CACF,CAAC,CAAC","debug_id":"e27a3dc9-6e2a-5b94-b404-01bf23ea1d5f"}
@@ -1,9 +1,9 @@
1
1
  /** @returns Personal events (no class) for user in date range. */
2
2
  export declare function findPersonalEvents(userId: string, rangeStart: Date, rangeEnd: Date): import(".prisma/client").Prisma.PrismaPromise<({
3
3
  class: {
4
+ name: string;
4
5
  id: string;
5
6
  schoolId: string | null;
6
- name: string;
7
7
  subject: string;
8
8
  color: string | null;
9
9
  section: string;
@@ -13,13 +13,11 @@ export declare function findPersonalEvents(userId: string, rangeStart: Date, ran
13
13
  type: import(".prisma/client").$Enums.AssignmentType;
14
14
  id: string;
15
15
  createdAt: Date | null;
16
+ modifiedAt: Date | null;
16
17
  classId: string;
17
18
  title: string;
18
- dueDate: Date;
19
- maxGrade: number | null;
20
- eventId: string | null;
21
19
  instructions: string;
22
- modifiedAt: Date | null;
20
+ dueDate: Date;
23
21
  teacherId: string;
24
22
  acceptFiles: boolean;
25
23
  acceptExtendedResponse: boolean;
@@ -28,30 +26,32 @@ export declare function findPersonalEvents(userId: string, rangeStart: Date, ran
28
26
  aiPolicyLevel: number;
29
27
  sectionId: string | null;
30
28
  graded: boolean;
29
+ maxGrade: number | null;
31
30
  weight: number;
32
31
  inProgress: boolean;
33
32
  template: boolean;
33
+ eventId: string | null;
34
34
  markSchemeId: string | null;
35
35
  order: number | null;
36
36
  gradingBoundaryId: string | null;
37
37
  }[];
38
38
  } & {
39
+ name: string | null;
39
40
  id: string;
40
41
  userId: string | null;
41
- location: string | null;
42
- classId: string | null;
43
- name: string | null;
44
42
  color: string | null;
43
+ classId: string | null;
45
44
  startTime: Date;
46
45
  endTime: Date;
46
+ location: string | null;
47
47
  remarks: string | null;
48
48
  })[]>;
49
49
  /** @returns Class events for user's classes in date range. */
50
50
  export declare function findClassEvents(userId: string, rangeStart: Date, rangeEnd: Date): import(".prisma/client").Prisma.PrismaPromise<({
51
51
  class: {
52
+ name: string;
52
53
  id: string;
53
54
  schoolId: string | null;
54
- name: string;
55
55
  subject: string;
56
56
  color: string | null;
57
57
  section: string;
@@ -61,13 +61,11 @@ export declare function findClassEvents(userId: string, rangeStart: Date, rangeE
61
61
  type: import(".prisma/client").$Enums.AssignmentType;
62
62
  id: string;
63
63
  createdAt: Date | null;
64
+ modifiedAt: Date | null;
64
65
  classId: string;
65
66
  title: string;
66
- dueDate: Date;
67
- maxGrade: number | null;
68
- eventId: string | null;
69
67
  instructions: string;
70
- modifiedAt: Date | null;
68
+ dueDate: Date;
71
69
  teacherId: string;
72
70
  acceptFiles: boolean;
73
71
  acceptExtendedResponse: boolean;
@@ -76,22 +74,24 @@ export declare function findClassEvents(userId: string, rangeStart: Date, rangeE
76
74
  aiPolicyLevel: number;
77
75
  sectionId: string | null;
78
76
  graded: boolean;
77
+ maxGrade: number | null;
79
78
  weight: number;
80
79
  inProgress: boolean;
81
80
  template: boolean;
81
+ eventId: string | null;
82
82
  markSchemeId: string | null;
83
83
  order: number | null;
84
84
  gradingBoundaryId: string | null;
85
85
  }[];
86
86
  } & {
87
+ name: string | null;
87
88
  id: string;
88
89
  userId: string | null;
89
- location: string | null;
90
- classId: string | null;
91
- name: string | null;
92
90
  color: string | null;
91
+ classId: string | null;
93
92
  startTime: Date;
94
93
  endTime: Date;
94
+ location: string | null;
95
95
  remarks: string | null;
96
96
  })[]>;
97
97
  //# sourceMappingURL=agenda.d.ts.map
@@ -35,8 +35,8 @@ export declare function findAnnouncementsByClassId(classId: string): import(".pr
35
35
  comments: number;
36
36
  };
37
37
  createdAt: Date;
38
- remarks: string;
39
38
  modifiedAt: Date | null;
39
+ remarks: string;
40
40
  teacher: {
41
41
  id: string;
42
42
  username: string;
@@ -49,8 +49,8 @@ export declare function findAnnouncementsByClassId(classId: string): import(".pr
49
49
  attachments: {
50
50
  path: string;
51
51
  type: string;
52
- id: string;
53
52
  name: string;
53
+ id: string;
54
54
  size: number | null;
55
55
  uploadedAt: Date | null;
56
56
  thumbnailId: string | null;
@@ -60,8 +60,8 @@ export declare function findAnnouncementsByClassId(classId: string): import(".pr
60
60
  export declare function findAnnouncementByIdAndClass(id: string, classId: string): import(".prisma/client").Prisma.Prisma__AnnouncementClient<{
61
61
  id: string;
62
62
  createdAt: Date;
63
- remarks: string;
64
63
  modifiedAt: Date | null;
64
+ remarks: string;
65
65
  teacher: {
66
66
  id: string;
67
67
  username: string;
@@ -74,13 +74,19 @@ export declare function findAnnouncementByIdAndClass(id: string, classId: string
74
74
  attachments: {
75
75
  path: string;
76
76
  type: string;
77
- id: string;
78
77
  name: string;
78
+ id: string;
79
79
  size: number | null;
80
80
  uploadedAt: Date | null;
81
81
  thumbnailId: string | null;
82
82
  }[];
83
- } | null, null, import("@prisma/client/runtime/library.js").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
83
+ } | null, null, import("@prisma/client/runtime/library.js").DefaultArgs, {
84
+ datasources: {
85
+ db: {
86
+ url: string;
87
+ };
88
+ };
89
+ }>;
84
90
  /** @returns Announcement by ID with class and teachers. */
85
91
  export declare function findAnnouncementWithClass(id: string): import(".prisma/client").Prisma.Prisma__AnnouncementClient<({
86
92
  class: {
@@ -94,9 +100,9 @@ export declare function findAnnouncementWithClass(id: string): import(".prisma/c
94
100
  schoolId: string | null;
95
101
  }[];
96
102
  } & {
103
+ name: string;
97
104
  id: string;
98
105
  schoolId: string | null;
99
- name: string;
100
106
  subject: string;
101
107
  color: string | null;
102
108
  section: string;
@@ -105,22 +111,28 @@ export declare function findAnnouncementWithClass(id: string): import(".prisma/c
105
111
  attachments: {
106
112
  path: string;
107
113
  type: string;
108
- id: string;
109
114
  name: string;
115
+ id: string;
110
116
  size: number | null;
117
+ uploadStatus: import(".prisma/client").$Enums.UploadStatus;
111
118
  thumbnail: {
112
119
  path: string;
113
120
  } | null;
114
- uploadStatus: import(".prisma/client").$Enums.UploadStatus;
115
121
  }[];
116
122
  } & {
117
123
  id: string;
118
124
  createdAt: Date;
119
- classId: string;
120
- remarks: string;
121
125
  modifiedAt: Date | null;
126
+ classId: string;
122
127
  teacherId: string;
123
- }) | null, null, import("@prisma/client/runtime/library.js").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
128
+ remarks: string;
129
+ }) | null, null, import("@prisma/client/runtime/library.js").DefaultArgs, {
130
+ datasources: {
131
+ db: {
132
+ url: string;
133
+ };
134
+ };
135
+ }>;
124
136
  /** Create an announcement. */
125
137
  export declare function createAnnouncement(data: {
126
138
  remarks: string;
@@ -129,8 +141,8 @@ export declare function createAnnouncement(data: {
129
141
  }): import(".prisma/client").Prisma.Prisma__AnnouncementClient<{
130
142
  id: string;
131
143
  createdAt: Date;
132
- remarks: string;
133
144
  modifiedAt: Date | null;
145
+ remarks: string;
134
146
  teacher: {
135
147
  id: string;
136
148
  username: string;
@@ -143,13 +155,19 @@ export declare function createAnnouncement(data: {
143
155
  attachments: {
144
156
  path: string;
145
157
  type: string;
146
- id: string;
147
158
  name: string;
159
+ id: string;
148
160
  size: number | null;
149
161
  uploadedAt: Date | null;
150
162
  thumbnailId: string | null;
151
163
  }[];
152
- }, never, import("@prisma/client/runtime/library.js").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
164
+ }, never, import("@prisma/client/runtime/library.js").DefaultArgs, {
165
+ datasources: {
166
+ db: {
167
+ url: string;
168
+ };
169
+ };
170
+ }>;
153
171
  /** Update announcement attachments. */
154
172
  export declare function updateAnnouncementAttachments(id: string, data: {
155
173
  connect?: {
@@ -163,8 +181,8 @@ export declare function updateAnnouncementAttachments(id: string, data: {
163
181
  }): import(".prisma/client").Prisma.Prisma__AnnouncementClient<{
164
182
  id: string;
165
183
  createdAt: Date;
166
- remarks: string;
167
184
  modifiedAt: Date | null;
185
+ remarks: string;
168
186
  teacher: {
169
187
  id: string;
170
188
  username: string;
@@ -177,21 +195,27 @@ export declare function updateAnnouncementAttachments(id: string, data: {
177
195
  attachments: {
178
196
  path: string;
179
197
  type: string;
180
- id: string;
181
198
  name: string;
199
+ id: string;
182
200
  size: number | null;
183
201
  uploadedAt: Date | null;
184
202
  thumbnailId: string | null;
185
203
  }[];
186
- }, never, import("@prisma/client/runtime/library.js").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
204
+ }, never, import("@prisma/client/runtime/library.js").DefaultArgs, {
205
+ datasources: {
206
+ db: {
207
+ url: string;
208
+ };
209
+ };
210
+ }>;
187
211
  /** Update announcement remarks. */
188
212
  export declare function updateAnnouncement(id: string, data: {
189
213
  remarks?: string;
190
214
  }): import(".prisma/client").Prisma.Prisma__AnnouncementClient<{
191
215
  id: string;
192
216
  createdAt: Date;
193
- remarks: string;
194
217
  modifiedAt: Date | null;
218
+ remarks: string;
195
219
  teacher: {
196
220
  id: string;
197
221
  username: string;
@@ -204,20 +228,32 @@ export declare function updateAnnouncement(id: string, data: {
204
228
  attachments: {
205
229
  path: string;
206
230
  type: string;
207
- id: string;
208
231
  name: string;
232
+ id: string;
209
233
  size: number | null;
210
234
  uploadedAt: Date | null;
211
235
  thumbnailId: string | null;
212
236
  }[];
213
- }, never, import("@prisma/client/runtime/library.js").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
237
+ }, never, import("@prisma/client/runtime/library.js").DefaultArgs, {
238
+ datasources: {
239
+ db: {
240
+ url: string;
241
+ };
242
+ };
243
+ }>;
214
244
  /** Delete an announcement. */
215
245
  export declare function deleteAnnouncement(id: string): import(".prisma/client").Prisma.Prisma__AnnouncementClient<{
216
246
  id: string;
217
247
  createdAt: Date;
218
- classId: string;
219
- remarks: string;
220
248
  modifiedAt: Date | null;
249
+ classId: string;
221
250
  teacherId: string;
222
- }, never, import("@prisma/client/runtime/library.js").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
251
+ remarks: string;
252
+ }, never, import("@prisma/client/runtime/library.js").DefaultArgs, {
253
+ datasources: {
254
+ db: {
255
+ url: string;
256
+ };
257
+ };
258
+ }>;
223
259
  //# sourceMappingURL=announcement.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"announcement.d.ts","sourceRoot":"/","sources":["models/announcement.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B9B,CAAC;AAEF,0CAA0C;AAC1C,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;KAWzD;AAED,6CAA6C;AAC7C,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;8HAKvE;AAED,2DAA2D;AAC3D,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+HAoBnD;AAED,8BAA8B;AAC9B,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;;;;;;;;;;;;;;;;;;;;;;;wHASA;AAED,uCAAuC;AACvC,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE;QAAE,EAAE,EAAE;YAAE,EAAE,EAAE,MAAM,EAAE,CAAA;SAAE,CAAA;KAAE,CAAC;CACvC;;;;;;;;;;;;;;;;;;;;;;;wHAcF;AAED,mCAAmC;AACnC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;wHAMxE;AAED,8BAA8B;AAC9B,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM;;;;;;;wHAI5C"}
1
+ {"version":3,"file":"announcement.d.ts","sourceRoot":"/","sources":["models/announcement.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6B9B,CAAC;AAEF,0CAA0C;AAC1C,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;KAWzD;AAED,6CAA6C;AAC7C,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAKvE;AAED,2DAA2D;AAC3D,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoBnD;AAED,8BAA8B;AAC9B,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GASA;AAED,uCAAuC;AACvC,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE;QAAE,EAAE,EAAE;YAAE,EAAE,EAAE,MAAM,EAAE,CAAA;SAAE,CAAA;KAAE,CAAC;CACvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAcF;AAED,mCAAmC;AACnC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAMxE;AAED,8BAA8B;AAC9B,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;GAI5C"}