Skip to content

Commit ec358f4

Browse files
committed
feat: added /documents endpoint and multiple docs upload
1 parent b4c606e commit ec358f4

File tree

10 files changed

+127
-28
lines changed

10 files changed

+127
-28
lines changed

src/app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { appConfig } from './config'
88

99
import AuthRoutes from '@/modules/auth/application/routes'
1010
import GenAIRoutes from '@/modules/genai/application/routes'
11+
import ResourcesRoutes from '@/modules/resources/application/routes'
1112
import StatusRoutes from '@/modules/status/application/routes'
1213
import UserRoutes from '@/modules/users/application/routes'
1314

@@ -29,6 +30,7 @@ app.use('/', AuthRoutes)
2930
app.use('/status', StatusRoutes)
3031
app.use('/users', UserRoutes)
3132
app.use('/gen-ai', GenAIRoutes)
33+
app.use('/resources', ResourcesRoutes)
3234

3335
app.listen(port, () => {
3436
console.log(`Server listening to http://localhost:${port}`)

src/di/index.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99

1010
import { AuthController } from '@/modules/auth/application/controllers/auth.controller'
1111
import { GenAIController } from '@/modules/genai/application/controllers/gen-ai.controller'
12+
import { ResourcesController } from '@/modules/resources/application/controllers/resources.controller'
1213
import { UserDataProvider } from '@/modules/users/adapters/dataproviders/user.dataprovider'
1314
import { UsersController } from '@/modules/users/application/controllers/users.controller'
1415

@@ -33,14 +34,18 @@ const usersController = new UsersController(userDatProvider)
3334
// Auth Module
3435
const authController = new AuthController(userDatProvider)
3536

37+
// Resources Module
38+
const resourcesController = new ResourcesController()
39+
3640
export {
37-
authController,
38-
documentService,
39-
genAIController,
40-
llmService,
41-
prismaClient,
42-
searchInDocumentUseCase,
43-
translateUseCase,
44-
userDatProvider,
45-
usersController
41+
authController,
42+
documentService,
43+
genAIController,
44+
llmService,
45+
prismaClient,
46+
resourcesController,
47+
searchInDocumentUseCase,
48+
translateUseCase,
49+
userDatProvider,
50+
usersController,
4651
}

src/modules/core/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './utils'

src/modules/core/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './upload.config'
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { Request, Response } from 'express'
2+
3+
import crypto from 'crypto'
4+
import multer from 'multer'
5+
import path from 'path'
6+
7+
const storageConfig = multer.diskStorage({
8+
destination: (_, __, callBack) => {
9+
callBack(null, 'uploads/')
10+
},
11+
filename: (_, file, callBack) => {
12+
const fileExt = path.extname(file.originalname)
13+
const fileName = `user-document-${crypto.randomUUID()}${fileExt}`
14+
callBack(null, fileName)
15+
},
16+
})
17+
18+
const fileFilter = (
19+
_: Request,
20+
file: Express.Multer.File,
21+
cb: multer.FileFilterCallback,
22+
) => {
23+
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf']
24+
if (allowedTypes.includes(file.mimetype)) {
25+
cb(null, true)
26+
} else {
27+
cb(new Error('Invalid file type. Only JPEG, PNG, and PDF are allowed.'))
28+
}
29+
}
30+
31+
export const uploadSingle = multer({
32+
storage: storageConfig,
33+
fileFilter,
34+
limits: { fileSize: 5 * 1024 * 1024 },
35+
}).single('document')
36+
37+
export const uploadMultipleDocs = multer({
38+
storage: storageConfig,
39+
fileFilter,
40+
limits: { fileSize: 5 * 1024 * 1024 },
41+
}).array('documents', 10)
42+
43+
export function handleMulterErrorMessages(err: any, res: Response): Response {
44+
if (err instanceof multer.MulterError) {
45+
switch (err.code) {
46+
case 'LIMIT_FILE_SIZE':
47+
return res.status(400).json({ error: 'File size exceeds the limit!' })
48+
case 'LIMIT_FILE_COUNT':
49+
return res.status(400).json({ error: 'Too many files uploaded!' })
50+
case 'LIMIT_UNEXPECTED_FILE':
51+
return res.status(400).json({ error: 'Unexpected file uploaded!' })
52+
default:
53+
return res
54+
.status(400)
55+
.json({ error: 'Unexpected error was occurred while uploading!' })
56+
}
57+
}
58+
59+
return res.status(500).json({ error: 'An unknown error occurred!' })
60+
}

src/modules/genai/application/controllers/gen-ai.controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AppRequest, AppResponse } from '@/common/types';
22
import { searchInDocumentUseCase, translateUseCase } from '@/di';
3-
import { upload } from '../../core';
3+
import { uploadSingle } from '@/modules/core'
44

55
export class GenAIController {
66
async translateText(
@@ -16,7 +16,7 @@ export class GenAIController {
1616
req: AppRequest<any, any, { query: string }>,
1717
res: AppResponse,
1818
) {
19-
upload(req, res, async (err) => {
19+
uploadSingle(req, res, async (err) => {
2020
if (err) {
2121
return res
2222
.status(500)
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
export * from './constants'
2-
export * from './upload.config'

src/modules/genai/core/utils/upload.config.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { AppRequest, AppResponse } from '@/common/types'
2+
import { handleMulterErrorMessages, uploadMultipleDocs } from '@/modules/core'
3+
4+
export class ResourcesController {
5+
async uploadDocs(
6+
req: AppRequest<any, any, { query: string }>,
7+
res: AppResponse,
8+
) {
9+
uploadMultipleDocs(req, res, async (err) => {
10+
if (err) handleMulterErrorMessages(err, res)
11+
12+
if (!req.files || (req.files as Express.Multer.File[]).length === 0) {
13+
return res.status(400).json({
14+
success: false,
15+
error: { message: 'Please provide at least one document!' },
16+
})
17+
}
18+
19+
const files = req.files as Express.Multer.File[]
20+
const fileDetails = files.map((file) => ({
21+
originalName: file.originalname,
22+
fileName: file.filename,
23+
path: file.path,
24+
size: file.size,
25+
}))
26+
27+
// TODO: Implement logic to process and store the uploaded files
28+
29+
return res.status(201).json({
30+
success: true,
31+
data: {
32+
documents: fileDetails,
33+
},
34+
})
35+
})
36+
}
37+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import express from 'express'
2+
3+
import { isAuthenticated } from '@/common/middlewares'
4+
import { resourcesController } from '@/di'
5+
6+
const router = express.Router()
7+
8+
router.post('/docs', isAuthenticated, resourcesController.uploadDocs)
9+
10+
export default router

0 commit comments

Comments
 (0)