arkos 1.0.1-beta → 1.0.2-alpha

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 (65) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/app.js +1 -1
  3. package/dist/cjs/app.js.map +1 -1
  4. package/dist/cjs/exports/services/index.js +3 -3
  5. package/dist/cjs/exports/services/index.js.map +1 -1
  6. package/dist/cjs/modules/auth/__tests__/auth.controller.test.js +0 -1
  7. package/dist/cjs/modules/auth/__tests__/auth.controller.test.js.map +1 -1
  8. package/dist/cjs/modules/auth/__tests__/auth.service.test.js +470 -0
  9. package/dist/cjs/modules/auth/__tests__/auth.service.test.js.map +1 -0
  10. package/dist/cjs/modules/auth/auth.service.js +30 -9
  11. package/dist/cjs/modules/auth/auth.service.js.map +1 -1
  12. package/dist/cjs/modules/email/email.service.js +12 -7
  13. package/dist/cjs/modules/email/email.service.js.map +1 -1
  14. package/dist/cjs/modules/file-uploader/__tests__/file-uploader.service.test.js +402 -0
  15. package/dist/cjs/modules/file-uploader/__tests__/file-uploader.service.test.js.map +1 -0
  16. package/dist/cjs/modules/file-uploader/file-uploader.controller.js +226 -0
  17. package/dist/cjs/modules/file-uploader/file-uploader.controller.js.map +1 -0
  18. package/dist/cjs/modules/file-uploader/file-uploader.router.js +50 -0
  19. package/dist/cjs/modules/file-uploader/file-uploader.router.js.map +1 -0
  20. package/dist/cjs/modules/file-uploader/file-uploader.service.js +299 -0
  21. package/dist/cjs/modules/file-uploader/file-uploader.service.js.map +1 -0
  22. package/dist/cjs/modules/file-uploader/utils/helpers/__tests__/file-uploader.helpers.test.js +164 -0
  23. package/dist/cjs/modules/file-uploader/utils/helpers/__tests__/file-uploader.helpers.test.js.map +1 -0
  24. package/dist/cjs/modules/file-uploader/utils/helpers/file-uploader.helpers.js +85 -0
  25. package/dist/cjs/modules/file-uploader/utils/helpers/file-uploader.helpers.js.map +1 -0
  26. package/dist/cjs/server.js +1 -1
  27. package/dist/cjs/server.js.map +1 -1
  28. package/dist/cjs/types/arkos-config.js.map +1 -1
  29. package/dist/cjs/types/auth.js.map +1 -1
  30. package/dist/cjs/types/index.js.map +1 -1
  31. package/dist/cjs/utils/helpers/models.helpers.js +19 -6
  32. package/dist/cjs/utils/helpers/models.helpers.js.map +1 -1
  33. package/dist/es2020/app.js +1 -1
  34. package/dist/es2020/app.js.map +1 -1
  35. package/dist/es2020/exports/services/index.js +1 -1
  36. package/dist/es2020/exports/services/index.js.map +1 -1
  37. package/dist/es2020/modules/auth/auth.service.js +30 -9
  38. package/dist/es2020/modules/auth/auth.service.js.map +1 -1
  39. package/dist/es2020/modules/email/email.service.js +12 -7
  40. package/dist/es2020/modules/email/email.service.js.map +1 -1
  41. package/dist/es2020/modules/file-uploader/file-uploader.controller.js +220 -0
  42. package/dist/es2020/modules/file-uploader/file-uploader.controller.js.map +1 -0
  43. package/dist/es2020/modules/file-uploader/file-uploader.router.js +44 -0
  44. package/dist/es2020/modules/file-uploader/file-uploader.router.js.map +1 -0
  45. package/dist/es2020/modules/file-uploader/file-uploader.service.js +291 -0
  46. package/dist/es2020/modules/file-uploader/file-uploader.service.js.map +1 -0
  47. package/dist/es2020/modules/file-uploader/utils/helpers/file-uploader.helpers.js +77 -0
  48. package/dist/es2020/modules/file-uploader/utils/helpers/file-uploader.helpers.js.map +1 -0
  49. package/dist/es2020/server.js +1 -1
  50. package/dist/es2020/server.js.map +1 -1
  51. package/dist/es2020/types/arkos-config.js.map +1 -1
  52. package/dist/es2020/types/auth.js.map +1 -1
  53. package/dist/es2020/types/index.js.map +1 -1
  54. package/dist/es2020/utils/helpers/models.helpers.js +19 -6
  55. package/dist/es2020/utils/helpers/models.helpers.js.map +1 -1
  56. package/dist/types/exports/services/index.d.ts +1 -1
  57. package/dist/types/modules/email/email.service.d.ts +1 -2
  58. package/dist/types/modules/file-uploader/file-uploader.controller.d.ts +3 -0
  59. package/dist/types/modules/file-uploader/file-uploader.router.d.ts +3 -0
  60. package/dist/types/modules/file-uploader/file-uploader.service.d.ts +30 -0
  61. package/dist/types/modules/file-uploader/utils/helpers/file-uploader.helpers.d.ts +2 -0
  62. package/dist/types/types/arkos-config.d.ts +8 -1
  63. package/dist/types/types/auth.d.ts +2 -2
  64. package/dist/types/types/index.d.ts +1 -0
  65. package/package.json +6 -7
@@ -0,0 +1,299 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.getFileUploaderServices = exports.FileUploaderService = void 0;
16
+ const multer_1 = __importDefault(require("multer"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const fs_1 = __importDefault(require("fs"));
19
+ const app_error_1 = __importDefault(require("../error-handler/utils/app-error"));
20
+ const util_1 = require("util");
21
+ const server_1 = require("../../server");
22
+ const deepmerge_helper_1 = __importDefault(require("../../utils/helpers/deepmerge.helper"));
23
+ const file_uploader_helpers_1 = require("./utils/helpers/file-uploader.helpers");
24
+ class FileUploaderService {
25
+ constructor(uploadDir, fileSizeLimit = 1024 * 1024 * 5, allowedFileTypes = /.*/, maxCount = 30) {
26
+ this.fileFilter = (req, file, cb) => {
27
+ const extName = this.allowedFileTypes.test(path_1.default.extname(file.originalname).toLowerCase());
28
+ const mimeType = this.allowedFileTypes.test(file.mimetype);
29
+ if (mimeType && extName) {
30
+ cb(null, true);
31
+ }
32
+ else {
33
+ cb(new app_error_1.default("Invalid file type", 400));
34
+ }
35
+ };
36
+ uploadDir = uploadDir.startsWith("/") ? uploadDir.substring(1) : uploadDir;
37
+ uploadDir = uploadDir.endsWith("/") ? uploadDir.slice(0, -1) : uploadDir;
38
+ this.uploadDir = path_1.default.join(".", `${uploadDir}/`);
39
+ this.fileSizeLimit = fileSizeLimit;
40
+ this.allowedFileTypes = allowedFileTypes;
41
+ this.maxCount = maxCount;
42
+ if (!fs_1.default.existsSync(this.uploadDir)) {
43
+ fs_1.default.mkdirSync(this.uploadDir, { recursive: true });
44
+ }
45
+ this.storage = multer_1.default.diskStorage({
46
+ destination: (req, file, cb) => {
47
+ cb(null, this.uploadDir);
48
+ },
49
+ filename: (req, file, cb) => {
50
+ const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
51
+ cb(null, `${uniqueSuffix}${path_1.default.extname(file.originalname)}`);
52
+ },
53
+ });
54
+ }
55
+ getUploader() {
56
+ return (0, multer_1.default)({
57
+ storage: this.storage,
58
+ fileFilter: this.fileFilter,
59
+ limits: { fileSize: this.fileSizeLimit },
60
+ });
61
+ }
62
+ handleSingleUpload(oldFilePath) {
63
+ return (req, res, next) => {
64
+ const upload = this.getUploader().single(this.getFieldName());
65
+ upload(req, res, (err) => __awaiter(this, void 0, void 0, function* () {
66
+ if (err instanceof multer_1.default.MulterError) {
67
+ return next(err);
68
+ }
69
+ else if (err) {
70
+ return next(err);
71
+ }
72
+ if (oldFilePath) {
73
+ const filePath = path_1.default.join(oldFilePath);
74
+ try {
75
+ const stats = yield (0, util_1.promisify)(fs_1.default.stat)(filePath);
76
+ if (stats)
77
+ yield (0, util_1.promisify)(fs_1.default.unlink)(filePath);
78
+ }
79
+ catch (err) {
80
+ console.error(err);
81
+ }
82
+ }
83
+ next();
84
+ }));
85
+ };
86
+ }
87
+ handleMultipleUpload() {
88
+ return (req, res, next) => {
89
+ const upload = this.getUploader().array(this.getFieldName(), this.maxCount);
90
+ upload(req, res, (err) => {
91
+ if (err instanceof multer_1.default.MulterError)
92
+ return next(err);
93
+ else if (err)
94
+ return next(err);
95
+ next();
96
+ });
97
+ };
98
+ }
99
+ handleDeleteSingleFile(oldFilePath) {
100
+ return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
101
+ const filePath = path_1.default.join(oldFilePath);
102
+ try {
103
+ const stats = yield (0, util_1.promisify)(fs_1.default.stat)(filePath);
104
+ if (stats) {
105
+ yield (0, util_1.promisify)(fs_1.default.unlink)(filePath);
106
+ }
107
+ }
108
+ catch (err) {
109
+ console.error(err);
110
+ }
111
+ next();
112
+ });
113
+ }
114
+ deleteFileByUrl(fileUrl) {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ try {
117
+ const { fileUpload } = (0, server_1.getArkosConfig)();
118
+ const baseRoute = (fileUpload === null || fileUpload === void 0 ? void 0 : fileUpload.baseRoute) || "/api/uploads";
119
+ let urlPath;
120
+ if (fileUrl.startsWith("http")) {
121
+ const url = new URL(fileUrl);
122
+ urlPath = url.pathname;
123
+ }
124
+ else {
125
+ urlPath = fileUrl;
126
+ }
127
+ const baseRouteIndex = urlPath.indexOf(baseRoute);
128
+ if (baseRouteIndex === -1) {
129
+ throw new app_error_1.default("Invalid file URL: base route not found", 400);
130
+ }
131
+ const pathAfterBaseRoute = urlPath.substring(baseRouteIndex + baseRoute.length);
132
+ const cleanPath = pathAfterBaseRoute.startsWith("/")
133
+ ? pathAfterBaseRoute.substring(1)
134
+ : pathAfterBaseRoute;
135
+ const fileTypes = ["images", "videos", "documents", "files"];
136
+ let fileType = null;
137
+ let fileName = null;
138
+ for (const type of fileTypes) {
139
+ const typeIndex = cleanPath.indexOf(type + "/");
140
+ if (typeIndex !== -1) {
141
+ fileType = type;
142
+ fileName = cleanPath.substring(typeIndex + type.length + 1);
143
+ break;
144
+ }
145
+ }
146
+ if (!fileType || !fileName) {
147
+ throw new app_error_1.default("Unable to determine file type or file name from URL", 400);
148
+ }
149
+ const { documentUploaderService, fileUploaderService, imageUploaderService, videoUploaderService, } = (0, exports.getFileUploaderServices)();
150
+ let filePath;
151
+ switch (fileType) {
152
+ case "images":
153
+ filePath = path_1.default.join(imageUploaderService.uploadDir, fileName);
154
+ break;
155
+ case "videos":
156
+ filePath = path_1.default.join(videoUploaderService.uploadDir, fileName);
157
+ break;
158
+ case "documents":
159
+ filePath = path_1.default.join(documentUploaderService.uploadDir, fileName);
160
+ break;
161
+ case "files":
162
+ filePath = path_1.default.join(fileUploaderService.uploadDir, fileName);
163
+ break;
164
+ default:
165
+ throw new app_error_1.default(`Unsupported file type: ${fileType}`, 400);
166
+ }
167
+ yield (0, util_1.promisify)(fs_1.default.stat)(filePath);
168
+ yield (0, util_1.promisify)(fs_1.default.unlink)(filePath);
169
+ return true;
170
+ }
171
+ catch (error) {
172
+ if (error instanceof app_error_1.default) {
173
+ throw error;
174
+ }
175
+ if (error.code === "ENOENT") {
176
+ throw new app_error_1.default("File not found", 404);
177
+ }
178
+ throw new app_error_1.default(`Failed to delete file: ${error.message}`, 500);
179
+ }
180
+ });
181
+ }
182
+ getFieldName() {
183
+ let fieldName = "files";
184
+ if (this.uploadDir.endsWith("images") || this.uploadDir.endsWith("images/"))
185
+ fieldName === "images";
186
+ if (this.uploadDir.endsWith("videos") || this.uploadDir.endsWith("videos/"))
187
+ fieldName === "videos";
188
+ if (this.uploadDir.endsWith("documents") ||
189
+ this.uploadDir.endsWith("documents/"))
190
+ fieldName === "documents";
191
+ if (this.uploadDir.endsWith("files") || this.uploadDir.endsWith("files/"))
192
+ fieldName === "files";
193
+ return fieldName;
194
+ }
195
+ upload(req_1, res_1) {
196
+ return __awaiter(this, arguments, void 0, function* (req, res, options = {}) {
197
+ const { fileUpload } = (0, server_1.getArkosConfig)();
198
+ const baseRoute = (fileUpload === null || fileUpload === void 0 ? void 0 : fileUpload.baseRoute) || "/api/uploads";
199
+ return new Promise((resolve, reject) => {
200
+ const isMultiple = Array.isArray(req.query.multiple)
201
+ ? req.query.multiple[0] == "true"
202
+ : req.query.multiple == "true";
203
+ const uploadHandler = isMultiple
204
+ ? this.getUploader().array(this.getFieldName(), this.maxCount)
205
+ : this.getUploader().single(this.getFieldName());
206
+ uploadHandler(req, res, (err) => __awaiter(this, void 0, void 0, function* () {
207
+ var _a;
208
+ if (err)
209
+ return reject(err);
210
+ try {
211
+ const protocol = ((_a = req.get("host")) === null || _a === void 0 ? void 0 : _a.includes("localhost"))
212
+ ? "http"
213
+ : "https";
214
+ const baseURL = `${protocol}://${req.get("host")}`;
215
+ const dirParts = this.uploadDir.split("/");
216
+ const fileType = (this.uploadDir.endsWith("/")
217
+ ? dirParts[dirParts.length - 2]
218
+ : dirParts[dirParts.length - 1]) || "files";
219
+ let data;
220
+ if (req.files && Array.isArray(req.files) && req.files.length > 0) {
221
+ const isImageUploader = this.uploadDir.includes("/images");
222
+ if (isImageUploader) {
223
+ data = yield Promise.all(req.files.map((file) => (0, file_uploader_helpers_1.processImage)(file.path, baseURL, baseRoute, options, fileType)));
224
+ }
225
+ else {
226
+ data = yield Promise.all(req.files.map((file) => (0, file_uploader_helpers_1.processFile)(file.path, baseURL, baseRoute, fileType)));
227
+ }
228
+ data = data.filter((url) => url !== null);
229
+ }
230
+ else if (req.file) {
231
+ const isImageUploader = this.uploadDir.includes("/images");
232
+ if (isImageUploader) {
233
+ data = yield (0, file_uploader_helpers_1.processImage)(req.file.path, baseURL, baseRoute, options, fileType);
234
+ }
235
+ else {
236
+ data = yield (0, file_uploader_helpers_1.processFile)(req.file.path, baseURL, baseRoute, fileType);
237
+ }
238
+ }
239
+ else {
240
+ return reject(new app_error_1.default("No file uploaded", 400));
241
+ }
242
+ resolve(data);
243
+ }
244
+ catch (error) {
245
+ reject(error);
246
+ }
247
+ }));
248
+ });
249
+ });
250
+ }
251
+ }
252
+ exports.FileUploaderService = FileUploaderService;
253
+ const getFileUploaderServices = () => {
254
+ const { fileUpload } = (0, server_1.getArkosConfig)();
255
+ const baseUploadDir = (fileUpload === null || fileUpload === void 0 ? void 0 : fileUpload.baseUploadDir) || "/uploads";
256
+ const defaultRegexPatterns = {
257
+ image: /jpeg|jpg|png|gif|webp|svg|bmp|tiff|heif|heic|ico|jfif|raw|cr2|nef|orf|sr2|arw|dng|pef|raf|rw2|psd|ai|eps|xcf|jxr|wdp|hdp|jp2|j2k|jpf|jpx|jpm|mj2|avif/,
258
+ video: /mp4|avi|mov|mkv|flv|wmv|webm|mpg|mpeg|3gp|m4v|ts|rm|rmvb|vob|ogv|dv|qt|asf|m2ts|mts|divx|f4v|swf|mxf|roq|nsv|mvb|svi|mpe|m2v|mp2|mpv|h264|h265|hevc/,
259
+ document: /pdf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odg|odp|txt|rtf|csv|epub|md|tex|pages|numbers|key|xml|json|yaml|yml|ini|cfg|conf|log|html|htm|xhtml|djvu|mobi|azw|azw3|fb2|lit|ps|wpd|wps|dot|dotx|xlt|xltx|pot|potx|oft|one|onetoc2|opf|oxps|hwp/,
260
+ other: /.*/,
261
+ };
262
+ const defaultRestrictions = {
263
+ images: {
264
+ maxCount: 30,
265
+ maxSize: 1024 * 1024 * 15,
266
+ supportedFilesRegex: defaultRegexPatterns.image,
267
+ },
268
+ videos: {
269
+ maxCount: 10,
270
+ maxSize: 1024 * 1024 * 5096,
271
+ supportedFilesRegex: defaultRegexPatterns.video,
272
+ },
273
+ documents: {
274
+ maxCount: 30,
275
+ maxSize: 1024 * 1024 * 50,
276
+ supportedFilesRegex: defaultRegexPatterns.document,
277
+ },
278
+ others: {
279
+ maxCount: 10,
280
+ maxSize: 1024 * 1024 * 5096,
281
+ supportedFilesRegex: defaultRegexPatterns.other,
282
+ },
283
+ };
284
+ const restrictions = (fileUpload === null || fileUpload === void 0 ? void 0 : fileUpload.restrictions)
285
+ ? (0, deepmerge_helper_1.default)(defaultRestrictions, fileUpload.restrictions)
286
+ : defaultRestrictions;
287
+ const imageUploaderService = new FileUploaderService(`${baseUploadDir}/images`, restrictions.images.maxSize, restrictions.images.supportedFilesRegex, restrictions.images.maxCount);
288
+ const videoUploaderService = new FileUploaderService(`${baseUploadDir}/videos`, restrictions.videos.maxSize, restrictions.videos.supportedFilesRegex, restrictions.videos.maxCount);
289
+ const documentUploaderService = new FileUploaderService(`${baseUploadDir}/documents`, restrictions.documents.maxSize, restrictions.documents.supportedFilesRegex, restrictions.documents.maxCount);
290
+ const fileUploaderService = new FileUploaderService(`${baseUploadDir}/files`, restrictions.others.maxSize, restrictions.others.supportedFilesRegex, restrictions.others.maxCount);
291
+ return {
292
+ imageUploaderService,
293
+ videoUploaderService,
294
+ documentUploaderService,
295
+ fileUploaderService,
296
+ };
297
+ };
298
+ exports.getFileUploaderServices = getFileUploaderServices;
299
+ //# sourceMappingURL=file-uploader.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-uploader.service.js","sourceRoot":"","sources":["../../../../src/modules/file-uploader/file-uploader.service.ts"],"names":[],"mappings":"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","sourcesContent":["import multer, { StorageEngine } from \"multer\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { NextFunction } from \"express\";\nimport AppError from \"../error-handler/utils/app-error\";\nimport { promisify } from \"util\";\nimport { getArkosConfig } from \"../../server\";\nimport deepmerge from \"../../utils/helpers/deepmerge.helper\";\nimport { ArkosRequest, ArkosResponse } from \"../../types\";\nimport {\n processFile,\n processImage,\n} from \"./utils/helpers/file-uploader.helpers\";\n\n/**\n * Service to handle file uploads, including single and multiple file uploads,\n * file validation (type, size), and file deletion.\n */\nexport class FileUploaderService {\n private uploadDir: string;\n private fileSizeLimit: number;\n private allowedFileTypes: RegExp;\n private storage: StorageEngine;\n private maxCount: number;\n\n /**\n * Constructor to initialize the file uploader service.\n * @param {string} uploadDir - The directory where files will be uploaded.\n * @param {number} fileSizeLimit - The maximum allowed file size.\n * @param {RegExp} allowedFileTypes - The regular expression for allowed file types.\n */\n constructor(\n uploadDir: string,\n fileSizeLimit: number = 1024 * 1024 * 5,\n allowedFileTypes: RegExp = /.*/,\n maxCount: number = 30\n ) {\n uploadDir = uploadDir.startsWith(\"/\") ? uploadDir.substring(1) : uploadDir;\n uploadDir = uploadDir.endsWith(\"/\") ? uploadDir.slice(0, -1) : uploadDir;\n\n this.uploadDir = path.join(\".\", `${uploadDir}/`);\n this.fileSizeLimit = fileSizeLimit;\n this.allowedFileTypes = allowedFileTypes;\n this.maxCount = maxCount;\n\n if (!fs.existsSync(this.uploadDir)) {\n fs.mkdirSync(this.uploadDir, { recursive: true });\n }\n\n this.storage = multer.diskStorage({\n destination: (req, file, cb) => {\n cb(null, this.uploadDir);\n },\n filename: (req, file, cb) => {\n const uniqueSuffix = Date.now() + \"-\" + Math.round(Math.random() * 1e9);\n cb(null, `${uniqueSuffix}${path.extname(file.originalname)}`);\n },\n });\n }\n\n /**\n * Validates the file's type and MIME type.\n * @param {Request} req - The Express request object.\n * @param {Express.Multer.File} file - The uploaded file.\n * @param {Function} cb - The callback function to indicate if file is valid.\n */\n private fileFilter = (req: any, file: any, cb: any) => {\n const extName = this.allowedFileTypes.test(\n path.extname(file.originalname).toLowerCase()\n );\n const mimeType = this.allowedFileTypes.test(file.mimetype);\n\n if (mimeType && extName) {\n cb(null, true);\n } else {\n cb(new AppError(\"Invalid file type\", 400));\n }\n };\n\n /**\n * Returns the multer upload configuration.\n * @returns {multer.Instance} The multer instance configured for file uploads.\n */\n public getUploader() {\n return multer({\n storage: this.storage,\n fileFilter: this.fileFilter,\n limits: { fileSize: this.fileSizeLimit },\n });\n }\n\n /**\n * Middleware to handle single file upload.\n * @param {string} [oldFilePath] - The path to the file to delete before uploading.\n * @returns {Function} Middleware function for handling file upload.\n */\n public handleSingleUpload(oldFilePath?: string) {\n return (req: ArkosRequest, res: ArkosResponse, next: NextFunction) => {\n const upload = this.getUploader().single(this.getFieldName());\n upload(req, res, async (err) => {\n if (err instanceof multer.MulterError) {\n return next(err);\n } else if (err) {\n return next(err);\n }\n\n if (oldFilePath) {\n const filePath = path.join(oldFilePath);\n try {\n const stats = await promisify(fs.stat)(filePath);\n if (stats) await promisify(fs.unlink)(filePath);\n } catch (err) {\n console.error(err);\n }\n }\n\n next();\n });\n };\n }\n\n /**\n * Middleware to handle multiple file uploads.\n * @param {number} maxCount - The maximum number of files allowed for upload.\n * @returns {Function} Middleware function for handling multiple file uploads.\n */\n public handleMultipleUpload() {\n return (req: ArkosRequest, res: ArkosResponse, next: NextFunction) => {\n const upload = this.getUploader().array(\n this.getFieldName(),\n this.maxCount\n );\n upload(req, res, (err) => {\n if (err instanceof multer.MulterError) return next(err);\n else if (err) return next(err);\n next();\n });\n };\n }\n\n /**\n * Middleware to handle deletion of a single file from the filesystem.\n * @param {string} oldFilePath - The path to the file to be deleted.\n * @returns {Function} Middleware function for handling file deletion.\n */\n public handleDeleteSingleFile(oldFilePath: string) {\n return async (\n req: ArkosRequest,\n res: ArkosResponse,\n next: NextFunction\n ) => {\n const filePath = path.join(oldFilePath);\n try {\n const stats = await promisify(fs.stat)(filePath);\n if (stats) {\n await promisify(fs.unlink)(filePath);\n }\n } catch (err) {\n console.error(err);\n }\n\n next();\n };\n }\n\n /**\n * Deletes a file based on its URL by identifying the appropriate uploader service\n * @param {string} fileUrl - The URL of the file to delete\n * @returns {Promise<boolean>} - True if deletion successful, false otherwise\n */\n public async deleteFileByUrl(fileUrl: string): Promise<boolean> {\n try {\n // Get configuration values\n const { fileUpload } = getArkosConfig();\n const baseRoute = fileUpload?.baseRoute || \"/api/uploads\";\n\n // Parse the URL to get the path\n let urlPath: string;\n if (fileUrl.startsWith(\"http\")) {\n const url = new URL(fileUrl);\n urlPath = url.pathname;\n } else {\n urlPath = fileUrl;\n }\n\n // Extract the path after the base route\n const baseRouteIndex = urlPath.indexOf(baseRoute);\n if (baseRouteIndex === -1) {\n throw new AppError(\"Invalid file URL: base route not found\", 400);\n }\n\n const pathAfterBaseRoute = urlPath.substring(\n baseRouteIndex + baseRoute.length\n );\n const cleanPath = pathAfterBaseRoute.startsWith(\"/\")\n ? pathAfterBaseRoute.substring(1)\n : pathAfterBaseRoute;\n\n // Determine file type and file name\n const fileTypes = [\"images\", \"videos\", \"documents\", \"files\"];\n let fileType: string | null = null;\n let fileName: string | null = null;\n\n for (const type of fileTypes) {\n const typeIndex = cleanPath.indexOf(type + \"/\");\n if (typeIndex !== -1) {\n fileType = type;\n fileName = cleanPath.substring(typeIndex + type.length + 1);\n break;\n }\n }\n\n if (!fileType || !fileName) {\n throw new AppError(\n \"Unable to determine file type or file name from URL\",\n 400\n );\n }\n\n // Get the appropriate uploader service based on file type\n const {\n documentUploaderService,\n fileUploaderService,\n imageUploaderService,\n videoUploaderService,\n } = getFileUploaderServices();\n\n let filePath: string;\n switch (fileType) {\n case \"images\":\n filePath = path.join(imageUploaderService.uploadDir, fileName);\n break;\n case \"videos\":\n filePath = path.join(videoUploaderService.uploadDir, fileName);\n break;\n case \"documents\":\n filePath = path.join(documentUploaderService.uploadDir, fileName);\n break;\n case \"files\":\n filePath = path.join(fileUploaderService.uploadDir, fileName);\n break;\n default:\n throw new AppError(`Unsupported file type: ${fileType}`, 400);\n }\n\n // Delete the file\n\n await promisify(fs.stat)(filePath);\n await promisify(fs.unlink)(filePath);\n\n return true;\n } catch (error: any) {\n if (error instanceof AppError) {\n throw error;\n }\n\n if (error.code === \"ENOENT\") {\n throw new AppError(\"File not found\", 404);\n }\n\n throw new AppError(`Failed to delete file: ${error.message}`, 500);\n }\n }\n\n private getFieldName() {\n let fieldName = \"files\";\n if (this.uploadDir.endsWith(\"images\") || this.uploadDir.endsWith(\"images/\"))\n fieldName === \"images\";\n if (this.uploadDir.endsWith(\"videos\") || this.uploadDir.endsWith(\"videos/\"))\n fieldName === \"videos\";\n if (\n this.uploadDir.endsWith(\"documents\") ||\n this.uploadDir.endsWith(\"documents/\")\n )\n fieldName === \"documents\";\n if (this.uploadDir.endsWith(\"files\") || this.uploadDir.endsWith(\"files/\"))\n fieldName === \"files\";\n return fieldName;\n }\n\n /**\n * Handles the upload process and returns the full URLs of uploaded files\n * @param {ArkosRequest} req - Arkos request object containing the files\n * @param {ArkosResponse} res - Arkos response object\n * @param {object} options - Optional parameters for image processing\n * @returns {Promise<string|string[]>} URL or array of URLs to the uploaded files\n */\n public async upload(\n req: ArkosRequest,\n res: ArkosResponse,\n options: {\n format?: string;\n width?: number;\n height?: number;\n resizeTo?: number;\n } = {}\n ): Promise<string | string[] | null> {\n const { fileUpload } = getArkosConfig();\n const baseRoute = fileUpload?.baseRoute || \"/api/uploads\";\n\n return new Promise((resolve, reject) => {\n // Determine if it's a single or multiple file upload\n const isMultiple = Array.isArray(req.query.multiple)\n ? req.query.multiple[0] == \"true\"\n : req.query.multiple == \"true\";\n\n // Use appropriate upload handler\n const uploadHandler = isMultiple\n ? this.getUploader().array(this.getFieldName(), this.maxCount)\n : this.getUploader().single(this.getFieldName());\n\n uploadHandler(req, res, async (err) => {\n if (err) return reject(err);\n\n try {\n // Determine the base URL for file access\n const protocol = req.get(\"host\")?.includes(\"localhost\")\n ? \"http\"\n : \"https\";\n const baseURL = `${protocol}://${req.get(\"host\")}`;\n\n // Get file type from uploadDir path\n const dirParts = this.uploadDir.split(\"/\");\n const fileType =\n (this.uploadDir.endsWith(\"/\")\n ? dirParts[dirParts.length - 2]\n : dirParts[dirParts.length - 1]) || \"files\";\n\n // Process all uploaded files\n let data;\n if (req.files && Array.isArray(req.files) && req.files.length > 0) {\n // Process multiple files\n const isImageUploader = this.uploadDir.includes(\"/images\");\n if (isImageUploader) {\n data = await Promise.all(\n req.files.map((file) =>\n processImage(file.path, baseURL, baseRoute, options, fileType)\n )\n );\n } else {\n data = await Promise.all(\n req.files.map((file) =>\n processFile(file.path, baseURL, baseRoute, fileType)\n )\n );\n }\n // Filter out any null values from failed processing\n data = data.filter((url) => url !== null);\n } else if (req.file) {\n // Process a single file\n const isImageUploader = this.uploadDir.includes(\"/images\");\n // console.log(req.file.path, baseURL, baseRoute, options, fileType);\n if (isImageUploader) {\n data = await processImage(\n req.file.path,\n baseURL,\n baseRoute,\n options,\n fileType\n );\n } else {\n data = await processFile(\n req.file.path,\n baseURL,\n baseRoute,\n fileType\n );\n }\n } else {\n return reject(new AppError(\"No file uploaded\", 400));\n }\n\n resolve(data);\n } catch (error) {\n reject(error);\n }\n });\n });\n }\n}\n\n/**\n * Creates and returns all file uploader services based on config\n * @returns Object containing all specialized file uploader services\n */\nexport const getFileUploaderServices = () => {\n const { fileUpload } = getArkosConfig();\n const baseUploadDir = fileUpload?.baseUploadDir || \"/uploads\";\n\n // Default regex patterns for each file type\n const defaultRegexPatterns = {\n image:\n /jpeg|jpg|png|gif|webp|svg|bmp|tiff|heif|heic|ico|jfif|raw|cr2|nef|orf|sr2|arw|dng|pef|raf|rw2|psd|ai|eps|xcf|jxr|wdp|hdp|jp2|j2k|jpf|jpx|jpm|mj2|avif/,\n video:\n /mp4|avi|mov|mkv|flv|wmv|webm|mpg|mpeg|3gp|m4v|ts|rm|rmvb|vob|ogv|dv|qt|asf|m2ts|mts|divx|f4v|swf|mxf|roq|nsv|mvb|svi|mpe|m2v|mp2|mpv|h264|h265|hevc/,\n document:\n /pdf|doc|docx|xls|xlsx|ppt|pptx|odt|ods|odg|odp|txt|rtf|csv|epub|md|tex|pages|numbers|key|xml|json|yaml|yml|ini|cfg|conf|log|html|htm|xhtml|djvu|mobi|azw|azw3|fb2|lit|ps|wpd|wps|dot|dotx|xlt|xltx|pot|potx|oft|one|onetoc2|opf|oxps|hwp/,\n other: /.*/,\n };\n\n // Default upload restrictions\n const defaultRestrictions = {\n images: {\n maxCount: 30,\n maxSize: 1024 * 1024 * 15, // 15 MB\n supportedFilesRegex: defaultRegexPatterns.image,\n },\n videos: {\n maxCount: 10,\n maxSize: 1024 * 1024 * 5096, // 5 GB\n supportedFilesRegex: defaultRegexPatterns.video,\n },\n documents: {\n maxCount: 30,\n maxSize: 1024 * 1024 * 50, // 50 MB\n supportedFilesRegex: defaultRegexPatterns.document,\n },\n others: {\n maxCount: 10,\n maxSize: 1024 * 1024 * 5096, // 5 GB\n supportedFilesRegex: defaultRegexPatterns.other,\n },\n };\n\n // Merge with user configuration (if any)\n const restrictions = fileUpload?.restrictions\n ? deepmerge(defaultRestrictions, fileUpload.restrictions)\n : defaultRestrictions;\n\n /**\n * Specialized file uploader service for handling image uploads.\n */\n const imageUploaderService = new FileUploaderService(\n `${baseUploadDir}/images`,\n restrictions.images.maxSize,\n restrictions.images.supportedFilesRegex,\n restrictions.images.maxCount\n );\n\n /**\n * Specialized file uploader service for handling video uploads.\n */\n const videoUploaderService = new FileUploaderService(\n `${baseUploadDir}/videos`,\n restrictions.videos.maxSize,\n restrictions.videos.supportedFilesRegex,\n restrictions.videos.maxCount\n );\n\n /**\n * Specialized file uploader service for handling document uploads.\n */\n const documentUploaderService = new FileUploaderService(\n `${baseUploadDir}/documents`,\n restrictions.documents.maxSize,\n restrictions.documents.supportedFilesRegex,\n restrictions.documents.maxCount\n );\n\n /**\n * Generic file uploader service for handling all file uploads.\n */\n const fileUploaderService = new FileUploaderService(\n `${baseUploadDir}/files`,\n restrictions.others.maxSize,\n restrictions.others.supportedFilesRegex,\n restrictions.others.maxCount\n );\n\n return {\n imageUploaderService,\n videoUploaderService,\n documentUploaderService,\n fileUploaderService,\n };\n};\n"]}
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const path_1 = __importDefault(require("path"));
17
+ const sharp_1 = __importDefault(require("sharp"));
18
+ const util_1 = require("util");
19
+ const file_uploader_helpers_1 = require("../file-uploader.helpers");
20
+ const server_1 = require("../../../../../server");
21
+ jest.mock("fs");
22
+ jest.mock("path");
23
+ jest.mock("sharp");
24
+ jest.mock("util");
25
+ jest.mock("../../../../../server");
26
+ describe("File Uploader Helpers", () => {
27
+ let mockBaseURL = "https://example.com";
28
+ let mockBaseRoute = "/files";
29
+ let mockFileType = "images";
30
+ beforeEach(() => {
31
+ jest.clearAllMocks();
32
+ server_1.getArkosConfig.mockReturnValue({
33
+ fileUpload: {
34
+ baseUploadDir: "/uploads",
35
+ },
36
+ });
37
+ path_1.default.join.mockImplementation((...args) => args.join("/"));
38
+ path_1.default.basename.mockImplementation((filePath, ext) => {
39
+ const base = filePath.split("/").pop();
40
+ return ext ? base.replace(ext, "") : base;
41
+ });
42
+ path_1.default.dirname.mockImplementation((filePath) => {
43
+ return filePath.substring(0, filePath.lastIndexOf("/"));
44
+ });
45
+ path_1.default.extname.mockImplementation((filePath) => {
46
+ const parts = filePath.split(".");
47
+ return parts.length > 1 ? `.${parts.pop()}` : "";
48
+ });
49
+ jest.spyOn(process, "cwd").mockReturnValue("/app");
50
+ util_1.promisify.mockImplementation((fn) => fn);
51
+ });
52
+ describe("processFile", () => {
53
+ it("should process a file with internal upload directory", () => __awaiter(void 0, void 0, void 0, function* () {
54
+ const mockFilePath = "test.pdf";
55
+ mockFileType = "documents";
56
+ const result = yield (0, file_uploader_helpers_1.processFile)(mockFilePath, mockBaseURL, mockBaseRoute, mockFileType);
57
+ expect(result).toBe("https://example.com/files/documents/test.pdf");
58
+ }));
59
+ it("should process a file with external upload directory", () => __awaiter(void 0, void 0, void 0, function* () {
60
+ server_1.getArkosConfig.mockReturnValue({
61
+ fileUpload: {
62
+ baseUploadDir: "../uploads",
63
+ },
64
+ });
65
+ const mockFilePath = "../uploads/documents/test.pdf";
66
+ const result = yield (0, file_uploader_helpers_1.processFile)(mockFilePath, mockBaseURL, mockBaseRoute, mockFileType);
67
+ expect(path_1.default.basename).toHaveBeenCalledWith(mockFilePath);
68
+ expect(path_1.default.join).toHaveBeenCalledWith(mockFileType, "test.pdf");
69
+ expect(result).toBe("https://example.com/files/documents/test.pdf");
70
+ }));
71
+ });
72
+ describe("processImage", () => {
73
+ beforeEach(() => {
74
+ const mockTransformer = {
75
+ metadata: jest.fn().mockResolvedValue({ width: 1000, height: 800 }),
76
+ resize: jest.fn().mockReturnThis(),
77
+ toFormat: jest.fn().mockReturnThis(),
78
+ toFile: jest.fn().mockResolvedValue(undefined),
79
+ };
80
+ sharp_1.default.mockReturnValue(mockTransformer);
81
+ fs_1.default.rename = jest
82
+ .fn()
83
+ .mockImplementation((tempPath, origPath) => {
84
+ return true;
85
+ });
86
+ fs_1.default.stat = jest
87
+ .fn()
88
+ .mockReturnValue({ isFile: () => true });
89
+ fs_1.default.unlink = jest
90
+ .fn()
91
+ .mockImplementation((path, callback) => {
92
+ callback(null);
93
+ });
94
+ });
95
+ it("should process a non-image file without transformations", () => __awaiter(void 0, void 0, void 0, function* () {
96
+ const mockFilePath = "test.pdf";
97
+ const options = {};
98
+ mockFileType = "documents";
99
+ const result = yield (0, file_uploader_helpers_1.processImage)(mockFilePath, mockBaseURL, mockBaseRoute, options, mockFileType);
100
+ expect(sharp_1.default).not.toHaveBeenCalled();
101
+ expect(result).toBe("https://example.com/files/documents/test.pdf");
102
+ }));
103
+ it("should process an image file with resizeTo option", () => __awaiter(void 0, void 0, void 0, function* () {
104
+ const mockFilePath = "test.jpg";
105
+ const options = { resizeTo: 500 };
106
+ mockFileType = "images";
107
+ const result = yield (0, file_uploader_helpers_1.processImage)(mockFilePath, mockBaseURL, mockBaseRoute, options, mockFileType);
108
+ expect(sharp_1.default).toHaveBeenCalledWith(mockFilePath);
109
+ expect((0, sharp_1.default)().resize).toHaveBeenCalledWith(625, 500);
110
+ expect((0, sharp_1.default)().toFile).toHaveBeenCalled();
111
+ expect(fs_1.default.rename).toHaveBeenCalled();
112
+ expect(result).toBe("https://example.com/files/images/test.jpg");
113
+ }));
114
+ it("should process an image file with width and height options", () => __awaiter(void 0, void 0, void 0, function* () {
115
+ const mockFilePath = "test.png";
116
+ const options = { width: 300, height: 200 };
117
+ mockFileType = "images";
118
+ const result = yield (0, file_uploader_helpers_1.processImage)(mockFilePath, mockBaseURL, mockBaseRoute, options, mockFileType);
119
+ expect(sharp_1.default).toHaveBeenCalledWith(mockFilePath);
120
+ expect((0, sharp_1.default)().resize).toHaveBeenCalledWith(300, 200, { fit: "inside" });
121
+ expect(result).toBe("https://example.com/files/images/test.png");
122
+ }));
123
+ it("should convert image format to webp if requested", () => __awaiter(void 0, void 0, void 0, function* () {
124
+ const mockFilePath = "test.jpg";
125
+ const options = { format: "webp" };
126
+ mockFileType = "images";
127
+ const result = yield (0, file_uploader_helpers_1.processImage)(mockFilePath, mockBaseURL, mockBaseRoute, options, mockFileType);
128
+ expect(sharp_1.default).toHaveBeenCalledWith(mockFilePath);
129
+ expect((0, sharp_1.default)().toFormat).toHaveBeenCalledWith("webp");
130
+ expect(result).toBe("https://example.com/files/images/test.jpg");
131
+ }));
132
+ it("should convert image format to jpeg if requested", () => __awaiter(void 0, void 0, void 0, function* () {
133
+ const mockFilePath = "test.png";
134
+ const options = { format: "jpeg" };
135
+ mockFileType = "images";
136
+ const result = yield (0, file_uploader_helpers_1.processImage)(mockFilePath, mockBaseURL, mockBaseRoute, options, mockFileType);
137
+ expect(sharp_1.default).toHaveBeenCalledWith(mockFilePath);
138
+ expect((0, sharp_1.default)().toFormat).toHaveBeenCalledWith("jpeg");
139
+ expect(result).toBe("https://example.com/files/images/test.png");
140
+ }));
141
+ it("should handle errors and clean up temp files", () => __awaiter(void 0, void 0, void 0, function* () {
142
+ const mockFilePath = "test.jpg";
143
+ const options = {};
144
+ const error = new Error("Image processing failed");
145
+ (0, sharp_1.default)().toFile.mockRejectedValue(error);
146
+ yield expect((0, file_uploader_helpers_1.processImage)(mockFilePath, mockBaseURL, mockBaseRoute, options, mockFileType)).rejects.toThrow(error);
147
+ expect(fs_1.default.stat).toHaveBeenCalled();
148
+ expect(fs_1.default.unlink).toHaveBeenCalled();
149
+ }));
150
+ it("should handle non-existent temp files gracefully", () => __awaiter(void 0, void 0, void 0, function* () {
151
+ const mockFilePath = "/app/uploads/images/test.jpg";
152
+ const options = {};
153
+ const error = new Error("Image processing failed");
154
+ (0, sharp_1.default)().toFile.mockRejectedValue(error);
155
+ fs_1.default.stat.mockImplementation((path, callback) => {
156
+ callback(new Error("File not found"), null);
157
+ });
158
+ yield expect((0, file_uploader_helpers_1.processImage)(mockFilePath, mockBaseURL, mockBaseRoute, options, mockFileType)).rejects.toThrow(error);
159
+ expect(fs_1.default.stat).toHaveBeenCalled();
160
+ expect(fs_1.default.unlink).not.toHaveBeenCalled();
161
+ }));
162
+ });
163
+ });
164
+ //# sourceMappingURL=file-uploader.helpers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-uploader.helpers.test.js","sourceRoot":"","sources":["../../../../../../../src/modules/file-uploader/utils/helpers/__tests__/file-uploader.helpers.test.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport sharp from \"sharp\";\nimport { promisify } from \"util\";\nimport { processFile, processImage } from \"../file-uploader.helpers\";\nimport { getArkosConfig } from \"../../../../../server\";\n\n// Mock dependencies\njest.mock(\"fs\");\njest.mock(\"path\");\njest.mock(\"sharp\");\njest.mock(\"util\");\njest.mock(\"../../../../../server\");\n\ndescribe(\"File Uploader Helpers\", () => {\n let mockBaseURL = \"https://example.com\";\n let mockBaseRoute = \"/files\";\n let mockFileType = \"images\";\n\n beforeEach(() => {\n jest.clearAllMocks();\n\n // Mock getArkosConfig\n (getArkosConfig as jest.Mock).mockReturnValue({\n fileUpload: {\n baseUploadDir: \"/uploads\",\n },\n });\n\n // Mock path functions\n (path.join as jest.Mock).mockImplementation((...args) => args.join(\"/\"));\n (path.basename as jest.Mock).mockImplementation((filePath, ext) => {\n const base = filePath.split(\"/\").pop();\n return ext ? base.replace(ext, \"\") : base;\n });\n (path.dirname as jest.Mock).mockImplementation((filePath) => {\n return filePath.substring(0, filePath.lastIndexOf(\"/\"));\n });\n (path.extname as jest.Mock).mockImplementation((filePath) => {\n const parts = filePath.split(\".\");\n return parts.length > 1 ? `.${parts.pop()}` : \"\";\n });\n\n // Mock process.cwd\n jest.spyOn(process, \"cwd\").mockReturnValue(\"/app\");\n\n // Mock promisify\n (promisify as any as jest.Mock).mockImplementation((fn) => fn);\n });\n\n describe(\"processFile\", () => {\n it(\"should process a file with internal upload directory\", async () => {\n const mockFilePath = \"test.pdf\";\n // const mockFilePath = \"/app/uploads/documents/test.pdf\";\n mockFileType = \"documents\";\n\n const result = await processFile(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n mockFileType\n );\n\n expect(result).toBe(\"https://example.com/files/documents/test.pdf\");\n });\n\n it(\"should process a file with external upload directory\", async () => {\n (getArkosConfig as jest.Mock).mockReturnValue({\n fileUpload: {\n baseUploadDir: \"../uploads\",\n },\n });\n\n const mockFilePath = \"../uploads/documents/test.pdf\";\n\n const result = await processFile(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n mockFileType\n );\n\n expect(path.basename).toHaveBeenCalledWith(mockFilePath);\n expect(path.join).toHaveBeenCalledWith(mockFileType, \"test.pdf\");\n expect(result).toBe(\"https://example.com/files/documents/test.pdf\");\n });\n });\n\n describe(\"processImage\", () => {\n beforeEach(() => {\n // Mock sharp\n const mockTransformer = {\n metadata: jest.fn().mockResolvedValue({ width: 1000, height: 800 }),\n resize: jest.fn().mockReturnThis(),\n toFormat: jest.fn().mockReturnThis(),\n toFile: jest.fn().mockResolvedValue(undefined),\n };\n (sharp as any as jest.Mock).mockReturnValue(mockTransformer);\n\n // Mock fs functions\n (fs.rename as any as jest.Mock) = jest\n .fn()\n .mockImplementation((tempPath, origPath) => {\n return true;\n });\n (fs.stat as any as jest.Mock) = jest\n .fn()\n .mockReturnValue({ isFile: () => true });\n (fs.unlink as any as jest.Mock) = jest\n .fn()\n .mockImplementation((path, callback) => {\n callback(null);\n });\n });\n\n it(\"should process a non-image file without transformations\", async () => {\n const mockFilePath = \"test.pdf\";\n // const mockFilePath = \"/app/uploads/documents/test.pdf\";\n const options = {};\n\n mockFileType = \"documents\";\n\n const result = await processImage(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n options,\n mockFileType\n );\n\n expect(sharp).not.toHaveBeenCalled();\n expect(result).toBe(\"https://example.com/files/documents/test.pdf\");\n });\n\n it(\"should process an image file with resizeTo option\", async () => {\n const mockFilePath = \"test.jpg\";\n // const mockFilePath = \"/app/uploads/images/test.jpg\";\n const options = { resizeTo: 500 };\n\n mockFileType = \"images\";\n\n const result = await processImage(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n options,\n mockFileType\n );\n\n expect(sharp).toHaveBeenCalledWith(mockFilePath);\n expect(sharp().resize).toHaveBeenCalledWith(625, 500);\n expect(sharp().toFile).toHaveBeenCalled();\n expect(fs.rename).toHaveBeenCalled();\n expect(result).toBe(\"https://example.com/files/images/test.jpg\");\n });\n\n it(\"should process an image file with width and height options\", async () => {\n // const mockFilePath = \"/app/uploads/images/test.png\";\n const mockFilePath = \"test.png\";\n const options = { width: 300, height: 200 };\n\n mockFileType = \"images\";\n\n const result = await processImage(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n options,\n mockFileType\n );\n\n expect(sharp).toHaveBeenCalledWith(mockFilePath);\n expect(sharp().resize).toHaveBeenCalledWith(300, 200, { fit: \"inside\" });\n expect(result).toBe(\"https://example.com/files/images/test.png\");\n });\n\n it(\"should convert image format to webp if requested\", async () => {\n const mockFilePath = \"test.jpg\";\n const options = { format: \"webp\" };\n\n mockFileType = \"images\";\n\n const result = await processImage(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n options,\n mockFileType\n );\n\n expect(sharp).toHaveBeenCalledWith(mockFilePath);\n expect(sharp().toFormat).toHaveBeenCalledWith(\"webp\");\n expect(result).toBe(\"https://example.com/files/images/test.jpg\");\n });\n\n it(\"should convert image format to jpeg if requested\", async () => {\n // const mockFilePath = \"/app/uploads/images/test.png\";\n const mockFilePath = \"test.png\";\n const options = { format: \"jpeg\" };\n\n mockFileType = \"images\";\n\n const result = await processImage(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n options,\n mockFileType\n );\n\n expect(sharp).toHaveBeenCalledWith(mockFilePath);\n expect(sharp().toFormat).toHaveBeenCalledWith(\"jpeg\");\n expect(result).toBe(\"https://example.com/files/images/test.png\");\n });\n\n it(\"should handle errors and clean up temp files\", async () => {\n const mockFilePath = \"test.jpg\";\n // const mockFilePath = \"/app/uploads/images/test.jpg\";\n const options = {};\n\n const error = new Error(\"Image processing failed\");\n (sharp().toFile as jest.Mock).mockRejectedValue(error);\n\n await expect(\n processImage(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n options,\n mockFileType\n )\n ).rejects.toThrow(error);\n\n expect(fs.stat).toHaveBeenCalled();\n expect(fs.unlink).toHaveBeenCalled();\n });\n\n it(\"should handle non-existent temp files gracefully\", async () => {\n const mockFilePath = \"/app/uploads/images/test.jpg\";\n const options = {};\n\n const error = new Error(\"Image processing failed\");\n (sharp().toFile as jest.Mock).mockRejectedValue(error);\n (fs.stat as any as jest.Mock).mockImplementation((path, callback) => {\n callback(new Error(\"File not found\"), null);\n });\n\n await expect(\n processImage(\n mockFilePath,\n mockBaseURL,\n mockBaseRoute,\n options,\n mockFileType\n )\n ).rejects.toThrow(error);\n\n expect(fs.stat).toHaveBeenCalled();\n expect(fs.unlink).not.toHaveBeenCalled();\n });\n });\n});\n"]}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.processImage = exports.processFile = void 0;
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const sharp_1 = __importDefault(require("sharp"));
19
+ const util_1 = require("util");
20
+ const server_1 = require("../../../../server");
21
+ const mimetype_1 = __importDefault(require("mimetype"));
22
+ const generateRelativePath = (filePath, fileType) => {
23
+ const { fileUpload } = (0, server_1.getArkosConfig)();
24
+ const baseUploadDir = (fileUpload === null || fileUpload === void 0 ? void 0 : fileUpload.baseUploadDir) || "/uploads";
25
+ if (baseUploadDir.startsWith("..")) {
26
+ return path_1.default.join(fileType, path_1.default.basename(filePath));
27
+ }
28
+ else {
29
+ return (`${fileType}/` + filePath.replace(`${process.cwd()}${baseUploadDir}/`, ""));
30
+ }
31
+ };
32
+ const processFile = (filePath, baseURL, baseRoute, fileType) => __awaiter(void 0, void 0, void 0, function* () {
33
+ const relativePath = generateRelativePath(filePath, fileType);
34
+ return `${baseURL}${baseRoute}/${relativePath}`;
35
+ });
36
+ exports.processFile = processFile;
37
+ const processImage = (filePath, baseURL, baseRoute, options, fileType) => __awaiter(void 0, void 0, void 0, function* () {
38
+ var _a;
39
+ const ext = path_1.default.extname(filePath).toLowerCase();
40
+ const originalFormat = ext.replace(".", "");
41
+ const outputFormat = options.format || originalFormat;
42
+ if (!((_a = mimetype_1.default.lookup(ext)) === null || _a === void 0 ? void 0 : _a.includes("image"))) {
43
+ const relativePath = generateRelativePath(filePath, fileType);
44
+ return `${baseURL}${baseRoute}/${relativePath}`;
45
+ }
46
+ const tempName = `${path_1.default.basename(filePath, ext)}_${Date.now()}${ext}`;
47
+ const tempPath = path_1.default.join(path_1.default.dirname(filePath), tempName);
48
+ try {
49
+ let transformer = (0, sharp_1.default)(filePath);
50
+ const metadata = yield transformer.metadata();
51
+ if (options.resizeTo && metadata.width && metadata.height) {
52
+ const targetSize = options.resizeTo;
53
+ const scaleFactor = targetSize / Math.min(metadata.width, metadata.height);
54
+ const newWidth = Math.round(metadata.width * scaleFactor);
55
+ const newHeight = Math.round(metadata.height * scaleFactor);
56
+ transformer = transformer.resize(newWidth, newHeight);
57
+ }
58
+ else if (options.width || options.height) {
59
+ transformer = transformer.resize(options.width || null, options.height || null, {
60
+ fit: "inside",
61
+ });
62
+ }
63
+ if (outputFormat === "webp") {
64
+ transformer = transformer.toFormat("webp");
65
+ }
66
+ else if (outputFormat === "jpeg" || outputFormat === "jpg") {
67
+ transformer = transformer.toFormat("jpeg");
68
+ }
69
+ yield transformer.toFile(tempPath);
70
+ yield (0, util_1.promisify)(fs_1.default.rename)(tempPath, filePath);
71
+ const relativePath = generateRelativePath(filePath, fileType);
72
+ return `${baseURL}${baseRoute}/${relativePath}`;
73
+ }
74
+ catch (error) {
75
+ try {
76
+ yield (0, util_1.promisify)(fs_1.default.stat)(tempPath);
77
+ yield (0, util_1.promisify)(fs_1.default.unlink)(tempPath);
78
+ }
79
+ catch (err) {
80
+ }
81
+ throw error;
82
+ }
83
+ });
84
+ exports.processImage = processImage;
85
+ //# sourceMappingURL=file-uploader.helpers.js.map