@studious-lms/server 1.0.4 → 1.0.7

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 (101) hide show
  1. package/API_SPECIFICATION.md +1117 -0
  2. package/dist/exportType.js +1 -2
  3. package/dist/index.js +25 -30
  4. package/dist/lib/fileUpload.d.ts.map +1 -1
  5. package/dist/lib/fileUpload.js +31 -29
  6. package/dist/lib/googleCloudStorage.js +9 -14
  7. package/dist/lib/prisma.js +4 -7
  8. package/dist/lib/thumbnailGenerator.js +12 -20
  9. package/dist/middleware/auth.d.ts.map +1 -1
  10. package/dist/middleware/auth.js +17 -22
  11. package/dist/middleware/logging.js +5 -9
  12. package/dist/routers/_app.d.ts +3483 -1801
  13. package/dist/routers/_app.d.ts.map +1 -1
  14. package/dist/routers/_app.js +28 -27
  15. package/dist/routers/agenda.d.ts +13 -8
  16. package/dist/routers/agenda.d.ts.map +1 -1
  17. package/dist/routers/agenda.js +14 -17
  18. package/dist/routers/announcement.d.ts +4 -3
  19. package/dist/routers/announcement.d.ts.map +1 -1
  20. package/dist/routers/announcement.js +28 -31
  21. package/dist/routers/assignment.d.ts +282 -196
  22. package/dist/routers/assignment.d.ts.map +1 -1
  23. package/dist/routers/assignment.js +256 -202
  24. package/dist/routers/attendance.d.ts +5 -4
  25. package/dist/routers/attendance.d.ts.map +1 -1
  26. package/dist/routers/attendance.js +31 -34
  27. package/dist/routers/auth.d.ts +1 -0
  28. package/dist/routers/auth.d.ts.map +1 -1
  29. package/dist/routers/auth.js +80 -75
  30. package/dist/routers/class.d.ts +284 -14
  31. package/dist/routers/class.d.ts.map +1 -1
  32. package/dist/routers/class.js +435 -164
  33. package/dist/routers/event.d.ts +47 -38
  34. package/dist/routers/event.d.ts.map +1 -1
  35. package/dist/routers/event.js +76 -79
  36. package/dist/routers/file.d.ts +71 -1
  37. package/dist/routers/file.d.ts.map +1 -1
  38. package/dist/routers/file.js +267 -32
  39. package/dist/routers/folder.d.ts +296 -0
  40. package/dist/routers/folder.d.ts.map +1 -0
  41. package/dist/routers/folder.js +693 -0
  42. package/dist/routers/notifications.d.ts +103 -0
  43. package/dist/routers/notifications.d.ts.map +1 -0
  44. package/dist/routers/notifications.js +91 -0
  45. package/dist/routers/school.d.ts +208 -0
  46. package/dist/routers/school.d.ts.map +1 -0
  47. package/dist/routers/school.js +481 -0
  48. package/dist/routers/section.d.ts +1 -0
  49. package/dist/routers/section.d.ts.map +1 -1
  50. package/dist/routers/section.js +30 -33
  51. package/dist/routers/user.d.ts +2 -1
  52. package/dist/routers/user.d.ts.map +1 -1
  53. package/dist/routers/user.js +21 -24
  54. package/dist/seedDatabase.d.ts +22 -0
  55. package/dist/seedDatabase.d.ts.map +1 -0
  56. package/dist/seedDatabase.js +57 -0
  57. package/dist/socket/handlers.js +26 -30
  58. package/dist/trpc.d.ts +5 -0
  59. package/dist/trpc.d.ts.map +1 -1
  60. package/dist/trpc.js +35 -26
  61. package/dist/types/trpc.js +1 -2
  62. package/dist/utils/email.js +2 -8
  63. package/dist/utils/generateInviteCode.js +1 -5
  64. package/dist/utils/logger.d.ts.map +1 -1
  65. package/dist/utils/logger.js +13 -9
  66. package/dist/utils/prismaErrorHandler.d.ts +9 -0
  67. package/dist/utils/prismaErrorHandler.d.ts.map +1 -0
  68. package/dist/utils/prismaErrorHandler.js +234 -0
  69. package/dist/utils/prismaWrapper.d.ts +14 -0
  70. package/dist/utils/prismaWrapper.d.ts.map +1 -0
  71. package/dist/utils/prismaWrapper.js +64 -0
  72. package/package.json +17 -4
  73. package/prisma/migrations/20250807062924_init/migration.sql +436 -0
  74. package/prisma/migrations/migration_lock.toml +3 -0
  75. package/prisma/schema.prisma +67 -0
  76. package/src/index.ts +2 -2
  77. package/src/lib/fileUpload.ts +16 -7
  78. package/src/middleware/auth.ts +0 -2
  79. package/src/routers/_app.ts +5 -1
  80. package/src/routers/assignment.ts +82 -22
  81. package/src/routers/auth.ts +80 -54
  82. package/src/routers/class.ts +330 -36
  83. package/src/routers/file.ts +283 -20
  84. package/src/routers/folder.ts +755 -0
  85. package/src/routers/notifications.ts +93 -0
  86. package/src/seedDatabase.ts +66 -0
  87. package/src/socket/handlers.ts +4 -4
  88. package/src/trpc.ts +13 -0
  89. package/src/utils/logger.ts +14 -4
  90. package/src/utils/prismaErrorHandler.ts +275 -0
  91. package/src/utils/prismaWrapper.ts +91 -0
  92. package/tests/auth.test.ts +25 -0
  93. package/tests/class.test.ts +281 -0
  94. package/tests/setup.ts +98 -0
  95. package/tests/startup.test.ts +5 -0
  96. package/tsconfig.json +2 -1
  97. package/vitest.config.ts +11 -0
  98. package/dist/logger.d.ts +0 -26
  99. package/dist/logger.d.ts.map +0 -1
  100. package/dist/logger.js +0 -135
  101. package/src/logger.ts +0 -163
@@ -1,7 +1,6 @@
1
- "use strict";
2
1
  /**
3
2
  * Export types for the server
4
3
  * This is used to export the types for the server
5
4
  * to the client via npmjs
6
5
  */
7
- Object.defineProperty(exports, "__esModule", { value: true });
6
+ export {};
package/dist/index.js CHANGED
@@ -1,23 +1,18 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const express_1 = __importDefault(require("express"));
7
- const http_1 = require("http");
8
- const socket_io_1 = require("socket.io");
9
- const cors_1 = __importDefault(require("cors"));
10
- const dotenv_1 = __importDefault(require("dotenv"));
11
- const express_2 = require("@trpc/server/adapters/express");
12
- const _app_1 = require("./routers/_app");
13
- const trpc_1 = require("./trpc");
14
- const logger_1 = require("./utils/logger");
15
- const handlers_1 = require("./socket/handlers");
16
- dotenv_1.default.config();
17
- const app = (0, express_1.default)();
1
+ import express from 'express';
2
+ import { createServer } from 'http';
3
+ import { Server } from 'socket.io';
4
+ import cors from 'cors';
5
+ import dotenv from 'dotenv';
6
+ import { createExpressMiddleware } from '@trpc/server/adapters/express';
7
+ import { appRouter } from './routers/_app';
8
+ import { createTRPCContext, createCallerFactory } from './trpc';
9
+ import { logger } from './utils/logger';
10
+ import { setupSocketHandlers } from './socket/handlers';
11
+ dotenv.config();
12
+ const app = express();
18
13
  // CORS middleware
19
- app.use((0, cors_1.default)({
20
- origin: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',
14
+ app.use(cors({
15
+ origin: [process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000', 'http://localhost:3000'],
21
16
  credentials: true,
22
17
  }));
23
18
  // Response time logging middleware
@@ -25,7 +20,7 @@ app.use((req, res, next) => {
25
20
  const start = Date.now();
26
21
  res.on('finish', () => {
27
22
  const duration = Date.now() - start;
28
- logger_1.logger.info('Request completed', {
23
+ logger.info('Request completed', {
29
24
  method: req.method,
30
25
  path: req.path,
31
26
  statusCode: res.statusCode,
@@ -35,9 +30,9 @@ app.use((req, res, next) => {
35
30
  next();
36
31
  });
37
32
  // Create HTTP server
38
- const httpServer = (0, http_1.createServer)(app);
33
+ const httpServer = createServer(app);
39
34
  // Setup Socket.IO
40
- const io = new socket_io_1.Server(httpServer, {
35
+ const io = new Server(httpServer, {
41
36
  cors: {
42
37
  origin: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',
43
38
  methods: ['GET', 'POST'],
@@ -53,28 +48,28 @@ const io = new socket_io_1.Server(httpServer, {
53
48
  });
54
49
  // Add server-level logging
55
50
  io.engine.on('connection_error', (err) => {
56
- logger_1.logger.error('Socket connection error', { error: err.message });
51
+ logger.error('Socket connection error', { error: err.message });
57
52
  });
58
53
  // Setup socket handlers
59
- (0, handlers_1.setupSocketHandlers)(io);
54
+ setupSocketHandlers(io);
60
55
  // Create caller
61
- const createCaller = (0, trpc_1.createCallerFactory)(_app_1.appRouter);
56
+ const createCaller = createCallerFactory(appRouter);
62
57
  // Setup tRPC middleware
63
- app.use('/trpc', (0, express_2.createExpressMiddleware)({
64
- router: _app_1.appRouter,
58
+ app.use('/trpc', createExpressMiddleware({
59
+ router: appRouter,
65
60
  createContext: async ({ req, res }) => {
66
- return (0, trpc_1.createTRPCContext)({ req, res });
61
+ return createTRPCContext({ req, res });
67
62
  },
68
63
  }));
69
64
  const PORT = process.env.PORT || 3001;
70
65
  httpServer.listen(PORT, () => {
71
- logger_1.logger.info(`Server running on port ${PORT}`, {
66
+ logger.info(`Server running on port ${PORT}`, {
72
67
  port: PORT,
73
68
  services: ['tRPC', 'Socket.IO']
74
69
  });
75
70
  });
76
71
  // log all env variables
77
- logger_1.logger.info('Configurations', {
72
+ logger.info('Configurations', {
78
73
  NODE_ENV: process.env.NODE_ENV,
79
74
  PORT: process.env.PORT,
80
75
  NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
@@ -1 +1 @@
1
- {"version":3,"file":"fileUpload.d.ts","sourceRoot":"","sources":["../../src/lib/fileUpload.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,YAAY,CAAC,CAsFvB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CAWzB;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUlE"}
1
+ {"version":3,"file":"fileUpload.d.ts","sourceRoot":"","sources":["../../src/lib/fileUpload.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,YAAY,CAAC,CA+FvB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CAWzB;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUlE"}
@@ -1,13 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uploadFile = uploadFile;
4
- exports.uploadFiles = uploadFiles;
5
- exports.getFileUrl = getFileUrl;
6
- const server_1 = require("@trpc/server");
7
- const uuid_1 = require("uuid");
8
- const googleCloudStorage_1 = require("./googleCloudStorage");
9
- const thumbnailGenerator_1 = require("./thumbnailGenerator");
10
- const prisma_1 = require("./prisma");
1
+ import { TRPCError } from "@trpc/server";
2
+ import { v4 as uuidv4 } from "uuid";
3
+ import { uploadFile as uploadToGCS, getSignedUrl } from "./googleCloudStorage";
4
+ import { generateMediaThumbnail } from "./thumbnailGenerator";
5
+ import { prisma } from "./prisma";
11
6
  /**
12
7
  * Uploads a single file to Google Cloud Storage and creates a file record
13
8
  * @param file The file data to upload
@@ -16,36 +11,37 @@ const prisma_1 = require("./prisma");
16
11
  * @param assignmentId Optional assignment ID to associate the file with
17
12
  * @returns The uploaded file record
18
13
  */
19
- async function uploadFile(file, userId, directory, assignmentId) {
14
+ export async function uploadFile(file, userId, directory, assignmentId) {
20
15
  try {
21
16
  // Create a unique filename
22
17
  const fileExtension = file.name.split('.').pop();
23
- const uniqueFilename = `${(0, uuid_1.v4)()}.${fileExtension}`;
24
- // Construct the full path
18
+ const uniqueFilename = `${uuidv4()}.${fileExtension}`;
19
+ // // Construct the full path
25
20
  const filePath = directory
26
21
  ? `${directory}/${uniqueFilename}`
27
22
  : uniqueFilename;
28
- // Upload to Google Cloud Storage
29
- const uploadedPath = await (0, googleCloudStorage_1.uploadFile)(file.data, filePath, file.type);
30
- // Generate and store thumbnail if supported
23
+ // // Upload to Google Cloud Storage
24
+ const uploadedPath = await uploadToGCS(file.data, filePath, file.type);
25
+ // // Generate and store thumbnail if supported
31
26
  let thumbnailId;
32
27
  try {
33
- // Convert base64 to buffer for thumbnail generation
28
+ // // Convert base64 to buffer for thumbnail generation
34
29
  const base64Data = file.data.split(',')[1];
35
30
  const fileBuffer = Buffer.from(base64Data, 'base64');
36
- // Generate thumbnail directly from buffer
37
- const thumbnailBuffer = await (0, thumbnailGenerator_1.generateMediaThumbnail)(fileBuffer, file.type);
31
+ // // Generate thumbnail directly from buffer
32
+ const thumbnailBuffer = await generateMediaThumbnail(fileBuffer, file.type);
38
33
  if (thumbnailBuffer) {
39
34
  // Store thumbnail in a thumbnails directory
40
35
  const thumbnailPath = `thumbnails/${filePath}`;
41
36
  const thumbnailBase64 = `data:image/jpeg;base64,${thumbnailBuffer.toString('base64')}`;
42
- await (0, googleCloudStorage_1.uploadFile)(thumbnailBase64, thumbnailPath, 'image/jpeg');
37
+ await uploadToGCS(thumbnailBase64, thumbnailPath, 'image/jpeg');
43
38
  // Create thumbnail file record
44
- const thumbnailFile = await prisma_1.prisma.file.create({
39
+ const thumbnailFile = await prisma.file.create({
45
40
  data: {
46
- name: `${file.name}_thumb.jpg`,
41
+ name: `${file.name}_thumb.jpg${Math.random()}`,
47
42
  type: 'image/jpeg',
48
43
  path: thumbnailPath,
44
+ // path: '/dummyPath' + Math.random().toString(36).substring(2, 15),
49
45
  user: {
50
46
  connect: { id: userId }
51
47
  }
@@ -58,7 +54,8 @@ async function uploadFile(file, userId, directory, assignmentId) {
58
54
  console.warn('Failed to generate thumbnail:', error);
59
55
  }
60
56
  // Create file record in database
61
- const fileRecord = await prisma_1.prisma.file.create({
57
+ // const uploadedPath = '/dummyPath' + Math.random().toString(36).substring(2, 15);
58
+ const fileRecord = await prisma.file.create({
62
59
  data: {
63
60
  name: file.name,
64
61
  type: file.type,
@@ -67,6 +64,11 @@ async function uploadFile(file, userId, directory, assignmentId) {
67
64
  user: {
68
65
  connect: { id: userId }
69
66
  },
67
+ ...(directory && {
68
+ folder: {
69
+ connect: { id: directory },
70
+ },
71
+ }),
70
72
  ...(thumbnailId && {
71
73
  thumbnail: {
72
74
  connect: { id: thumbnailId }
@@ -91,7 +93,7 @@ async function uploadFile(file, userId, directory, assignmentId) {
91
93
  }
92
94
  catch (error) {
93
95
  console.error('Error uploading file:', error);
94
- throw new server_1.TRPCError({
96
+ throw new TRPCError({
95
97
  code: 'INTERNAL_SERVER_ERROR',
96
98
  message: 'Failed to upload file',
97
99
  });
@@ -104,14 +106,14 @@ async function uploadFile(file, userId, directory, assignmentId) {
104
106
  * @param directory Optional subdirectory to store the files in
105
107
  * @returns Array of uploaded file information
106
108
  */
107
- async function uploadFiles(files, userId, directory) {
109
+ export async function uploadFiles(files, userId, directory) {
108
110
  try {
109
111
  const uploadPromises = files.map(file => uploadFile(file, userId, directory));
110
112
  return await Promise.all(uploadPromises);
111
113
  }
112
114
  catch (error) {
113
115
  console.error('Error uploading files:', error);
114
- throw new server_1.TRPCError({
116
+ throw new TRPCError({
115
117
  code: 'INTERNAL_SERVER_ERROR',
116
118
  message: 'Failed to upload files',
117
119
  });
@@ -122,13 +124,13 @@ async function uploadFiles(files, userId, directory) {
122
124
  * @param filePath The path of the file in Google Cloud Storage
123
125
  * @returns The signed URL
124
126
  */
125
- async function getFileUrl(filePath) {
127
+ export async function getFileUrl(filePath) {
126
128
  try {
127
- return await (0, googleCloudStorage_1.getSignedUrl)(filePath);
129
+ return await getSignedUrl(filePath);
128
130
  }
129
131
  catch (error) {
130
132
  console.error('Error getting signed URL:', error);
131
- throw new server_1.TRPCError({
133
+ throw new TRPCError({
132
134
  code: 'INTERNAL_SERVER_ERROR',
133
135
  message: 'Failed to get file URL',
134
136
  });
@@ -1,11 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uploadFile = uploadFile;
4
- exports.getSignedUrl = getSignedUrl;
5
- exports.deleteFile = deleteFile;
6
- const storage_1 = require("@google-cloud/storage");
7
- const server_1 = require("@trpc/server");
8
- const storage = new storage_1.Storage({
1
+ import { Storage } from '@google-cloud/storage';
2
+ import { TRPCError } from '@trpc/server';
3
+ const storage = new Storage({
9
4
  projectId: process.env.GOOGLE_CLOUD_PROJECT_ID,
10
5
  credentials: {
11
6
  client_email: process.env.GOOGLE_CLOUD_CLIENT_EMAIL,
@@ -22,7 +17,7 @@ const SIGNED_URL_EXPIRATION = 5 * 60 * 1000;
22
17
  * @param contentType The MIME type of the file
23
18
  * @returns The path of the uploaded file
24
19
  */
25
- async function uploadFile(base64Data, filePath, contentType) {
20
+ export async function uploadFile(base64Data, filePath, contentType) {
26
21
  try {
27
22
  // Remove the data URL prefix if present
28
23
  const base64Content = base64Data.includes('base64,')
@@ -42,7 +37,7 @@ async function uploadFile(base64Data, filePath, contentType) {
42
37
  }
43
38
  catch (error) {
44
39
  console.error('Error uploading to Google Cloud Storage:', error);
45
- throw new server_1.TRPCError({
40
+ throw new TRPCError({
46
41
  code: 'INTERNAL_SERVER_ERROR',
47
42
  message: 'Failed to upload file to storage',
48
43
  });
@@ -53,7 +48,7 @@ async function uploadFile(base64Data, filePath, contentType) {
53
48
  * @param filePath The path of the file in the bucket
54
49
  * @returns The signed URL
55
50
  */
56
- async function getSignedUrl(filePath) {
51
+ export async function getSignedUrl(filePath) {
57
52
  try {
58
53
  const [url] = await bucket.file(filePath).getSignedUrl({
59
54
  version: 'v4',
@@ -64,7 +59,7 @@ async function getSignedUrl(filePath) {
64
59
  }
65
60
  catch (error) {
66
61
  console.error('Error getting signed URL:', error);
67
- throw new server_1.TRPCError({
62
+ throw new TRPCError({
68
63
  code: 'INTERNAL_SERVER_ERROR',
69
64
  message: 'Failed to get signed URL',
70
65
  });
@@ -74,13 +69,13 @@ async function getSignedUrl(filePath) {
74
69
  * Deletes a file from Google Cloud Storage
75
70
  * @param filePath The path of the file to delete
76
71
  */
77
- async function deleteFile(filePath) {
72
+ export async function deleteFile(filePath) {
78
73
  try {
79
74
  await bucket.file(filePath).delete();
80
75
  }
81
76
  catch (error) {
82
77
  console.error('Error deleting file from Google Cloud Storage:', error);
83
- throw new server_1.TRPCError({
78
+ throw new TRPCError({
84
79
  code: 'INTERNAL_SERVER_ERROR',
85
80
  message: 'Failed to delete file from storage',
86
81
  });
@@ -1,11 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prisma = void 0;
4
- const client_1 = require("@prisma/client");
1
+ import { PrismaClient } from '@prisma/client';
5
2
  const prismaClientSingleton = () => {
6
- return new client_1.PrismaClient();
3
+ return new PrismaClient();
7
4
  };
8
- exports.prisma = globalThis.prisma ?? prismaClientSingleton();
5
+ export const prisma = globalThis.prisma ?? prismaClientSingleton();
9
6
  if (process.env.NODE_ENV !== 'production') {
10
- globalThis.prisma = exports.prisma;
7
+ globalThis.prisma = prisma;
11
8
  }
@@ -1,14 +1,6 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateMediaThumbnail = generateMediaThumbnail;
7
- exports.generateThumbnail = generateThumbnail;
8
- exports.storeThumbnail = storeThumbnail;
9
- const sharp_1 = __importDefault(require("sharp"));
10
- const prisma_1 = require("./prisma");
11
- const googleCloudStorage_1 = require("./googleCloudStorage");
1
+ import sharp from 'sharp';
2
+ import { prisma } from './prisma';
3
+ import { uploadFile, getSignedUrl } from './googleCloudStorage';
12
4
  // Thumbnail size configuration
13
5
  const THUMBNAIL_WIDTH = 200;
14
6
  const THUMBNAIL_HEIGHT = 200;
@@ -55,11 +47,11 @@ const AUDIO_TYPES = [
55
47
  * @param fileType The MIME type of the file
56
48
  * @returns Thumbnail buffer
57
49
  */
58
- async function generateMediaThumbnail(fileBuffer, fileType) {
50
+ export async function generateMediaThumbnail(fileBuffer, fileType) {
59
51
  if (fileType === 'application/pdf') {
60
52
  // For PDFs, we need to use a different approach
61
53
  try {
62
- return await (0, sharp_1.default)(fileBuffer, {
54
+ return await sharp(fileBuffer, {
63
55
  density: 300, // Higher density for better quality
64
56
  page: 0 // First page only
65
57
  })
@@ -76,7 +68,7 @@ async function generateMediaThumbnail(fileBuffer, fileType) {
76
68
  }
77
69
  }
78
70
  // For regular images
79
- return (0, sharp_1.default)(fileBuffer)
71
+ return sharp(fileBuffer)
80
72
  .resize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, {
81
73
  fit: 'inside',
82
74
  withoutEnlargement: true,
@@ -91,7 +83,7 @@ async function generateMediaThumbnail(fileBuffer, fileType) {
91
83
  */
92
84
  async function generateGenericThumbnail(fileType) {
93
85
  // Create a blank canvas with a colored background based on file type
94
- const canvas = (0, sharp_1.default)({
86
+ const canvas = sharp({
95
87
  create: {
96
88
  width: THUMBNAIL_WIDTH,
97
89
  height: THUMBNAIL_HEIGHT,
@@ -130,9 +122,9 @@ async function generateGenericThumbnail(fileType) {
130
122
  * @param fileType The MIME type of the file
131
123
  * @returns The thumbnail buffer or null if thumbnail generation is not supported
132
124
  */
133
- async function generateThumbnail(fileName, fileType) {
125
+ export async function generateThumbnail(fileName, fileType) {
134
126
  try {
135
- const signedUrl = await (0, googleCloudStorage_1.getSignedUrl)(fileName);
127
+ const signedUrl = await getSignedUrl(fileName);
136
128
  const response = await fetch(signedUrl);
137
129
  if (!response.ok) {
138
130
  throw new Error(`Failed to download file from storage: ${response.status} ${response.statusText}`);
@@ -163,12 +155,12 @@ async function generateThumbnail(fileName, fileType) {
163
155
  * @param userId The user ID who owns the file
164
156
  * @returns The ID of the created thumbnail File
165
157
  */
166
- async function storeThumbnail(thumbnailBuffer, originalFileName, userId) {
158
+ export async function storeThumbnail(thumbnailBuffer, originalFileName, userId) {
167
159
  // Convert buffer to base64 for uploadFile function
168
160
  const base64Data = `data:image/jpeg;base64,${thumbnailBuffer.toString('base64')}`;
169
- const thumbnailFileName = await (0, googleCloudStorage_1.uploadFile)(base64Data, `thumbnails/${originalFileName}_thumb`, 'image/jpeg');
161
+ const thumbnailFileName = await uploadFile(base64Data, `thumbnails/${originalFileName}_thumb`, 'image/jpeg');
170
162
  // Create a new File entry for the thumbnail
171
- const newThumbnail = await prisma_1.prisma.file.create({
163
+ const newThumbnail = await prisma.file.create({
172
164
  data: {
173
165
  name: `${originalFileName}_thumb.jpg`,
174
166
  path: thumbnailFileName,
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB,GAAI,GAAG,GAAG;;;;;CA0L1C,CAAC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB,GAAI,GAAG,GAAG;;;;;CAwL1C,CAAC"}
@@ -1,16 +1,13 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createAuthMiddleware = void 0;
4
- const server_1 = require("@trpc/server");
5
- const prisma_1 = require("../lib/prisma");
6
- const createAuthMiddleware = (t) => {
1
+ import { TRPCError } from '@trpc/server';
2
+ import { prisma } from '../lib/prisma';
3
+ export const createAuthMiddleware = (t) => {
7
4
  // Auth middleware
8
5
  const isAuthed = t.middleware(async ({ next, ctx }) => {
9
6
  const startTime = Date.now();
10
7
  // Get user from request headers
11
8
  const userHeader = ctx.req.headers['x-user'];
12
9
  if (!userHeader) {
13
- throw new server_1.TRPCError({
10
+ throw new TRPCError({
14
11
  code: 'UNAUTHORIZED',
15
12
  message: 'Not authenticated - no token found',
16
13
  });
@@ -18,7 +15,7 @@ const createAuthMiddleware = (t) => {
18
15
  try {
19
16
  const token = typeof userHeader === 'string' ? userHeader : userHeader[0];
20
17
  // Find user by session token
21
- const user = await prisma_1.prisma.user.findFirst({
18
+ const user = await prisma.user.findFirst({
22
19
  where: {
23
20
  sessions: {
24
21
  some: {
@@ -33,12 +30,11 @@ const createAuthMiddleware = (t) => {
33
30
  }
34
31
  });
35
32
  if (!user) {
36
- throw new server_1.TRPCError({
33
+ throw new TRPCError({
37
34
  code: 'UNAUTHORIZED',
38
35
  message: 'Invalid or expired session',
39
36
  });
40
37
  }
41
- console.log(user);
42
38
  return next({
43
39
  ctx: {
44
40
  ...ctx,
@@ -48,7 +44,7 @@ const createAuthMiddleware = (t) => {
48
44
  }
49
45
  catch (error) {
50
46
  console.log(error);
51
- throw new server_1.TRPCError({
47
+ throw new TRPCError({
52
48
  code: 'UNAUTHORIZED',
53
49
  message: 'Invalid user data',
54
50
  });
@@ -57,13 +53,13 @@ const createAuthMiddleware = (t) => {
57
53
  // Add computed flags middleware
58
54
  const addComputedFlags = t.middleware(async ({ next, ctx }) => {
59
55
  if (!ctx.user) {
60
- throw new server_1.TRPCError({
56
+ throw new TRPCError({
61
57
  code: 'UNAUTHORIZED',
62
58
  message: 'Not authenticated',
63
59
  });
64
60
  }
65
61
  // Get all classes where user is a teacher
66
- const teacherClasses = await prisma_1.prisma.class.findMany({
62
+ const teacherClasses = await prisma.class.findMany({
67
63
  where: {
68
64
  teachers: {
69
65
  some: {
@@ -86,19 +82,19 @@ const createAuthMiddleware = (t) => {
86
82
  // Student middleware
87
83
  const isMemberInClass = t.middleware(async ({ next, ctx, input }) => {
88
84
  if (!ctx.user) {
89
- throw new server_1.TRPCError({
85
+ throw new TRPCError({
90
86
  code: 'UNAUTHORIZED',
91
87
  message: 'Not authenticated',
92
88
  });
93
89
  }
94
90
  const classId = input?.classId;
95
91
  if (!classId) {
96
- throw new server_1.TRPCError({
92
+ throw new TRPCError({
97
93
  code: 'BAD_REQUEST',
98
94
  message: 'classId is required',
99
95
  });
100
96
  }
101
- const isMember = await prisma_1.prisma.class.findFirst({
97
+ const isMember = await prisma.class.findFirst({
102
98
  where: {
103
99
  id: classId,
104
100
  OR: [
@@ -120,7 +116,7 @@ const createAuthMiddleware = (t) => {
120
116
  }
121
117
  });
122
118
  if (!isMember) {
123
- throw new server_1.TRPCError({
119
+ throw new TRPCError({
124
120
  code: 'FORBIDDEN',
125
121
  message: 'Not a member in this class',
126
122
  });
@@ -130,19 +126,19 @@ const createAuthMiddleware = (t) => {
130
126
  // Teacher middleware
131
127
  const isTeacherInClass = t.middleware(async ({ next, ctx, input }) => {
132
128
  if (!ctx.user) {
133
- throw new server_1.TRPCError({
129
+ throw new TRPCError({
134
130
  code: 'UNAUTHORIZED',
135
131
  message: 'Not authenticated',
136
132
  });
137
133
  }
138
134
  const classId = input.classId;
139
135
  if (!classId) {
140
- throw new server_1.TRPCError({
136
+ throw new TRPCError({
141
137
  code: 'BAD_REQUEST',
142
138
  message: 'classId is required',
143
139
  });
144
140
  }
145
- const isTeacher = await prisma_1.prisma.class.findFirst({
141
+ const isTeacher = await prisma.class.findFirst({
146
142
  where: {
147
143
  id: classId,
148
144
  teachers: {
@@ -153,7 +149,7 @@ const createAuthMiddleware = (t) => {
153
149
  }
154
150
  });
155
151
  if (!isTeacher) {
156
- throw new server_1.TRPCError({
152
+ throw new TRPCError({
157
153
  code: 'FORBIDDEN',
158
154
  message: 'Not a teacher in this class',
159
155
  });
@@ -167,4 +163,3 @@ const createAuthMiddleware = (t) => {
167
163
  isTeacherInClass,
168
164
  };
169
165
  };
170
- exports.createAuthMiddleware = createAuthMiddleware;
@@ -1,13 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createLoggingMiddleware = void 0;
4
- const logger_1 = require("../utils/logger");
5
- const createLoggingMiddleware = (t) => {
1
+ import { logger } from '../utils/logger';
2
+ export const createLoggingMiddleware = (t) => {
6
3
  return t.middleware(async ({ path, type, next, ctx }) => {
7
4
  const start = Date.now();
8
5
  const requestId = crypto.randomUUID();
9
6
  // Log request
10
- logger_1.logger.info('tRPC Request', {
7
+ logger.info('tRPC Request', {
11
8
  requestId,
12
9
  path,
13
10
  type,
@@ -18,7 +15,7 @@ const createLoggingMiddleware = (t) => {
18
15
  const result = await next();
19
16
  const durationMs = Date.now() - start;
20
17
  // Log successful response
21
- logger_1.logger.info('tRPC Response', {
18
+ logger.info('tRPC Response', {
22
19
  requestId,
23
20
  path,
24
21
  type,
@@ -31,7 +28,7 @@ const createLoggingMiddleware = (t) => {
31
28
  catch (error) {
32
29
  const durationMs = Date.now() - start;
33
30
  // Log error response
34
- logger_1.logger.error('tRPC Error' + path, {
31
+ logger.error('tRPC Error' + path, {
35
32
  requestId,
36
33
  path,
37
34
  type,
@@ -48,4 +45,3 @@ const createLoggingMiddleware = (t) => {
48
45
  }
49
46
  });
50
47
  };
51
- exports.createLoggingMiddleware = createLoggingMiddleware;