@studious-lms/server 1.1.24 → 1.2.6
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/.coderabbit.yaml +9 -0
- package/.env.example +53 -0
- package/.env.test.example +37 -0
- package/README.md +34 -7
- package/dist/exportType.d.ts.map +1 -1
- package/dist/exportType.js +4 -0
- package/dist/exportType.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +212 -51
- package/dist/index.js.map +1 -0
- package/dist/instrument.d.ts +2 -0
- package/dist/instrument.d.ts.map +1 -0
- package/dist/instrument.js +18 -0
- package/dist/instrument.js.map +1 -0
- package/dist/lib/config/env.d.ts +190 -0
- package/dist/lib/config/env.d.ts.map +1 -0
- package/dist/lib/config/env.js +121 -0
- package/dist/lib/config/env.js.map +1 -0
- package/dist/lib/fileUpload.d.ts +2 -2
- package/dist/lib/fileUpload.d.ts.map +1 -1
- package/dist/lib/fileUpload.js +82 -15
- package/dist/lib/fileUpload.js.map +1 -0
- package/dist/lib/googleCloudStorage.d.ts +13 -0
- package/dist/lib/googleCloudStorage.d.ts.map +1 -1
- package/dist/lib/googleCloudStorage.js +45 -6
- package/dist/lib/googleCloudStorage.js.map +1 -0
- package/dist/lib/jsonConversion.d.ts.map +1 -1
- package/dist/lib/jsonConversion.js +16 -14
- package/dist/lib/jsonConversion.js.map +1 -0
- package/dist/lib/jsonStyles.d.ts.map +1 -1
- package/dist/lib/jsonStyles.js +4 -0
- package/dist/lib/jsonStyles.js.map +1 -0
- package/dist/lib/notificationHandler.d.ts +25 -0
- package/dist/lib/notificationHandler.d.ts.map +1 -0
- package/dist/lib/notificationHandler.js +32 -0
- package/dist/lib/notificationHandler.js.map +1 -0
- package/dist/lib/prisma.d.ts +2 -2
- package/dist/lib/prisma.d.ts.map +1 -1
- package/dist/lib/prisma.js +24 -1
- package/dist/lib/prisma.js.map +1 -0
- package/dist/lib/pusher.d.ts +4 -1
- package/dist/lib/pusher.d.ts.map +1 -1
- package/dist/lib/pusher.js +14 -6
- package/dist/lib/pusher.js.map +1 -0
- package/dist/lib/redis.d.ts +5 -0
- package/dist/lib/redis.d.ts.map +1 -0
- package/dist/lib/redis.js +53 -0
- package/dist/lib/redis.js.map +1 -0
- package/dist/lib/thumbnailGenerator.d.ts +0 -21
- package/dist/lib/thumbnailGenerator.d.ts.map +1 -1
- package/dist/lib/thumbnailGenerator.js +159 -158
- package/dist/lib/thumbnailGenerator.js.map +1 -0
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +41 -93
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/logging.d.ts.map +1 -1
- package/dist/middleware/logging.js +4 -0
- package/dist/middleware/logging.js.map +1 -0
- package/dist/middleware/security.d.ts +5 -0
- package/dist/middleware/security.d.ts.map +1 -0
- package/dist/middleware/security.js +77 -0
- package/dist/middleware/security.js.map +1 -0
- package/dist/models/agenda.d.ts +97 -0
- package/dist/models/agenda.d.ts.map +1 -0
- package/dist/models/agenda.js +40 -0
- package/dist/models/agenda.js.map +1 -0
- package/dist/models/announcement.d.ts +223 -0
- package/dist/models/announcement.d.ts.map +1 -0
- package/dist/models/announcement.js +120 -0
- package/dist/models/announcement.js.map +1 -0
- package/dist/models/assignment.d.ts +1292 -0
- package/dist/models/assignment.d.ts.map +1 -0
- package/dist/models/assignment.js +309 -0
- package/dist/models/assignment.js.map +1 -0
- package/dist/models/attendance.d.ts +180 -0
- package/dist/models/attendance.d.ts.map +1 -0
- package/dist/models/attendance.js +188 -0
- package/dist/models/attendance.js.map +1 -0
- package/dist/models/auth.d.ts +153 -0
- package/dist/models/auth.d.ts.map +1 -0
- package/dist/models/auth.js +217 -0
- package/dist/models/auth.js.map +1 -0
- package/dist/models/class.d.ts +439 -0
- package/dist/models/class.d.ts.map +1 -0
- package/dist/models/class.js +546 -0
- package/dist/models/class.js.map +1 -0
- package/dist/models/comment.d.ts +171 -0
- package/dist/models/comment.d.ts.map +1 -0
- package/dist/models/comment.js +138 -0
- package/dist/models/comment.js.map +1 -0
- package/dist/models/conversation.d.ts +164 -0
- package/dist/models/conversation.d.ts.map +1 -0
- package/dist/models/conversation.js +175 -0
- package/dist/models/conversation.js.map +1 -0
- package/dist/models/event.d.ts +295 -0
- package/dist/models/event.d.ts.map +1 -0
- package/dist/models/event.js +145 -0
- package/dist/models/event.js.map +1 -0
- package/dist/models/file.d.ts +536 -0
- package/dist/models/file.d.ts.map +1 -0
- package/dist/models/file.js +126 -0
- package/dist/models/file.js.map +1 -0
- package/dist/models/folder.d.ts +295 -0
- package/dist/models/folder.d.ts.map +1 -0
- package/dist/models/folder.js +202 -0
- package/dist/models/folder.js.map +1 -0
- package/dist/models/labChat.d.ts +243 -0
- package/dist/models/labChat.d.ts.map +1 -0
- package/dist/models/labChat.js +204 -0
- package/dist/models/labChat.js.map +1 -0
- package/dist/models/marketing.d.ts +72 -0
- package/dist/models/marketing.d.ts.map +1 -0
- package/dist/models/marketing.js +26 -0
- package/dist/models/marketing.js.map +1 -0
- package/dist/models/message.d.ts +100 -0
- package/dist/models/message.d.ts.map +1 -0
- package/dist/models/message.js +131 -0
- package/dist/models/message.js.map +1 -0
- package/dist/models/newtonChat.d.ts +72 -0
- package/dist/models/newtonChat.d.ts.map +1 -0
- package/dist/models/newtonChat.js +61 -0
- package/dist/models/newtonChat.js.map +1 -0
- package/dist/models/notification.d.ts +65 -0
- package/dist/models/notification.d.ts.map +1 -0
- package/dist/models/notification.js +46 -0
- package/dist/models/notification.js.map +1 -0
- package/dist/models/section.d.ts +102 -0
- package/dist/models/section.d.ts.map +1 -0
- package/dist/models/section.js +83 -0
- package/dist/models/section.js.map +1 -0
- package/dist/models/user.d.ts +39 -0
- package/dist/models/user.d.ts.map +1 -0
- package/dist/models/user.js +38 -0
- package/dist/models/user.js.map +1 -0
- package/dist/models/worksheet.d.ts +460 -0
- package/dist/models/worksheet.d.ts.map +1 -0
- package/dist/models/worksheet.js +200 -0
- package/dist/models/worksheet.js.map +1 -0
- package/dist/pipelines/aiLabChat.d.ts +21 -0
- package/dist/pipelines/aiLabChat.d.ts.map +1 -0
- package/dist/pipelines/aiLabChat.js +460 -0
- package/dist/pipelines/aiLabChat.js.map +1 -0
- package/dist/pipelines/aiNewtonChat.d.ts +30 -0
- package/dist/pipelines/aiNewtonChat.d.ts.map +1 -0
- package/dist/pipelines/aiNewtonChat.js +289 -0
- package/dist/pipelines/aiNewtonChat.js.map +1 -0
- package/dist/pipelines/gradeWorksheet.d.ts +30 -0
- package/dist/pipelines/gradeWorksheet.d.ts.map +1 -0
- package/dist/pipelines/gradeWorksheet.js +252 -0
- package/dist/pipelines/gradeWorksheet.js.map +1 -0
- package/dist/routers/_app.d.ts +6403 -3741
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/_app.js +10 -0
- package/dist/routers/_app.js.map +1 -0
- package/dist/routers/agenda.d.ts +58 -6
- package/dist/routers/agenda.d.ts.map +1 -1
- package/dist/routers/agenda.js +6 -58
- package/dist/routers/agenda.js.map +1 -0
- package/dist/routers/announcement.d.ts +325 -6
- package/dist/routers/announcement.d.ts.map +1 -1
- package/dist/routers/announcement.js +547 -57
- package/dist/routers/announcement.js.map +1 -0
- package/dist/routers/assignment.d.ts +431 -318
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +104 -1559
- package/dist/routers/assignment.js.map +1 -0
- package/dist/routers/attendance.d.ts +20 -9
- package/dist/routers/attendance.d.ts.map +1 -1
- package/dist/routers/attendance.js +10 -263
- package/dist/routers/attendance.js.map +1 -0
- package/dist/routers/auth.d.ts +21 -1
- package/dist/routers/auth.d.ts.map +1 -1
- package/dist/routers/auth.js +37 -241
- package/dist/routers/auth.js.map +1 -0
- package/dist/routers/class.d.ts +198 -68
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/class.js +88 -909
- package/dist/routers/class.js.map +1 -0
- package/dist/routers/comment.d.ts +153 -0
- package/dist/routers/comment.d.ts.map +1 -0
- package/dist/routers/comment.js +58 -0
- package/dist/routers/comment.js.map +1 -0
- package/dist/routers/conversation.d.ts +73 -3
- package/dist/routers/conversation.d.ts.map +1 -1
- package/dist/routers/conversation.js +23 -265
- package/dist/routers/conversation.js.map +1 -0
- package/dist/routers/event.d.ts +46 -37
- package/dist/routers/event.d.ts.map +1 -1
- package/dist/routers/event.js +15 -431
- package/dist/routers/event.js.map +1 -0
- package/dist/routers/file.d.ts +4 -2
- package/dist/routers/file.d.ts.map +1 -1
- package/dist/routers/file.js +11 -295
- package/dist/routers/file.js.map +1 -0
- package/dist/routers/folder.d.ts +21 -14
- package/dist/routers/folder.d.ts.map +1 -1
- package/dist/routers/folder.js +36 -743
- package/dist/routers/folder.js.map +1 -0
- package/dist/routers/labChat.d.ts +12 -9
- package/dist/routers/labChat.d.ts.map +1 -1
- package/dist/routers/labChat.js +21 -877
- package/dist/routers/labChat.js.map +1 -0
- package/dist/routers/marketing.d.ts +2 -2
- package/dist/routers/marketing.d.ts.map +1 -1
- package/dist/routers/marketing.js +9 -54
- package/dist/routers/marketing.js.map +1 -0
- package/dist/routers/message.d.ts +2 -1
- package/dist/routers/message.d.ts.map +1 -1
- package/dist/routers/message.js +29 -519
- package/dist/routers/message.js.map +1 -0
- package/dist/routers/newtonChat.d.ts +55 -0
- package/dist/routers/newtonChat.d.ts.map +1 -0
- package/dist/routers/newtonChat.js +22 -0
- package/dist/routers/newtonChat.js.map +1 -0
- package/dist/routers/notifications.d.ts +8 -8
- package/dist/routers/notifications.d.ts.map +1 -1
- package/dist/routers/notifications.js +20 -81
- package/dist/routers/notifications.js.map +1 -0
- package/dist/routers/section.d.ts +37 -6
- package/dist/routers/section.d.ts.map +1 -1
- package/dist/routers/section.js +26 -167
- package/dist/routers/section.js.map +1 -0
- package/dist/routers/user.d.ts +1 -1
- package/dist/routers/user.d.ts.map +1 -1
- package/dist/routers/user.js +34 -204
- package/dist/routers/user.js.map +1 -0
- package/dist/routers/worksheet.d.ts +362 -0
- package/dist/routers/worksheet.d.ts.map +1 -0
- package/dist/routers/worksheet.js +153 -0
- package/dist/routers/worksheet.js.map +1 -0
- package/dist/seedDatabase.d.ts +2 -3
- package/dist/seedDatabase.d.ts.map +1 -1
- package/dist/seedDatabase.js +311 -289
- package/dist/seedDatabase.js.map +1 -0
- package/dist/server/pipelines/aiLabChat.d.ts +21 -0
- package/dist/server/pipelines/aiLabChat.d.ts.map +1 -0
- package/dist/server/pipelines/aiLabChat.js +456 -0
- package/dist/server/pipelines/aiLabChat.js.map +1 -0
- package/dist/server/pipelines/aiNewtonChat.d.ts +30 -0
- package/dist/server/pipelines/aiNewtonChat.d.ts.map +1 -0
- package/dist/server/pipelines/aiNewtonChat.js +285 -0
- package/dist/server/pipelines/aiNewtonChat.js.map +1 -0
- package/dist/server/pipelines/gradeWorksheet.d.ts +30 -0
- package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -0
- package/dist/server/pipelines/gradeWorksheet.js +248 -0
- package/dist/server/pipelines/gradeWorksheet.js.map +1 -0
- package/dist/services/agenda.d.ts +100 -0
- package/dist/services/agenda.d.ts.map +1 -0
- package/dist/services/agenda.js +21 -0
- package/dist/services/agenda.js.map +1 -0
- package/dist/services/announcement.d.ts +135 -0
- package/dist/services/announcement.d.ts.map +1 -0
- package/dist/services/announcement.js +223 -0
- package/dist/services/announcement.js.map +1 -0
- package/dist/services/assignment.d.ts +1462 -0
- package/dist/services/assignment.d.ts.map +1 -0
- package/dist/services/assignment.js +898 -0
- package/dist/services/assignment.js.map +1 -0
- package/dist/services/attendance.d.ts +93 -0
- package/dist/services/attendance.d.ts.map +1 -0
- package/dist/services/attendance.js +61 -0
- package/dist/services/attendance.js.map +1 -0
- package/dist/services/auth.d.ts +68 -0
- package/dist/services/auth.d.ts.map +1 -0
- package/dist/services/auth.js +218 -0
- package/dist/services/auth.js.map +1 -0
- package/dist/services/class.d.ts +621 -0
- package/dist/services/class.d.ts.map +1 -0
- package/dist/services/class.js +474 -0
- package/dist/services/class.js.map +1 -0
- package/dist/services/comment.d.ts +100 -0
- package/dist/services/comment.d.ts.map +1 -0
- package/dist/services/comment.js +83 -0
- package/dist/services/comment.js.map +1 -0
- package/dist/services/conversation.d.ts +159 -0
- package/dist/services/conversation.d.ts.map +1 -0
- package/dist/services/conversation.js +138 -0
- package/dist/services/conversation.js.map +1 -0
- package/dist/services/event.d.ts +216 -0
- package/dist/services/event.d.ts.map +1 -0
- package/dist/services/event.js +168 -0
- package/dist/services/event.js.map +1 -0
- package/dist/services/file.d.ts +74 -0
- package/dist/services/file.d.ts.map +1 -0
- package/dist/services/file.js +133 -0
- package/dist/services/file.js.map +1 -0
- package/dist/services/folder.d.ts +239 -0
- package/dist/services/folder.d.ts.map +1 -0
- package/dist/services/folder.js +248 -0
- package/dist/services/folder.js.map +1 -0
- package/dist/services/labChat.d.ts +165 -0
- package/dist/services/labChat.d.ts.map +1 -0
- package/dist/services/labChat.js +289 -0
- package/dist/services/labChat.js.map +1 -0
- package/dist/services/marketing.d.ts +50 -0
- package/dist/services/marketing.d.ts.map +1 -0
- package/dist/services/marketing.js +32 -0
- package/dist/services/marketing.js.map +1 -0
- package/dist/services/message.d.ts +95 -0
- package/dist/services/message.d.ts.map +1 -0
- package/dist/services/message.js +350 -0
- package/dist/services/message.js.map +1 -0
- package/dist/services/newtonChat.d.ts +22 -0
- package/dist/services/newtonChat.d.ts.map +1 -0
- package/dist/services/newtonChat.js +174 -0
- package/dist/services/newtonChat.js.map +1 -0
- package/dist/services/notification.d.ts +65 -0
- package/dist/services/notification.d.ts.map +1 -0
- package/dist/services/notification.js +33 -0
- package/dist/services/notification.js.map +1 -0
- package/dist/services/section.d.ts +53 -0
- package/dist/services/section.d.ts.map +1 -0
- package/dist/services/section.js +199 -0
- package/dist/services/section.js.map +1 -0
- package/dist/services/user.d.ts +48 -0
- package/dist/services/user.d.ts.map +1 -0
- package/dist/services/user.js +141 -0
- package/dist/services/user.js.map +1 -0
- package/dist/services/worksheet.d.ts +239 -0
- package/dist/services/worksheet.d.ts.map +1 -0
- package/dist/services/worksheet.js +235 -0
- package/dist/services/worksheet.js.map +1 -0
- package/dist/socket/handlers.d.ts.map +1 -1
- package/dist/socket/handlers.js +4 -0
- package/dist/socket/handlers.js.map +1 -0
- package/dist/trpc.d.ts.map +1 -1
- package/dist/trpc.js +4 -0
- package/dist/trpc.js.map +1 -0
- package/dist/types/trpc.d.ts.map +1 -1
- package/dist/types/trpc.js +4 -0
- package/dist/types/trpc.js.map +1 -0
- package/dist/utils/aiUser.d.ts +1 -3
- package/dist/utils/aiUser.d.ts.map +1 -1
- package/dist/utils/aiUser.js +8 -3
- package/dist/utils/aiUser.js.map +1 -0
- package/dist/utils/email.d.ts +12 -1
- package/dist/utils/email.d.ts.map +1 -1
- package/dist/utils/email.js +26 -4
- package/dist/utils/email.js.map +1 -0
- package/dist/utils/generateInviteCode.d.ts +1 -2
- package/dist/utils/generateInviteCode.d.ts.map +1 -1
- package/dist/utils/generateInviteCode.js +5 -2
- package/dist/utils/generateInviteCode.js.map +1 -0
- package/dist/utils/inference.d.ts +8 -0
- package/dist/utils/inference.d.ts.map +1 -1
- package/dist/utils/inference.js +78 -10
- package/dist/utils/inference.js.map +1 -0
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +35 -3
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/prismaErrorHandler.d.ts.map +1 -1
- package/dist/utils/prismaErrorHandler.js +7 -0
- package/dist/utils/prismaErrorHandler.js.map +1 -0
- package/dist/utils/prismaWrapper.d.ts +1 -0
- package/dist/utils/prismaWrapper.d.ts.map +1 -1
- package/dist/utils/prismaWrapper.js +8 -0
- package/dist/utils/prismaWrapper.js.map +1 -0
- package/docker-compose.yml +19 -0
- package/package.json +21 -4
- package/prisma/migrations/20251109122857_annuoncements_comments/migration.sql +30 -0
- package/prisma/migrations/20251109135555_reactions_announcements_comments/migration.sql +35 -0
- package/prisma/schema.prisma +180 -12
- package/scripts/test-pre-push.ts +14 -0
- package/src/index.ts +247 -52
- package/src/instrument.ts +15 -0
- package/src/lib/config/env.ts +132 -0
- package/src/lib/fileUpload.ts +81 -16
- package/src/lib/googleCloudStorage.ts +42 -6
- package/src/lib/jsonConversion.ts +12 -14
- package/src/lib/prisma.ts +23 -2
- package/src/lib/pusher.ts +11 -6
- package/src/lib/redis.ts +56 -0
- package/src/lib/thumbnailGenerator.ts +170 -168
- package/src/middleware/auth.ts +86 -137
- package/src/middleware/security.ts +80 -0
- package/src/models/agenda.ts +46 -0
- package/src/models/announcement.ts +134 -0
- package/src/models/assignment.ts +322 -0
- package/src/models/attendance.ts +208 -0
- package/src/models/auth.ts +247 -0
- package/src/models/class.ts +598 -0
- package/src/models/comment.ts +152 -0
- package/src/models/conversation.ts +200 -0
- package/src/models/event.ts +177 -0
- package/src/models/file.ts +129 -0
- package/src/models/folder.ts +225 -0
- package/src/models/labChat.ts +213 -0
- package/src/models/marketing.ts +45 -0
- package/src/models/message.ts +153 -0
- package/src/models/newtonChat.ts +70 -0
- package/src/models/notification.ts +54 -0
- package/src/models/section.ts +98 -0
- package/src/models/user.ts +47 -0
- package/src/models/worksheet.ts +294 -0
- package/src/pipelines/aiLabChat.ts +511 -0
- package/src/pipelines/aiNewtonChat.ts +347 -0
- package/src/pipelines/gradeWorksheet.ts +286 -0
- package/src/routers/_app.ts +6 -0
- package/src/routers/agenda.ts +3 -61
- package/src/routers/announcement.ts +622 -57
- package/src/routers/assignment.ts +157 -1688
- package/src/routers/attendance.ts +16 -277
- package/src/routers/auth.ts +79 -313
- package/src/routers/class.ts +265 -1038
- package/src/routers/comment.ts +76 -0
- package/src/routers/conversation.ts +53 -284
- package/src/routers/event.ts +50 -481
- package/src/routers/file.ts +45 -341
- package/src/routers/folder.ts +107 -836
- package/src/routers/labChat.ts +29 -960
- package/src/routers/marketing.ts +35 -77
- package/src/routers/message.ts +45 -571
- package/src/routers/newtonChat.ts +36 -0
- package/src/routers/notifications.ts +32 -82
- package/src/routers/section.ts +58 -200
- package/src/routers/user.ts +49 -226
- package/src/routers/worksheet.ts +252 -0
- package/src/seedDatabase.ts +330 -290
- package/src/services/agenda.ts +21 -0
- package/src/services/announcement.ts +290 -0
- package/src/services/assignment.ts +1198 -0
- package/src/services/attendance.ts +85 -0
- package/src/services/auth.ts +277 -0
- package/src/services/class.ts +622 -0
- package/src/services/comment.ts +106 -0
- package/src/services/conversation.ts +213 -0
- package/src/services/event.ts +231 -0
- package/src/services/file.ts +167 -0
- package/src/services/folder.ts +316 -0
- package/src/services/labChat.ts +352 -0
- package/src/services/marketing.ts +57 -0
- package/src/services/message.ts +461 -0
- package/src/services/newtonChat.ts +222 -0
- package/src/services/notification.ts +50 -0
- package/src/services/section.ts +283 -0
- package/src/services/user.ts +172 -0
- package/src/services/worksheet.ts +358 -0
- package/src/trpc.ts +4 -0
- package/src/utils/aiUser.ts +4 -3
- package/src/utils/email.ts +33 -4
- package/src/utils/generateInviteCode.ts +1 -3
- package/src/utils/inference.ts +89 -10
- package/src/utils/logger.ts +33 -3
- package/src/utils/prismaErrorHandler.ts +3 -0
- package/src/utils/prismaWrapper.ts +4 -0
- package/tests/globalSetup.ts +62 -0
- package/tests/helpers.ts +22 -0
- package/tests/middleware/security.test.ts +42 -0
- package/tests/routers/agenda.test.ts +138 -0
- package/tests/routers/announcement.test.ts +490 -0
- package/tests/routers/assignment.test.ts +837 -0
- package/tests/routers/attendance.test.ts +160 -0
- package/tests/routers/auth.test.ts +171 -0
- package/tests/{class.test.ts → routers/class.test.ts} +163 -92
- package/tests/routers/comment.test.ts +126 -0
- package/tests/routers/conversation.test.ts +145 -0
- package/tests/routers/event.test.ts +289 -0
- package/tests/routers/folder.test.ts +178 -0
- package/tests/routers/labChat.test.ts +115 -0
- package/tests/routers/marketing.test.ts +59 -0
- package/tests/routers/message.test.ts +123 -0
- package/tests/routers/notification.test.ts +69 -0
- package/tests/routers/section.test.ts +208 -0
- package/tests/server/rateLimit.test.ts +73 -0
- package/tests/setup.ts +39 -65
- package/tests/user.test.ts +136 -0
- package/tests/utils/aiUser.test.ts +22 -0
- package/tests/utils/generateInviteCode.test.ts +24 -0
- package/tests/utils/logger.test.ts +74 -0
- package/tests/utils/prismaErrorHandler.test.ts +101 -0
- package/tests/utils/prismaWrapper.test.ts +82 -0
- package/tests/worksheet.test.ts +181 -0
- package/tsconfig.json +9 -2
- package/vitest.config.ts +30 -1
- package/vitest.unit.config.ts +21 -0
- package/API_SPECIFICATION.md +0 -1597
- package/BASE64_REMOVAL_SUMMARY.md +0 -164
- package/CHAT_API_SPEC.md +0 -579
- package/LAB_CHAT_API_SPEC.md +0 -518
- package/dist/routers/school.d.ts +0 -208
- package/dist/routers/school.d.ts.map +0 -1
- package/dist/routers/school.js +0 -481
- package/tests/auth.test.ts +0 -25
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
dotenv.config();
|
|
1
|
+
|
|
3
2
|
import { Storage } from '@google-cloud/storage';
|
|
4
3
|
import { TRPCError } from '@trpc/server';
|
|
4
|
+
import { env } from './config/env.js';
|
|
5
5
|
|
|
6
6
|
const storage = new Storage({
|
|
7
|
-
projectId:
|
|
7
|
+
projectId: env.GOOGLE_CLOUD_PROJECT_ID,
|
|
8
8
|
credentials: {
|
|
9
|
-
client_email:
|
|
10
|
-
private_key:
|
|
9
|
+
client_email: env.GOOGLE_CLOUD_CLIENT_EMAIL,
|
|
10
|
+
private_key: env.GOOGLE_CLOUD_PRIVATE_KEY?.replace(/\\n/g, '\n'),
|
|
11
11
|
},
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
export const bucket = storage.bucket(
|
|
14
|
+
export const bucket = storage.bucket(env.GOOGLE_CLOUD_BUCKET_NAME!);
|
|
15
15
|
|
|
16
16
|
// Short expiration time for signed URLs (5 minutes)
|
|
17
17
|
const SIGNED_URL_EXPIRATION = 5 * 60 * 1000;
|
|
@@ -62,4 +62,40 @@ export async function deleteFile(filePath: string): Promise<void> {
|
|
|
62
62
|
message: 'Failed to delete file from storage',
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Checks if an object exists in Google Cloud Storage
|
|
69
|
+
* @param bucketName The name of the bucket (unused, uses default bucket)
|
|
70
|
+
* @param objectPath The path of the object to check
|
|
71
|
+
* @returns Promise<boolean> True if the object exists, false otherwise
|
|
72
|
+
*/
|
|
73
|
+
export async function objectExists(bucketName: string, objectPath: string): Promise<boolean> {
|
|
74
|
+
try {
|
|
75
|
+
const [exists] = await bucket.file(objectPath).exists();
|
|
76
|
+
return exists;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('Error checking if object exists in Google Cloud Storage:', error);
|
|
79
|
+
throw new TRPCError({
|
|
80
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
81
|
+
message: 'Failed to check object existence',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Copies a file within the same bucket to a new path
|
|
88
|
+
* @param sourcePath The GCS path of the source file
|
|
89
|
+
* @param destPath The GCS path for the destination
|
|
90
|
+
*/
|
|
91
|
+
export async function copyFile(sourcePath: string, destPath: string): Promise<void> {
|
|
92
|
+
try {
|
|
93
|
+
await bucket.file(sourcePath).copy(destPath);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('Error copying file in Google Cloud Storage:', error);
|
|
96
|
+
throw new TRPCError({
|
|
97
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
98
|
+
message: 'Failed to copy file in storage',
|
|
99
|
+
});
|
|
100
|
+
}
|
|
65
101
|
}
|
|
@@ -4,12 +4,13 @@ import { readFileSync } from 'fs'
|
|
|
4
4
|
import { join } from 'path'
|
|
5
5
|
import { writeFile } from 'fs'
|
|
6
6
|
import { DocumentBlock, FormatTypes, Fonts } from './jsonStyles.js'
|
|
7
|
+
import { logger } from '../utils/logger.js'
|
|
7
8
|
|
|
8
9
|
export async function createPdf(blocks: DocumentBlock[]) {
|
|
9
|
-
|
|
10
|
+
logger.info(`createPdf: Starting PDF creation with ${blocks.length} blocks`);
|
|
10
11
|
try {
|
|
11
12
|
const pdfDoc = await PDFDocument.create()
|
|
12
|
-
|
|
13
|
+
logger.info('createPdf: PDFDocument created successfully');
|
|
13
14
|
|
|
14
15
|
// Register fontkit to enable custom font embedding
|
|
15
16
|
pdfDoc.registerFontkit(fontkit)
|
|
@@ -33,9 +34,9 @@ export async function createPdf(blocks: DocumentBlock[]) {
|
|
|
33
34
|
notoSansItalic = await pdfDoc.embedFont(italicFontBytes)
|
|
34
35
|
courierFont = await pdfDoc.embedFont(StandardFonts.Courier) // Keep Courier for code blocks
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
logger.info('createPdf: Unicode fonts loaded successfully');
|
|
37
38
|
} catch (fontError) {
|
|
38
|
-
|
|
39
|
+
logger.warn(`createPdf: Failed to load custom fonts, falling back to standard fonts: ${fontError}`);
|
|
39
40
|
// Fallback to standard fonts if custom fonts fail
|
|
40
41
|
notoSansRegular = await pdfDoc.embedFont(StandardFonts.Helvetica)
|
|
41
42
|
notoSansBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold)
|
|
@@ -342,10 +343,10 @@ export async function createPdf(blocks: DocumentBlock[]) {
|
|
|
342
343
|
|
|
343
344
|
let y = height - marginTop
|
|
344
345
|
let lastLineHeight = -1
|
|
345
|
-
|
|
346
|
+
logger.info(`createPdf: Starting to process ${blocks.length} blocks`);
|
|
346
347
|
for (let i = 0; i < blocks.length; i++) {
|
|
347
348
|
const block = blocks[i];
|
|
348
|
-
|
|
349
|
+
logger.info(`createPdf: Processing block ${i + 1}/${blocks.length}, format: ${block.format}, content type: ${typeof block.content}`);
|
|
349
350
|
try {
|
|
350
351
|
const preset = STYLE_PRESETS[block.format] || { fontSize: defaultFontSize, lineHeight: defaultLineHeight }
|
|
351
352
|
|
|
@@ -725,24 +726,21 @@ export async function createPdf(blocks: DocumentBlock[]) {
|
|
|
725
726
|
}
|
|
726
727
|
}
|
|
727
728
|
}
|
|
728
|
-
|
|
729
|
+
logger.info(`createPdf: Successfully processed block ${i + 1}`);
|
|
729
730
|
y -= paragraphSpacing
|
|
730
731
|
lastLineHeight = lineHeight
|
|
731
732
|
} catch (blockError) {
|
|
732
|
-
|
|
733
|
+
logger.error(`createPdf: Error processing block ${i + 1}: ${blockError}`);
|
|
733
734
|
throw blockError;
|
|
734
735
|
}
|
|
735
736
|
}
|
|
736
737
|
|
|
737
|
-
|
|
738
|
+
logger.info('createPdf: About to save PDF document');
|
|
738
739
|
const pdfBytes = await pdfDoc.save()
|
|
739
|
-
|
|
740
|
-
// writeFile('output.pdf', pdfBytes, () => {
|
|
741
|
-
// console.log('PDF created successfully') // Still only saves file, no API yet
|
|
742
|
-
// })
|
|
740
|
+
logger.info(`createPdf: PDF saved successfully, bytes length: ${pdfBytes.length}`);
|
|
743
741
|
return pdfBytes
|
|
744
742
|
} catch (error) {
|
|
745
|
-
|
|
743
|
+
logger.error(`createPdf: Error during PDF creation: ${error}`);
|
|
746
744
|
throw error;
|
|
747
745
|
}
|
|
748
746
|
}
|
package/src/lib/prisma.ts
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
import { env } from './config/env.js';
|
|
3
|
+
|
|
4
|
+
const getLogLevel = () => {
|
|
5
|
+
switch (env.NODE_ENV) {
|
|
6
|
+
case 'development':
|
|
7
|
+
return ['query', 'error', 'warn'];
|
|
8
|
+
case 'production':
|
|
9
|
+
return ['error'];
|
|
10
|
+
default:
|
|
11
|
+
return ['error'];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
2
14
|
|
|
3
15
|
const prismaClientSingleton = () => {
|
|
16
|
+
// return new PrismaClient({
|
|
17
|
+
// log: env.NODE_ENV === 'development'
|
|
18
|
+
// ? ['query', 'error', 'warn']
|
|
19
|
+
// : ['error'],
|
|
20
|
+
// });
|
|
4
21
|
return new PrismaClient();
|
|
5
22
|
};
|
|
6
23
|
|
|
@@ -11,6 +28,10 @@ declare global {
|
|
|
11
28
|
|
|
12
29
|
export const prisma = globalThis.prisma ?? prismaClientSingleton();
|
|
13
30
|
|
|
14
|
-
if (
|
|
31
|
+
if (env.NODE_ENV !== 'production') {
|
|
15
32
|
globalThis.prisma = prisma;
|
|
16
|
-
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
process.on('beforeExit', async () => {
|
|
36
|
+
await prisma.$disconnect();
|
|
37
|
+
});
|
package/src/lib/pusher.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import Pusher from 'pusher';
|
|
2
|
+
import { env } from './config/env.js';
|
|
2
3
|
|
|
3
4
|
const pusher = new Pusher({
|
|
4
|
-
appId:
|
|
5
|
-
key:
|
|
6
|
-
secret:
|
|
7
|
-
cluster:
|
|
8
|
-
useTLS:
|
|
5
|
+
appId: env.PUSHER_APP_ID,
|
|
6
|
+
key: env.PUSHER_KEY,
|
|
7
|
+
secret: env.PUSHER_SECRET,
|
|
8
|
+
cluster: env.PUSHER_CLUSTER,
|
|
9
|
+
useTLS: env.NODE_ENV !== 'development',
|
|
9
10
|
});
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
const chatChannel = (conversationId: string) => `private-conversation-${conversationId}`;
|
|
13
|
+
const worksheetChannel = (worksheetResponseId: string) => `private-worksheet-${worksheetResponseId}`;
|
|
14
|
+
const teacherChannel = (classId: string) => `private-teacher-${classId}`;
|
|
15
|
+
|
|
16
|
+
export { pusher, chatChannel, worksheetChannel, teacherChannel };
|
package/src/lib/redis.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import Redis from 'ioredis';
|
|
2
|
+
import { env } from './config/env.js';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
|
|
5
|
+
let redis: Redis | null = null;
|
|
6
|
+
|
|
7
|
+
export function getRedis(): Redis | null {
|
|
8
|
+
return redis;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function connectRedis(): Promise<Redis | null> {
|
|
12
|
+
const url = env.REDIS_URL;
|
|
13
|
+
if (!url) {
|
|
14
|
+
logger.info('Redis not configured (REDIS_URL not set), skipping');
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (redis) {
|
|
19
|
+
return redis;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
redis = new Redis(url, {
|
|
23
|
+
maxRetriesPerRequest: 3,
|
|
24
|
+
retryStrategy(times) {
|
|
25
|
+
if (times > 3) return null;
|
|
26
|
+
return Math.min(times * 200, 2000);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
redis.on('error', (err) => {
|
|
31
|
+
logger.error('Redis connection error', { error: err.message });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
redis.on('connect', () => {
|
|
35
|
+
logger.info('Redis connected');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
await redis.ping();
|
|
40
|
+
logger.info('Redis ready');
|
|
41
|
+
return redis;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
logger.error('Redis ping failed', { error });
|
|
44
|
+
redis.disconnect();
|
|
45
|
+
redis = null;
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function disconnectRedis(): Promise<void> {
|
|
51
|
+
if (redis) {
|
|
52
|
+
await redis.quit();
|
|
53
|
+
redis = null;
|
|
54
|
+
logger.info('Redis disconnected');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -1,170 +1,172 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
1
|
+
// @deprecated: this is not used anymore
|
|
2
|
+
|
|
3
|
+
// import sharp from 'sharp';
|
|
4
|
+
// import { prisma } from './prisma.js';
|
|
5
|
+
// import { deleteFile, getSignedUrl } from './googleCloudStorage.js';
|
|
6
|
+
|
|
7
|
+
// // Thumbnail size configuration
|
|
8
|
+
// const THUMBNAIL_WIDTH = 200;
|
|
9
|
+
// const THUMBNAIL_HEIGHT = 200;
|
|
10
|
+
|
|
11
|
+
// // File type configurations
|
|
12
|
+
// const SUPPORTED_IMAGE_TYPES = [
|
|
13
|
+
// 'image/jpeg',
|
|
14
|
+
// 'image/png',
|
|
15
|
+
// 'image/gif',
|
|
16
|
+
// 'image/webp',
|
|
17
|
+
// 'image/tiff',
|
|
18
|
+
// 'image/bmp',
|
|
19
|
+
// 'image/avif'
|
|
20
|
+
// ];
|
|
21
|
+
|
|
22
|
+
// const DOCUMENT_TYPES = [
|
|
23
|
+
// 'application/pdf',
|
|
24
|
+
// 'application/msword',
|
|
25
|
+
// 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
|
|
26
|
+
// 'application/vnd.ms-excel',
|
|
27
|
+
// 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
|
|
28
|
+
// 'application/vnd.ms-powerpoint',
|
|
29
|
+
// 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx
|
|
30
|
+
// 'text/plain',
|
|
31
|
+
// 'text/csv',
|
|
32
|
+
// 'application/json',
|
|
33
|
+
// 'text/html',
|
|
34
|
+
// 'text/javascript',
|
|
35
|
+
// 'text/css'
|
|
36
|
+
// ];
|
|
37
|
+
|
|
38
|
+
// const VIDEO_TYPES = [
|
|
39
|
+
// 'video/mp4',
|
|
40
|
+
// 'video/webm',
|
|
41
|
+
// 'video/ogg',
|
|
42
|
+
// 'video/quicktime'
|
|
43
|
+
// ];
|
|
44
|
+
|
|
45
|
+
// const AUDIO_TYPES = [
|
|
46
|
+
// 'audio/mpeg',
|
|
47
|
+
// 'audio/ogg',
|
|
48
|
+
// 'audio/wav',
|
|
49
|
+
// 'audio/webm'
|
|
50
|
+
// ];
|
|
51
|
+
|
|
52
|
+
// /**
|
|
53
|
+
// * Generates a thumbnail for an image or PDF file
|
|
54
|
+
// * @param fileBuffer The file buffer
|
|
55
|
+
// * @param fileType The MIME type of the file
|
|
56
|
+
// * @returns Thumbnail buffer
|
|
57
|
+
// */
|
|
58
|
+
// export async function generateMediaThumbnail(fileBuffer: Buffer, fileType: string): Promise<Buffer> {
|
|
59
|
+
// if (fileType === 'application/pdf') {
|
|
60
|
+
// // For PDFs, we need to use a different approach
|
|
61
|
+
// try {
|
|
62
|
+
// return await sharp(fileBuffer, {
|
|
63
|
+
// density: 300, // Higher density for better quality
|
|
64
|
+
// page: 0 // First page only
|
|
65
|
+
// })
|
|
66
|
+
// .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {
|
|
67
|
+
// fit: 'inside',
|
|
68
|
+
// withoutEnlargement: true,
|
|
69
|
+
// })
|
|
70
|
+
// .jpeg({ quality: 80 })
|
|
71
|
+
// .toBuffer();
|
|
72
|
+
// } catch (error) {
|
|
73
|
+
// console.warn('Failed to generate PDF thumbnail:', error);
|
|
74
|
+
// return generateGenericThumbnail(fileType);
|
|
75
|
+
// }
|
|
76
|
+
// }
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
async function generateGenericThumbnail(fileType: string): Promise<Buffer> {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
export async function generateThumbnail(fileName: string, fileType: string): Promise<Buffer | null> {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
78
|
+
// // For regular images
|
|
79
|
+
// return sharp(fileBuffer)
|
|
80
|
+
// .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {
|
|
81
|
+
// fit: 'inside',
|
|
82
|
+
// withoutEnlargement: true,
|
|
83
|
+
// })
|
|
84
|
+
// .jpeg({ quality: 80 })
|
|
85
|
+
// .toBuffer();
|
|
86
|
+
// }
|
|
87
|
+
|
|
88
|
+
// /**
|
|
89
|
+
// * Generates a generic icon-based thumbnail for a file type
|
|
90
|
+
// * @param fileType The MIME type of the file
|
|
91
|
+
// * @returns Thumbnail buffer
|
|
92
|
+
// */
|
|
93
|
+
// async function generateGenericThumbnail(fileType: string): Promise<Buffer> {
|
|
94
|
+
// // Create a blank canvas with a colored background based on file type
|
|
95
|
+
// const canvas = sharp({
|
|
96
|
+
// create: {
|
|
97
|
+
// width: THUMBNAIL_WIDTH,
|
|
98
|
+
// height: THUMBNAIL_HEIGHT,
|
|
99
|
+
// channels: 4,
|
|
100
|
+
// background: { r: 245, g: 245, b: 245, alpha: 1 }
|
|
101
|
+
// }
|
|
102
|
+
// });
|
|
103
|
+
|
|
104
|
+
// // Add a colored overlay based on file type
|
|
105
|
+
// let color = { r: 200, g: 200, b: 200, alpha: 0.5 }; // Default gray
|
|
106
|
+
|
|
107
|
+
// if (DOCUMENT_TYPES.includes(fileType)) {
|
|
108
|
+
// color = { r: 52, g: 152, b: 219, alpha: 0.5 }; // Blue for documents
|
|
109
|
+
// } else if (VIDEO_TYPES.includes(fileType)) {
|
|
110
|
+
// color = { r: 231, g: 76, b: 60, alpha: 0.5 }; // Red for videos
|
|
111
|
+
// } else if (AUDIO_TYPES.includes(fileType)) {
|
|
112
|
+
// color = { r: 46, g: 204, b: 113, alpha: 0.5 }; // Green for audio
|
|
113
|
+
// }
|
|
114
|
+
|
|
115
|
+
// return canvas
|
|
116
|
+
// .composite([{
|
|
117
|
+
// input: Buffer.from([color.r, color.g, color.b, Math.floor(color.alpha * 255)]),
|
|
118
|
+
// raw: {
|
|
119
|
+
// width: 1,
|
|
120
|
+
// height: 1,
|
|
121
|
+
// channels: 4
|
|
122
|
+
// },
|
|
123
|
+
// tile: true,
|
|
124
|
+
// blend: 'overlay'
|
|
125
|
+
// }])
|
|
126
|
+
// .jpeg({ quality: 80 })
|
|
127
|
+
// .toBuffer();
|
|
128
|
+
// }
|
|
129
|
+
|
|
130
|
+
// /**
|
|
131
|
+
// * Generates a thumbnail for a file
|
|
132
|
+
// * @param fileName The name of the file in Google Cloud Storage
|
|
133
|
+
// * @param fileType The MIME type of the file
|
|
134
|
+
// * @returns The thumbnail buffer or null if thumbnail generation is not supported
|
|
135
|
+
// */
|
|
136
|
+
// export async function generateThumbnail(fileName: string, fileType: string): Promise<Buffer | null> {
|
|
137
|
+
// try {
|
|
138
|
+
// const signedUrl = await getSignedUrl(fileName);
|
|
139
|
+
// const response = await fetch(signedUrl);
|
|
138
140
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
// DEPRECATED: This function is no longer used - thumbnails are generated during direct uploads
|
|
170
|
-
// Thumbnail generation is now handled in the direct upload flow
|
|
141
|
+
// if (!response.ok) {
|
|
142
|
+
// throw new Error(`Failed to download file from storage: ${response.status} ${response.statusText}`);
|
|
143
|
+
// }
|
|
144
|
+
|
|
145
|
+
// const fileBuffer = await response.arrayBuffer();
|
|
146
|
+
|
|
147
|
+
// if (SUPPORTED_IMAGE_TYPES.includes(fileType) || fileType === 'application/pdf') {
|
|
148
|
+
// try {
|
|
149
|
+
// const thumbnail = await generateMediaThumbnail(Buffer.from(fileBuffer), fileType);
|
|
150
|
+
// return thumbnail;
|
|
151
|
+
// } catch (error) {
|
|
152
|
+
// return generateGenericThumbnail(fileType);
|
|
153
|
+
// }
|
|
154
|
+
// } else if ([...DOCUMENT_TYPES, ...VIDEO_TYPES, ...AUDIO_TYPES].includes(fileType)) {
|
|
155
|
+
// return generateGenericThumbnail(fileType);
|
|
156
|
+
// }
|
|
157
|
+
|
|
158
|
+
// return null; // Unsupported file type
|
|
159
|
+
// } catch (error) {
|
|
160
|
+
// return null;
|
|
161
|
+
// }
|
|
162
|
+
// }
|
|
163
|
+
|
|
164
|
+
// /**
|
|
165
|
+
// * Stores a thumbnail in Google Cloud Storage and creates a File entry
|
|
166
|
+
// * @param thumbnailBuffer The thumbnail buffer to store
|
|
167
|
+
// * @param originalFileName The original file name
|
|
168
|
+
// * @param userId The user ID who owns the file
|
|
169
|
+
// * @returns The ID of the created thumbnail File
|
|
170
|
+
// */
|
|
171
|
+
// // DEPRECATED: This function is no longer used - thumbnails are generated during direct uploads
|
|
172
|
+
// // Thumbnail generation is now handled in the direct upload flow
|