arkos 1.1.12-test → 1.1.13-test
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/dist/cjs/app.js +1 -1
- package/dist/cjs/app.js.map +1 -1
- package/dist/cjs/modules/auth/auth.controller.js +53 -64
- package/dist/cjs/modules/auth/auth.controller.js.map +1 -1
- package/dist/cjs/modules/auth/auth.router.js +46 -58
- package/dist/cjs/modules/auth/auth.router.js.map +1 -1
- package/dist/cjs/modules/auth/auth.service.js +75 -97
- package/dist/cjs/modules/auth/auth.service.js.map +1 -1
- package/dist/cjs/modules/auth/utils/helpers/auth.controller.helpers.js +6 -7
- package/dist/cjs/modules/auth/utils/helpers/auth.controller.helpers.js.map +1 -1
- package/dist/cjs/modules/base/base.controller.js +30 -46
- package/dist/cjs/modules/base/base.controller.js.map +1 -1
- package/dist/cjs/modules/base/base.middlewares.js +17 -21
- package/dist/cjs/modules/base/base.middlewares.js.map +1 -1
- package/dist/cjs/modules/base/base.router.js +6 -17
- package/dist/cjs/modules/base/base.router.js.map +1 -1
- package/dist/cjs/modules/base/base.service.js +128 -116
- package/dist/cjs/modules/base/base.service.js.map +1 -1
- package/dist/cjs/modules/base/utils/helpers/base.controller.helpers.js +3 -5
- package/dist/cjs/modules/base/utils/helpers/base.controller.helpers.js.map +1 -1
- package/dist/cjs/modules/base/utils/helpers/base.router.helpers.js +36 -47
- package/dist/cjs/modules/base/utils/helpers/base.router.helpers.js.map +1 -1
- package/dist/cjs/modules/base/utils/helpers/base.service.helpers.js +30 -40
- package/dist/cjs/modules/base/utils/helpers/base.service.helpers.js.map +1 -1
- package/dist/cjs/modules/email/email.service.js +28 -39
- package/dist/cjs/modules/email/email.service.js.map +1 -1
- package/dist/cjs/modules/error-handler/error-handler.controller.js +6 -3
- package/dist/cjs/modules/error-handler/error-handler.controller.js.map +1 -1
- package/dist/cjs/modules/error-handler/utils/catch-async.js +3 -12
- package/dist/cjs/modules/error-handler/utils/catch-async.js.map +1 -1
- package/dist/cjs/modules/error-handler/utils/error-handler.helpers.js +17 -31
- package/dist/cjs/modules/error-handler/utils/error-handler.helpers.js.map +1 -1
- package/dist/cjs/modules/file-uploader/file-uploader.controller.js +18 -27
- package/dist/cjs/modules/file-uploader/file-uploader.controller.js.map +1 -1
- package/dist/cjs/modules/file-uploader/file-uploader.router.js +23 -34
- package/dist/cjs/modules/file-uploader/file-uploader.router.js.map +1 -1
- package/dist/cjs/modules/file-uploader/file-uploader.service.js +117 -131
- package/dist/cjs/modules/file-uploader/file-uploader.service.js.map +1 -1
- package/dist/cjs/modules/file-uploader/utils/helpers/file-uploader.helpers.js +15 -26
- package/dist/cjs/modules/file-uploader/utils/helpers/file-uploader.helpers.js.map +1 -1
- package/dist/cjs/server.js +1 -1
- package/dist/cjs/server.js.map +1 -1
- package/dist/cjs/utils/cli/build.js +9 -2
- package/dist/cjs/utils/cli/build.js.map +1 -1
- package/dist/cjs/utils/cli/dev.js +43 -48
- package/dist/cjs/utils/cli/dev.js.map +1 -1
- package/dist/cjs/utils/cli/start.js +35 -38
- package/dist/cjs/utils/cli/start.js.map +1 -1
- package/dist/cjs/utils/features/api.features.js +26 -33
- package/dist/cjs/utils/features/api.features.js.map +1 -1
- package/dist/cjs/utils/helpers/api.features.helpers.js +4 -6
- package/dist/cjs/utils/helpers/api.features.helpers.js.map +1 -1
- package/dist/cjs/utils/helpers/change-case.helpers.js +28 -36
- package/dist/cjs/utils/helpers/change-case.helpers.js.map +1 -1
- package/dist/cjs/utils/helpers/deepmerge.helper.js +4 -8
- package/dist/cjs/utils/helpers/deepmerge.helper.js.map +1 -1
- package/dist/cjs/utils/helpers/global.helpers.js +2 -13
- package/dist/cjs/utils/helpers/global.helpers.js.map +1 -1
- package/dist/cjs/utils/helpers/models.helpers.js +65 -80
- package/dist/cjs/utils/helpers/models.helpers.js.map +1 -1
- package/dist/cjs/utils/helpers/prisma.helpers.js +23 -34
- package/dist/cjs/utils/helpers/prisma.helpers.js.map +1 -1
- package/dist/cjs/utils/validate-dto.js +6 -17
- package/dist/cjs/utils/validate-dto.js.map +1 -1
- package/dist/cjs/utils/validate-schema.js +6 -17
- package/dist/cjs/utils/validate-schema.js.map +1 -1
- package/dist/es2020/app.js +1 -1
- package/dist/es2020/app.js.map +1 -1
- package/dist/es2020/modules/auth/auth.controller.js +53 -64
- package/dist/es2020/modules/auth/auth.controller.js.map +1 -1
- package/dist/es2020/modules/auth/auth.router.js +46 -58
- package/dist/es2020/modules/auth/auth.router.js.map +1 -1
- package/dist/es2020/modules/auth/auth.service.js +75 -97
- package/dist/es2020/modules/auth/auth.service.js.map +1 -1
- package/dist/es2020/modules/auth/utils/helpers/auth.controller.helpers.js +6 -7
- package/dist/es2020/modules/auth/utils/helpers/auth.controller.helpers.js.map +1 -1
- package/dist/es2020/modules/base/base.controller.js +30 -46
- package/dist/es2020/modules/base/base.controller.js.map +1 -1
- package/dist/es2020/modules/base/base.middlewares.js +17 -21
- package/dist/es2020/modules/base/base.middlewares.js.map +1 -1
- package/dist/es2020/modules/base/base.router.js +6 -17
- package/dist/es2020/modules/base/base.router.js.map +1 -1
- package/dist/es2020/modules/base/base.service.js +128 -116
- package/dist/es2020/modules/base/base.service.js.map +1 -1
- package/dist/es2020/modules/base/utils/helpers/base.controller.helpers.js +3 -5
- package/dist/es2020/modules/base/utils/helpers/base.controller.helpers.js.map +1 -1
- package/dist/es2020/modules/base/utils/helpers/base.router.helpers.js +36 -47
- package/dist/es2020/modules/base/utils/helpers/base.router.helpers.js.map +1 -1
- package/dist/es2020/modules/base/utils/helpers/base.service.helpers.js +30 -40
- package/dist/es2020/modules/base/utils/helpers/base.service.helpers.js.map +1 -1
- package/dist/es2020/modules/email/email.service.js +28 -39
- package/dist/es2020/modules/email/email.service.js.map +1 -1
- package/dist/es2020/modules/error-handler/error-handler.controller.js +6 -3
- package/dist/es2020/modules/error-handler/error-handler.controller.js.map +1 -1
- package/dist/es2020/modules/error-handler/utils/catch-async.js +3 -12
- package/dist/es2020/modules/error-handler/utils/catch-async.js.map +1 -1
- package/dist/es2020/modules/error-handler/utils/error-handler.helpers.js +17 -31
- package/dist/es2020/modules/error-handler/utils/error-handler.helpers.js.map +1 -1
- package/dist/es2020/modules/file-uploader/file-uploader.controller.js +18 -27
- package/dist/es2020/modules/file-uploader/file-uploader.controller.js.map +1 -1
- package/dist/es2020/modules/file-uploader/file-uploader.router.js +23 -34
- package/dist/es2020/modules/file-uploader/file-uploader.router.js.map +1 -1
- package/dist/es2020/modules/file-uploader/file-uploader.service.js +117 -131
- package/dist/es2020/modules/file-uploader/file-uploader.service.js.map +1 -1
- package/dist/es2020/modules/file-uploader/utils/helpers/file-uploader.helpers.js +15 -26
- package/dist/es2020/modules/file-uploader/utils/helpers/file-uploader.helpers.js.map +1 -1
- package/dist/es2020/server.js +1 -1
- package/dist/es2020/server.js.map +1 -1
- package/dist/es2020/utils/cli/build.js +9 -2
- package/dist/es2020/utils/cli/build.js.map +1 -1
- package/dist/es2020/utils/cli/dev.js +43 -48
- package/dist/es2020/utils/cli/dev.js.map +1 -1
- package/dist/es2020/utils/cli/start.js +35 -38
- package/dist/es2020/utils/cli/start.js.map +1 -1
- package/dist/es2020/utils/features/api.features.js +26 -33
- package/dist/es2020/utils/features/api.features.js.map +1 -1
- package/dist/es2020/utils/helpers/api.features.helpers.js +4 -6
- package/dist/es2020/utils/helpers/api.features.helpers.js.map +1 -1
- package/dist/es2020/utils/helpers/change-case.helpers.js +28 -36
- package/dist/es2020/utils/helpers/change-case.helpers.js.map +1 -1
- package/dist/es2020/utils/helpers/deepmerge.helper.js +4 -8
- package/dist/es2020/utils/helpers/deepmerge.helper.js.map +1 -1
- package/dist/es2020/utils/helpers/global.helpers.js +2 -13
- package/dist/es2020/utils/helpers/global.helpers.js.map +1 -1
- package/dist/es2020/utils/helpers/models.helpers.js +65 -80
- package/dist/es2020/utils/helpers/models.helpers.js.map +1 -1
- package/dist/es2020/utils/helpers/prisma.helpers.js +23 -34
- package/dist/es2020/utils/helpers/prisma.helpers.js.map +1 -1
- package/dist/es2020/utils/validate-dto.js +6 -17
- package/dist/es2020/utils/validate-dto.js.map +1 -1
- package/dist/es2020/utils/validate-schema.js +6 -17
- package/dist/es2020/utils/validate-schema.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import AppError from "../error-handler/utils/app-error";
|
|
11
2
|
import { getFileUploaderServices, } from "./file-uploader.service";
|
|
12
3
|
import path from "path";
|
|
@@ -15,19 +6,19 @@ import catchAsync from "../error-handler/utils/catch-async";
|
|
|
15
6
|
import { getArkosConfig } from "../../server";
|
|
16
7
|
import { processFile, processImage, } from "./utils/helpers/file-uploader.helpers";
|
|
17
8
|
import { accessAsync, mkdirAsync, statAsync, } from "../../utils/helpers/fs.helpers";
|
|
18
|
-
export const uploadFile = catchAsync((req, res, next) =>
|
|
9
|
+
export const uploadFile = catchAsync(async (req, res, next) => {
|
|
19
10
|
const { fileType } = req.params;
|
|
20
11
|
const { format, width, height, resizeTo } = req.query;
|
|
21
12
|
const options = { format, width, height, resizeTo };
|
|
22
13
|
const { documentUploaderService, fileUploaderService, imageUploaderService, videoUploaderService, } = getFileUploaderServices();
|
|
23
14
|
const { fileUpload } = getArkosConfig();
|
|
24
|
-
const baseUploadDir =
|
|
15
|
+
const baseUploadDir = fileUpload?.baseUploadDir || "/uploads";
|
|
25
16
|
const uploadPath = path.resolve(process.cwd(), baseUploadDir, fileType);
|
|
26
17
|
try {
|
|
27
|
-
|
|
18
|
+
await accessAsync(uploadPath);
|
|
28
19
|
}
|
|
29
20
|
catch (err) {
|
|
30
|
-
|
|
21
|
+
await mkdirAsync(uploadPath, { recursive: true });
|
|
31
22
|
}
|
|
32
23
|
let uploader;
|
|
33
24
|
switch (fileType) {
|
|
@@ -46,25 +37,25 @@ export const uploadFile = catchAsync((req, res, next) => __awaiter(void 0, void
|
|
|
46
37
|
default:
|
|
47
38
|
return next(new AppError("Invalid file type", 400));
|
|
48
39
|
}
|
|
49
|
-
uploader.handleMultipleUpload()(req, res, (err) =>
|
|
40
|
+
uploader.handleMultipleUpload()(req, res, async (err) => {
|
|
50
41
|
if (err)
|
|
51
42
|
return next(err);
|
|
52
43
|
let data;
|
|
53
44
|
if (req.files && Array.isArray(req.files)) {
|
|
54
45
|
if (fileType === "images") {
|
|
55
|
-
data =
|
|
46
|
+
data = await Promise.all(req.files.map((file) => processImage(req, file.path, options)));
|
|
56
47
|
}
|
|
57
48
|
else {
|
|
58
|
-
data =
|
|
49
|
+
data = await Promise.all(req.files.map((file) => processFile(req, file.path)));
|
|
59
50
|
}
|
|
60
51
|
data = data.filter((url) => url !== null);
|
|
61
52
|
}
|
|
62
53
|
else if (req.file) {
|
|
63
54
|
if (fileType === "images") {
|
|
64
|
-
data =
|
|
55
|
+
data = await processImage(req, req.file.path, options);
|
|
65
56
|
}
|
|
66
57
|
else {
|
|
67
|
-
data =
|
|
58
|
+
data = await processFile(req, req.file.path);
|
|
68
59
|
}
|
|
69
60
|
}
|
|
70
61
|
else {
|
|
@@ -77,9 +68,9 @@ export const uploadFile = catchAsync((req, res, next) => __awaiter(void 0, void
|
|
|
77
68
|
? `${data.length} files uploaded successfully`
|
|
78
69
|
: "File uploaded successfully",
|
|
79
70
|
});
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
export const deleteFile = catchAsync((req, res, next) =>
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
export const deleteFile = catchAsync(async (req, res, next) => {
|
|
83
74
|
const { fileType, fileName } = req.params;
|
|
84
75
|
const { documentUploaderService, fileUploaderService, imageUploaderService, videoUploaderService, } = getFileUploaderServices();
|
|
85
76
|
let uploader;
|
|
@@ -101,7 +92,7 @@ export const deleteFile = catchAsync((req, res, next) => __awaiter(void 0, void
|
|
|
101
92
|
}
|
|
102
93
|
try {
|
|
103
94
|
const fullUrl = `${req.protocol}://${req.get("host")}${req.originalUrl}`;
|
|
104
|
-
|
|
95
|
+
await uploader.deleteFileByUrl(fullUrl);
|
|
105
96
|
res.status(200).json({
|
|
106
97
|
success: true,
|
|
107
98
|
message: "File deleted successfully",
|
|
@@ -110,17 +101,17 @@ export const deleteFile = catchAsync((req, res, next) => __awaiter(void 0, void
|
|
|
110
101
|
catch (error) {
|
|
111
102
|
return next(new AppError("File not found", 404));
|
|
112
103
|
}
|
|
113
|
-
})
|
|
114
|
-
export const streamFile = catchAsync((req, res, next) =>
|
|
104
|
+
});
|
|
105
|
+
export const streamFile = catchAsync(async (req, res, next) => {
|
|
115
106
|
const { fileName, fileType } = req.params;
|
|
116
107
|
const filePath = path.join(".", "uploads", fileType, fileName);
|
|
117
108
|
try {
|
|
118
|
-
|
|
109
|
+
await accessAsync(filePath);
|
|
119
110
|
}
|
|
120
111
|
catch (err) {
|
|
121
112
|
throw new AppError("File not found", 404);
|
|
122
113
|
}
|
|
123
|
-
const fileStat =
|
|
114
|
+
const fileStat = await statAsync(filePath);
|
|
124
115
|
const fileSize = fileStat.size;
|
|
125
116
|
const range = req.headers.range;
|
|
126
117
|
if (range) {
|
|
@@ -148,5 +139,5 @@ export const streamFile = catchAsync((req, res, next) => __awaiter(void 0, void
|
|
|
148
139
|
});
|
|
149
140
|
fs.createReadStream(filePath).pipe(res);
|
|
150
141
|
}
|
|
151
|
-
})
|
|
142
|
+
});
|
|
152
143
|
//# sourceMappingURL=file-uploader.controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-uploader.controller.js","sourceRoot":"","sources":["../../../../src/modules/file-uploader/file-uploader.controller.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,QAAQ,MAAM,kCAAkC,CAAC;AACxD,OAAO,EAEL,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,UAAU,MAAM,oCAAoC,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EACL,WAAW,EACX,YAAY,GACb,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,WAAW,EACX,UAAU,EACV,SAAS,GACV,MAAM,gCAAgC,CAAC;AASxC,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAClC,CAAO,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACxD,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;IAChC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC;IACtD,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAEpD,MAAM,EACJ,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,GACrB,GAAG,uBAAuB,EAAE,CAAC;IAE9B,MAAM,EAAE,UAAU,EAAE,GAAG,cAAc,EAAE,CAAC;IACxC,MAAM,aAAa,GAAG,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,aAAa,KAAI,UAAU,CAAC;IAG9D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IACxE,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAEb,MAAM,UAAU,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAGD,IAAI,QAA6B,CAAC;IAClC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,QAAQ,GAAG,oBAAoB,CAAC;YAChC,MAAM;QACR,KAAK,QAAQ;YACX,QAAQ,GAAG,oBAAoB,CAAC;YAChC,MAAM;QACR,KAAK,WAAW;YACd,QAAQ,GAAG,uBAAuB,CAAC;YACnC,MAAM;QACR,KAAK,OAAO;YACV,QAAQ,GAAG,mBAAmB,CAAC;YAC/B,MAAM;QACR;YACE,OAAO,IAAI,CAAC,IAAI,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IAGD,QAAQ,CAAC,oBAAoB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAO,GAAG,EAAE,EAAE;QACtD,IAAI,GAAG;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QAG1B,IAAI,IAAI,CAAC;QACT,IAAI,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAE1B,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CACtB,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAC/D,CAAC;YACJ,CAAC;iBAAM,CAAC;gBAEN,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CACtB,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CACrD,CAAC;YACJ,CAAC;YAED,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;QAC5C,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YAEpB,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC1B,IAAI,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACzD,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC,IAAI,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,CAAC;QACrD,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,IAAI;YACb,IAAI;YACJ,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;gBAC1B,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,8BAA8B;gBAC9C,CAAC,CAAC,4BAA4B;SACjC,CAAC,CAAC;IACL,CAAC,CAAA,CAAC,CAAC;AACL,CAAC,CAAA,CACF,CAAC;AASF,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAClC,CAAO,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACxD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;IAsB1C,MAAM,EACJ,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,GACrB,GAAG,uBAAuB,EAAE,CAAC;IAE9B,IAAI,QAA6B,CAAC;IAClC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,QAAQ,GAAG,oBAAoB,CAAC;YAChC,MAAM;QACR,KAAK,QAAQ;YACX,QAAQ,GAAG,oBAAoB,CAAC;YAChC,MAAM;QACR,KAAK,WAAW;YACd,QAAQ,GAAG,uBAAuB,CAAC;YACnC,MAAM;QACR,KAAK,OAAO;YACV,QAAQ,GAAG,mBAAmB,CAAC;YAC/B,MAAM;QACR;YACE,OAAO,IAAI,CAAC,IAAI,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,CAAC;QAOH,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,QAAQ,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QACzE,MAAM,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAExC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,2BAA2B;SACrC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAEf,OAAO,IAAI,CAAC,IAAI,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;AACH,CAAC,CAAA,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAClC,CAAO,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACxD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;IAE1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/D,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;IAEhC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1E,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;QAEjE,IAAI,KAAK,IAAI,QAAQ,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;YACzC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC;YACzD,OAAO;QACT,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,eAAe,EAAE,SAAS,KAAK,IAAI,GAAG,IAAI,QAAQ,EAAE;YACpD,eAAe,EAAE,OAAO;YACxB,gBAAgB,EAAE,GAAG,GAAG,KAAK,GAAG,CAAC;YACjC,cAAc,EAAE,0BAA0B;YAC1C,qBAAqB,EAAE,qBAAqB,QAAQ,GAAG;SACxD,CAAC,CAAC;QAEH,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,gBAAgB,EAAE,QAAQ;YAC1B,cAAc,EAAE,0BAA0B;YAC1C,qBAAqB,EAAE,qBAAqB,QAAQ,GAAG;SACxD,CAAC,CAAC;QACH,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC,CAAA,CACF,CAAC","sourcesContent":["import AppError from \"../error-handler/utils/app-error\";\nimport {\n FileUploaderService,\n getFileUploaderServices,\n} from \"./file-uploader.service\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { NextFunction, Request, Response } from \"express\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport { promisify } from \"util\";\nimport { getArkosConfig } from \"../../server\";\nimport {\n processFile,\n processImage,\n} from \"./utils/helpers/file-uploader.helpers\";\nimport {\n accessAsync,\n mkdirAsync,\n statAsync,\n} from \"../../utils/helpers/fs.helpers\";\n\n/**\n * Handles file upload requests, processes images if needed, and returns URLs\n * Supports paths outside of the project directory with '../' prefix\n * @param {Request} req - Express request object\n * @param {Response} res - Express response object\n * @param {NextFunction} next - Express next middleware function\n */\nexport const uploadFile = catchAsync(\n async (req: Request, res: Response, next: NextFunction) => {\n const { fileType } = req.params;\n const { format, width, height, resizeTo } = req.query;\n const options = { format, width, height, resizeTo };\n\n const {\n documentUploaderService,\n fileUploaderService,\n imageUploaderService,\n videoUploaderService,\n } = getFileUploaderServices();\n\n const { fileUpload } = getArkosConfig();\n const baseUploadDir = fileUpload?.baseUploadDir || \"/uploads\";\n\n // Ensure upload directory exists\n const uploadPath = path.resolve(process.cwd(), baseUploadDir, fileType);\n try {\n await accessAsync(uploadPath);\n } catch (err) {\n // Create directory if it doesn't exist\n await mkdirAsync(uploadPath, { recursive: true });\n }\n\n // Select the appropriate uploader service based on file type\n let uploader: FileUploaderService;\n switch (fileType) {\n case \"images\":\n uploader = imageUploaderService;\n break;\n case \"videos\":\n uploader = videoUploaderService;\n break;\n case \"documents\":\n uploader = documentUploaderService;\n break;\n case \"files\":\n uploader = fileUploaderService;\n break;\n default:\n return next(new AppError(\"Invalid file type\", 400));\n }\n\n // Handle the file upload\n uploader.handleMultipleUpload()(req, res, async (err) => {\n if (err) return next(err);\n\n // Process all uploaded files\n let data;\n if (req.files && Array.isArray(req.files)) {\n if (fileType === \"images\") {\n // Process multiple image files with image transformations\n data = await Promise.all(\n req.files.map((file) => processImage(req, file.path, options))\n );\n } else {\n // Just store other file types without processing\n data = await Promise.all(\n req.files.map((file) => processFile(req, file.path))\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 if (fileType === \"images\") {\n data = await processImage(req, req.file.path, options);\n } else {\n data = await processFile(req, req.file.path);\n }\n } else {\n return next(new AppError(\"No file uploaded\", 400));\n }\n\n res.status(200).json({\n success: true,\n data,\n message: Array.isArray(data)\n ? `${data.length} files uploaded successfully`\n : \"File uploaded successfully\",\n });\n });\n }\n);\n\n/**\n * Handles file deletion requests\n * Supports paths outside of the project directory with '../' prefix\n * @param {Request} req - Express request object\n * @param {Response} res - Express response object\n * @param {NextFunction} next - Express next middleware function\n */\nexport const deleteFile = catchAsync(\n async (req: Request, res: Response, next: NextFunction) => {\n const { fileType, fileName } = req.params;\n\n // if (!fileName) {\n // return next(new AppError(\"File name is required\", 400));\n // }\n\n // if (!fileType) {\n // return next(new AppError(\"File type is required\", 400));\n // }\n\n // // Get the base upload directory from config\n // const { fileUpload } = getArkosConfig();\n // const baseUploadDir = fileUpload?.baseUploadDir || \"/uploads\";\n\n // // Construct the actual file path using path.resolve to handle '../' paths\n // const actualFilePath = path.resolve(\n // process.cwd(),\n // baseUploadDir,\n // fileType,\n // fileName\n // );\n\n const {\n documentUploaderService,\n fileUploaderService,\n imageUploaderService,\n videoUploaderService,\n } = getFileUploaderServices();\n\n let uploader: FileUploaderService;\n switch (fileType) {\n case \"images\":\n uploader = imageUploaderService;\n break;\n case \"videos\":\n uploader = videoUploaderService;\n break;\n case \"documents\":\n uploader = documentUploaderService;\n break;\n case \"files\":\n uploader = fileUploaderService;\n break;\n default:\n return next(new AppError(\"Invalid file type\", 400));\n }\n\n try {\n // // Check if file exists\n // await access(actualFilePath, fs.constants.F_OK);\n\n // // Delete the file\n // await unlink(actualFilePath);\n\n const fullUrl = `${req.protocol}://${req.get(\"host\")}${req.originalUrl}`;\n await uploader.deleteFileByUrl(fullUrl);\n\n res.status(200).json({\n success: true,\n message: \"File deleted successfully\",\n });\n } catch (error) {\n // File doesn't exist\n return next(new AppError(\"File not found\", 404));\n }\n }\n);\n\nexport const streamFile = catchAsync(\n async (req: Request, res: Response, next: NextFunction) => {\n const { fileName, fileType } = req.params;\n\n const filePath = path.join(\".\", \"uploads\", fileType, fileName);\n try {\n await accessAsync(filePath);\n } catch (err) {\n throw new AppError(\"File not found\", 404);\n }\n\n const fileStat = await statAsync(filePath);\n const fileSize = fileStat.size;\n const range = req.headers.range;\n\n if (range) {\n const [partialStart, partialEnd] = range.replace(/bytes=/, \"\").split(\"-\");\n const start = parseInt(partialStart, 10) || 0;\n const end = partialEnd ? parseInt(partialEnd, 10) : fileSize - 1;\n\n if (start >= fileSize || end >= fileSize) {\n res.status(416).json({ error: \"Range Not Satisfiable\" });\n return;\n }\n\n res.writeHead(206, {\n \"Content-Range\": `bytes ${start}-${end}/${fileSize}`,\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": end - start + 1,\n \"Content-Type\": \"application/octet-stream\",\n \"Content-Disposition\": `inline; filename=\"${fileName}\"`,\n });\n\n fs.createReadStream(filePath, { start, end }).pipe(res);\n } else {\n res.writeHead(200, {\n \"Content-Length\": fileSize,\n \"Content-Type\": \"application/octet-stream\",\n \"Content-Disposition\": `inline; filename=\"${fileName}\"`,\n });\n fs.createReadStream(filePath).pipe(res);\n }\n }\n);\n"]}
|
|
1
|
+
{"version":3,"file":"file-uploader.controller.js","sourceRoot":"","sources":["../../../../src/modules/file-uploader/file-uploader.controller.ts"],"names":[],"mappings":"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","sourcesContent":["import AppError from \"../error-handler/utils/app-error\";\nimport {\n FileUploaderService,\n getFileUploaderServices,\n} from \"./file-uploader.service\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { NextFunction, Request, Response } from \"express\";\nimport catchAsync from \"../error-handler/utils/catch-async\";\nimport { promisify } from \"util\";\nimport { getArkosConfig } from \"../../server\";\nimport {\n processFile,\n processImage,\n} from \"./utils/helpers/file-uploader.helpers\";\nimport {\n accessAsync,\n mkdirAsync,\n statAsync,\n} from \"../../utils/helpers/fs.helpers\";\n\n/**\n * Handles file upload requests, processes images if needed, and returns URLs\n * Supports paths outside of the project directory with '../' prefix\n * @param {Request} req - Express request object\n * @param {Response} res - Express response object\n * @param {NextFunction} next - Express next middleware function\n */\nexport const uploadFile = catchAsync(\n async (req: Request, res: Response, next: NextFunction) => {\n const { fileType } = req.params;\n const { format, width, height, resizeTo } = req.query;\n const options = { format, width, height, resizeTo };\n\n const {\n documentUploaderService,\n fileUploaderService,\n imageUploaderService,\n videoUploaderService,\n } = getFileUploaderServices();\n\n const { fileUpload } = getArkosConfig();\n const baseUploadDir = fileUpload?.baseUploadDir || \"/uploads\";\n\n // Ensure upload directory exists\n const uploadPath = path.resolve(process.cwd(), baseUploadDir, fileType);\n try {\n await accessAsync(uploadPath);\n } catch (err) {\n // Create directory if it doesn't exist\n await mkdirAsync(uploadPath, { recursive: true });\n }\n\n // Select the appropriate uploader service based on file type\n let uploader: FileUploaderService;\n switch (fileType) {\n case \"images\":\n uploader = imageUploaderService;\n break;\n case \"videos\":\n uploader = videoUploaderService;\n break;\n case \"documents\":\n uploader = documentUploaderService;\n break;\n case \"files\":\n uploader = fileUploaderService;\n break;\n default:\n return next(new AppError(\"Invalid file type\", 400));\n }\n\n // Handle the file upload\n uploader.handleMultipleUpload()(req, res, async (err) => {\n if (err) return next(err);\n\n // Process all uploaded files\n let data;\n if (req.files && Array.isArray(req.files)) {\n if (fileType === \"images\") {\n // Process multiple image files with image transformations\n data = await Promise.all(\n req.files.map((file) => processImage(req, file.path, options))\n );\n } else {\n // Just store other file types without processing\n data = await Promise.all(\n req.files.map((file) => processFile(req, file.path))\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 if (fileType === \"images\") {\n data = await processImage(req, req.file.path, options);\n } else {\n data = await processFile(req, req.file.path);\n }\n } else {\n return next(new AppError(\"No file uploaded\", 400));\n }\n\n res.status(200).json({\n success: true,\n data,\n message: Array.isArray(data)\n ? `${data.length} files uploaded successfully`\n : \"File uploaded successfully\",\n });\n });\n }\n);\n\n/**\n * Handles file deletion requests\n * Supports paths outside of the project directory with '../' prefix\n * @param {Request} req - Express request object\n * @param {Response} res - Express response object\n * @param {NextFunction} next - Express next middleware function\n */\nexport const deleteFile = catchAsync(\n async (req: Request, res: Response, next: NextFunction) => {\n const { fileType, fileName } = req.params;\n\n // if (!fileName) {\n // return next(new AppError(\"File name is required\", 400));\n // }\n\n // if (!fileType) {\n // return next(new AppError(\"File type is required\", 400));\n // }\n\n // // Get the base upload directory from config\n // const { fileUpload } = getArkosConfig();\n // const baseUploadDir = fileUpload?.baseUploadDir || \"/uploads\";\n\n // // Construct the actual file path using path.resolve to handle '../' paths\n // const actualFilePath = path.resolve(\n // process.cwd(),\n // baseUploadDir,\n // fileType,\n // fileName\n // );\n\n const {\n documentUploaderService,\n fileUploaderService,\n imageUploaderService,\n videoUploaderService,\n } = getFileUploaderServices();\n\n let uploader: FileUploaderService;\n switch (fileType) {\n case \"images\":\n uploader = imageUploaderService;\n break;\n case \"videos\":\n uploader = videoUploaderService;\n break;\n case \"documents\":\n uploader = documentUploaderService;\n break;\n case \"files\":\n uploader = fileUploaderService;\n break;\n default:\n return next(new AppError(\"Invalid file type\", 400));\n }\n\n try {\n // // Check if file exists\n // await access(actualFilePath, fs.constants.F_OK);\n\n // // Delete the file\n // await unlink(actualFilePath);\n\n const fullUrl = `${req.protocol}://${req.get(\"host\")}${req.originalUrl}`;\n await uploader.deleteFileByUrl(fullUrl);\n\n res.status(200).json({\n success: true,\n message: \"File deleted successfully\",\n });\n } catch (error) {\n // File doesn't exist\n return next(new AppError(\"File not found\", 404));\n }\n }\n);\n\nexport const streamFile = catchAsync(\n async (req: Request, res: Response, next: NextFunction) => {\n const { fileName, fileType } = req.params;\n\n const filePath = path.join(\".\", \"uploads\", fileType, fileName);\n try {\n await accessAsync(filePath);\n } catch (err) {\n throw new AppError(\"File not found\", 404);\n }\n\n const fileStat = await statAsync(filePath);\n const fileSize = fileStat.size;\n const range = req.headers.range;\n\n if (range) {\n const [partialStart, partialEnd] = range.replace(/bytes=/, \"\").split(\"-\");\n const start = parseInt(partialStart, 10) || 0;\n const end = partialEnd ? parseInt(partialEnd, 10) : fileSize - 1;\n\n if (start >= fileSize || end >= fileSize) {\n res.status(416).json({ error: \"Range Not Satisfiable\" });\n return;\n }\n\n res.writeHead(206, {\n \"Content-Range\": `bytes ${start}-${end}/${fileSize}`,\n \"Accept-Ranges\": \"bytes\",\n \"Content-Length\": end - start + 1,\n \"Content-Type\": \"application/octet-stream\",\n \"Content-Disposition\": `inline; filename=\"${fileName}\"`,\n });\n\n fs.createReadStream(filePath, { start, end }).pipe(res);\n } else {\n res.writeHead(200, {\n \"Content-Length\": fileSize,\n \"Content-Type\": \"application/octet-stream\",\n \"Content-Disposition\": `inline; filename=\"${fileName}\"`,\n });\n fs.createReadStream(filePath).pipe(res);\n }\n }\n);\n"]}
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { Router } from "express";
|
|
11
2
|
import { importPrismaModelModules } from "../../utils/helpers/models.helpers";
|
|
12
3
|
import authService from "../auth/auth.service";
|
|
@@ -15,30 +6,28 @@ import path from "path";
|
|
|
15
6
|
import express from "express";
|
|
16
7
|
import deepmerge from "../../utils/helpers/deepmerge.helper";
|
|
17
8
|
const router = Router();
|
|
18
|
-
export function getFileUploaderRouter(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return router;
|
|
42
|
-
});
|
|
9
|
+
export async function getFileUploaderRouter({ fileUpload }) {
|
|
10
|
+
const modelModules = await importPrismaModelModules("file-upload");
|
|
11
|
+
let { middlewares = {}, authConfigs = {} } = {};
|
|
12
|
+
if (modelModules) {
|
|
13
|
+
({ middlewares = {}, authConfigs = {} } = modelModules);
|
|
14
|
+
}
|
|
15
|
+
let basePathname = fileUpload?.baseRoute || "/api/uploads/";
|
|
16
|
+
if (!basePathname.startsWith("/"))
|
|
17
|
+
basePathname = "/" + basePathname;
|
|
18
|
+
if (!basePathname.endsWith("/"))
|
|
19
|
+
basePathname = basePathname + "/";
|
|
20
|
+
router.use(basePathname, authService.handleAuthenticationControl("view", authConfigs), authService.handleAccessControl("view", "file-upload", authConfigs), express.static(path.resolve(process.cwd(), fileUpload?.baseUploadDir || "uploads"), deepmerge({
|
|
21
|
+
maxAge: "1y",
|
|
22
|
+
etag: true,
|
|
23
|
+
lastModified: true,
|
|
24
|
+
dotfiles: "ignore",
|
|
25
|
+
fallthrough: true,
|
|
26
|
+
index: false,
|
|
27
|
+
cacheControl: true,
|
|
28
|
+
}, fileUpload?.expressStaticOptions || {})));
|
|
29
|
+
router.post(`${basePathname}:fileType`, authService.handleAuthenticationControl("create", authConfigs), authService.handleAccessControl("create", "file-upload", authConfigs), uploadFile);
|
|
30
|
+
router.delete(`${basePathname}:fileType/:fileName`, authService.handleAuthenticationControl("delete", authConfigs), authService.handleAccessControl("create", "file-upload", authConfigs), deleteFile);
|
|
31
|
+
return router;
|
|
43
32
|
}
|
|
44
33
|
//# sourceMappingURL=file-uploader.router.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-uploader.router.js","sourceRoot":"","sources":["../../../../src/modules/file-uploader/file-uploader.router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"file-uploader.router.js","sourceRoot":"","sources":["../../../../src/modules/file-uploader/file-uploader.router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAEpE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,SAAS,MAAM,sCAAsC,CAAC;AAE7D,MAAM,MAAM,GAAW,MAAM,EAAE,CAAC;AAEhC,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAAE,UAAU,EAAe;IACrE,MAAM,YAAY,GAAG,MAAM,wBAAwB,CAAC,aAAa,CAAC,CAAC;IACnE,IAAI,EAAE,WAAW,GAAG,EAAE,EAAE,WAAW,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC;IAEhD,IAAI,YAAY,EAAE,CAAC;QACjB,CAAC,EAAE,WAAW,GAAG,EAAE,EAAE,WAAW,GAAG,EAAE,EAAE,GAAG,YAAY,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,YAAY,GAAG,UAAU,EAAE,SAAS,IAAI,eAAe,CAAC;IAE5D,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,YAAY,GAAG,GAAG,GAAG,YAAY,CAAC;IACrE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,YAAY,GAAG,YAAY,GAAG,GAAG,CAAC;IAEnE,MAAM,CAAC,GAAG,CACR,YAAY,EACZ,WAAW,CAAC,2BAA2B,CAAC,MAAM,EAAE,WAAW,CAAC,EAC5D,WAAW,CAAC,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC,EACnE,OAAO,CAAC,MAAM,CACZ,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,aAAa,IAAI,SAAS,CAAC,EACnE,SAAS,CACP;QACE,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,IAAI;QACV,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,QAAQ;QAClB,WAAW,EAAE,IAAI;QACjB,KAAK,EAAE,KAAK;QACZ,YAAY,EAAE,IAAI;KACnB,EACD,UAAU,EAAE,oBAAoB,IAAI,EAAE,CACvC,CACF,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,GAAG,YAAY,WAAW,EAC1B,WAAW,CAAC,2BAA2B,CAAC,QAAQ,EAAE,WAAW,CAAC,EAC9D,WAAW,CAAC,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,WAAW,CAAC,EACrE,UAAU,CACX,CAAC;IAEF,MAAM,CAAC,MAAM,CACX,GAAG,YAAY,qBAAqB,EACpC,WAAW,CAAC,2BAA2B,CAAC,QAAQ,EAAE,WAAW,CAAC,EAC9D,WAAW,CAAC,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,WAAW,CAAC,EACrE,UAAU,CACX,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { Router } from \"express\";\nimport { importPrismaModelModules } from \"../../utils/helpers/models.helpers\";\nimport authService from \"../auth/auth.service\";\nimport { deleteFile, uploadFile } from \"./file-uploader.controller\";\nimport { ArkosConfig } from \"../../types/arkos-config\";\nimport path from \"path\";\nimport express from \"express\";\nimport deepmerge from \"../../utils/helpers/deepmerge.helper\";\n\nconst router: Router = Router();\n\nexport async function getFileUploaderRouter({ fileUpload }: ArkosConfig) {\n const modelModules = await importPrismaModelModules(\"file-upload\");\n let { middlewares = {}, authConfigs = {} } = {};\n\n if (modelModules) {\n ({ middlewares = {}, authConfigs = {} } = modelModules);\n }\n\n let basePathname = fileUpload?.baseRoute || \"/api/uploads/\";\n\n if (!basePathname.startsWith(\"/\")) basePathname = \"/\" + basePathname;\n if (!basePathname.endsWith(\"/\")) basePathname = basePathname + \"/\";\n\n router.use(\n basePathname,\n authService.handleAuthenticationControl(\"view\", authConfigs),\n authService.handleAccessControl(\"view\", \"file-upload\", authConfigs),\n express.static(\n path.resolve(process.cwd(), fileUpload?.baseUploadDir || \"uploads\"),\n deepmerge(\n {\n maxAge: \"1y\",\n etag: true,\n lastModified: true,\n dotfiles: \"ignore\",\n fallthrough: true,\n index: false,\n cacheControl: true,\n },\n fileUpload?.expressStaticOptions || {}\n )\n )\n );\n\n router.post(\n `${basePathname}:fileType`,\n authService.handleAuthenticationControl(\"create\", authConfigs),\n authService.handleAccessControl(\"create\", \"file-upload\", authConfigs),\n uploadFile\n );\n\n router.delete(\n `${basePathname}:fileType/:fileName`,\n authService.handleAuthenticationControl(\"delete\", authConfigs),\n authService.handleAccessControl(\"create\", \"file-upload\", authConfigs),\n deleteFile\n );\n\n return router;\n}\n"]}
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import multer from "multer";
|
|
11
2
|
import path from "path";
|
|
12
3
|
import fs from "fs";
|
|
@@ -57,7 +48,7 @@ export class FileUploaderService {
|
|
|
57
48
|
handleSingleUpload(oldFilePath) {
|
|
58
49
|
return (req, res, next) => {
|
|
59
50
|
const upload = this.getUploader().single(this.getFieldName());
|
|
60
|
-
upload(req, res, (err) =>
|
|
51
|
+
upload(req, res, async (err) => {
|
|
61
52
|
if (err instanceof multer.MulterError) {
|
|
62
53
|
return next(err);
|
|
63
54
|
}
|
|
@@ -66,18 +57,18 @@ export class FileUploaderService {
|
|
|
66
57
|
}
|
|
67
58
|
if (oldFilePath) {
|
|
68
59
|
const { fileUpload: configs } = getArkosConfig();
|
|
69
|
-
const filePath = path.resolve(process.cwd(), removeBothSlashes(configs
|
|
60
|
+
const filePath = path.resolve(process.cwd(), removeBothSlashes(configs?.baseUploadDir), removeBothSlashes(oldFilePath));
|
|
70
61
|
try {
|
|
71
|
-
const stats =
|
|
62
|
+
const stats = await promisify(fs.stat)(filePath);
|
|
72
63
|
if (stats)
|
|
73
|
-
|
|
64
|
+
await promisify(fs.unlink)(filePath);
|
|
74
65
|
}
|
|
75
66
|
catch (err) {
|
|
76
67
|
console.error(err);
|
|
77
68
|
}
|
|
78
69
|
}
|
|
79
70
|
next();
|
|
80
|
-
})
|
|
71
|
+
});
|
|
81
72
|
};
|
|
82
73
|
}
|
|
83
74
|
handleMultipleUpload() {
|
|
@@ -93,87 +84,85 @@ export class FileUploaderService {
|
|
|
93
84
|
};
|
|
94
85
|
}
|
|
95
86
|
handleDeleteSingleFile(oldFilePath) {
|
|
96
|
-
return (req, res, next) =>
|
|
87
|
+
return async (req, res, next) => {
|
|
97
88
|
const filePath = path.join(oldFilePath);
|
|
98
89
|
try {
|
|
99
|
-
const stats =
|
|
90
|
+
const stats = await promisify(fs.stat)(filePath);
|
|
100
91
|
if (stats) {
|
|
101
|
-
|
|
92
|
+
await promisify(fs.unlink)(filePath);
|
|
102
93
|
}
|
|
103
94
|
}
|
|
104
95
|
catch (err) {
|
|
105
96
|
console.error(err);
|
|
106
97
|
}
|
|
107
98
|
next();
|
|
108
|
-
}
|
|
99
|
+
};
|
|
109
100
|
}
|
|
110
|
-
deleteFileByUrl(fileUrl) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
urlPath = url.pathname;
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
urlPath = fileUrl;
|
|
122
|
-
}
|
|
123
|
-
const baseRouteIndex = urlPath.indexOf(baseRoute);
|
|
124
|
-
if (baseRouteIndex === -1) {
|
|
125
|
-
throw new AppError("Invalid file URL: base route not found", 400);
|
|
126
|
-
}
|
|
127
|
-
const pathAfterBaseRoute = urlPath.substring(baseRouteIndex + baseRoute.length);
|
|
128
|
-
const cleanPath = pathAfterBaseRoute.startsWith("/")
|
|
129
|
-
? pathAfterBaseRoute.substring(1)
|
|
130
|
-
: pathAfterBaseRoute;
|
|
131
|
-
const fileTypes = ["images", "videos", "documents", "files"];
|
|
132
|
-
let fileType = null;
|
|
133
|
-
let fileName = null;
|
|
134
|
-
for (const type of fileTypes) {
|
|
135
|
-
const typeIndex = cleanPath.indexOf(type + "/");
|
|
136
|
-
if (typeIndex !== -1) {
|
|
137
|
-
fileType = type;
|
|
138
|
-
fileName = cleanPath.substring(typeIndex + type.length + 1);
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (!fileType || !fileName) {
|
|
143
|
-
throw new AppError("Unable to determine file type or file name from URL", 400);
|
|
144
|
-
}
|
|
145
|
-
const { documentUploaderService, fileUploaderService, imageUploaderService, videoUploaderService, } = getFileUploaderServices();
|
|
146
|
-
let filePath;
|
|
147
|
-
switch (fileType) {
|
|
148
|
-
case "images":
|
|
149
|
-
filePath = path.join(imageUploaderService.uploadDir, fileName);
|
|
150
|
-
break;
|
|
151
|
-
case "videos":
|
|
152
|
-
filePath = path.join(videoUploaderService.uploadDir, fileName);
|
|
153
|
-
break;
|
|
154
|
-
case "documents":
|
|
155
|
-
filePath = path.join(documentUploaderService.uploadDir, fileName);
|
|
156
|
-
break;
|
|
157
|
-
case "files":
|
|
158
|
-
filePath = path.join(fileUploaderService.uploadDir, fileName);
|
|
159
|
-
break;
|
|
160
|
-
default:
|
|
161
|
-
throw new AppError(`Unsupported file type: ${fileType}`, 400);
|
|
162
|
-
}
|
|
163
|
-
yield promisify(fs.stat)(filePath);
|
|
164
|
-
yield promisify(fs.unlink)(filePath);
|
|
165
|
-
return true;
|
|
101
|
+
async deleteFileByUrl(fileUrl) {
|
|
102
|
+
try {
|
|
103
|
+
const { fileUpload } = getArkosConfig();
|
|
104
|
+
const baseRoute = fileUpload?.baseRoute || "/api/uploads";
|
|
105
|
+
let urlPath;
|
|
106
|
+
if (fileUrl.startsWith("http")) {
|
|
107
|
+
const url = new URL(fileUrl);
|
|
108
|
+
urlPath = url.pathname;
|
|
166
109
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
110
|
+
else {
|
|
111
|
+
urlPath = fileUrl;
|
|
112
|
+
}
|
|
113
|
+
const baseRouteIndex = urlPath.indexOf(baseRoute);
|
|
114
|
+
if (baseRouteIndex === -1) {
|
|
115
|
+
throw new AppError("Invalid file URL: base route not found", 400);
|
|
116
|
+
}
|
|
117
|
+
const pathAfterBaseRoute = urlPath.substring(baseRouteIndex + baseRoute.length);
|
|
118
|
+
const cleanPath = pathAfterBaseRoute.startsWith("/")
|
|
119
|
+
? pathAfterBaseRoute.substring(1)
|
|
120
|
+
: pathAfterBaseRoute;
|
|
121
|
+
const fileTypes = ["images", "videos", "documents", "files"];
|
|
122
|
+
let fileType = null;
|
|
123
|
+
let fileName = null;
|
|
124
|
+
for (const type of fileTypes) {
|
|
125
|
+
const typeIndex = cleanPath.indexOf(type + "/");
|
|
126
|
+
if (typeIndex !== -1) {
|
|
127
|
+
fileType = type;
|
|
128
|
+
fileName = cleanPath.substring(typeIndex + type.length + 1);
|
|
129
|
+
break;
|
|
173
130
|
}
|
|
174
|
-
throw new AppError(`Failed to delete file: ${error.message}`, 500);
|
|
175
131
|
}
|
|
176
|
-
|
|
132
|
+
if (!fileType || !fileName) {
|
|
133
|
+
throw new AppError("Unable to determine file type or file name from URL", 400);
|
|
134
|
+
}
|
|
135
|
+
const { documentUploaderService, fileUploaderService, imageUploaderService, videoUploaderService, } = getFileUploaderServices();
|
|
136
|
+
let filePath;
|
|
137
|
+
switch (fileType) {
|
|
138
|
+
case "images":
|
|
139
|
+
filePath = path.join(imageUploaderService.uploadDir, fileName);
|
|
140
|
+
break;
|
|
141
|
+
case "videos":
|
|
142
|
+
filePath = path.join(videoUploaderService.uploadDir, fileName);
|
|
143
|
+
break;
|
|
144
|
+
case "documents":
|
|
145
|
+
filePath = path.join(documentUploaderService.uploadDir, fileName);
|
|
146
|
+
break;
|
|
147
|
+
case "files":
|
|
148
|
+
filePath = path.join(fileUploaderService.uploadDir, fileName);
|
|
149
|
+
break;
|
|
150
|
+
default:
|
|
151
|
+
throw new AppError(`Unsupported file type: ${fileType}`, 400);
|
|
152
|
+
}
|
|
153
|
+
await promisify(fs.stat)(filePath);
|
|
154
|
+
await promisify(fs.unlink)(filePath);
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
if (error instanceof AppError) {
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
if (error.code === "ENOENT") {
|
|
162
|
+
throw new AppError("File not found", 404);
|
|
163
|
+
}
|
|
164
|
+
throw new AppError(`Failed to delete file: ${error.message}`, 500);
|
|
165
|
+
}
|
|
177
166
|
}
|
|
178
167
|
getFieldName() {
|
|
179
168
|
let fieldName = "files";
|
|
@@ -188,66 +177,63 @@ export class FileUploaderService {
|
|
|
188
177
|
fieldName = "files";
|
|
189
178
|
return fieldName;
|
|
190
179
|
}
|
|
191
|
-
upload(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if (
|
|
217
|
-
|
|
218
|
-
if (isImageUploader) {
|
|
219
|
-
data = yield Promise.all(req.files.map((file) => processImage(req, file.path, options)));
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
data = yield Promise.all(req.files.map((file) => processFile(req, file.path)));
|
|
223
|
-
}
|
|
224
|
-
data = data.filter((url) => url !== null);
|
|
180
|
+
async upload(req, res, options = {}) {
|
|
181
|
+
const { fileUpload } = getArkosConfig();
|
|
182
|
+
const baseRoute = fileUpload?.baseRoute || "/api/uploads";
|
|
183
|
+
return new Promise((resolve, reject) => {
|
|
184
|
+
const isMultiple = Array.isArray(req.query.multiple)
|
|
185
|
+
? req.query.multiple[0] == "true"
|
|
186
|
+
: req.query.multiple == "true";
|
|
187
|
+
const uploadHandler = isMultiple
|
|
188
|
+
? this.getUploader().array(this.getFieldName(), this.maxCount)
|
|
189
|
+
: this.getUploader().single(this.getFieldName());
|
|
190
|
+
uploadHandler(req, res, async (err) => {
|
|
191
|
+
if (err)
|
|
192
|
+
return reject(err);
|
|
193
|
+
try {
|
|
194
|
+
const protocol = req.get("host")?.includes?.("localhost")
|
|
195
|
+
? "http"
|
|
196
|
+
: "https";
|
|
197
|
+
const baseURL = `${protocol}://${req.get("host")}`;
|
|
198
|
+
const dirParts = this.uploadDir.split("/");
|
|
199
|
+
const fileType = (this.uploadDir.endsWith("/")
|
|
200
|
+
? dirParts[dirParts.length - 2]
|
|
201
|
+
: dirParts[dirParts.length - 1]) || "files";
|
|
202
|
+
let data;
|
|
203
|
+
if (req.files && Array.isArray(req.files) && req.files.length > 0) {
|
|
204
|
+
const isImageUploader = this.uploadDir?.includes?.("/images");
|
|
205
|
+
if (isImageUploader) {
|
|
206
|
+
data = await Promise.all(req.files.map((file) => processImage(req, file.path, options)));
|
|
225
207
|
}
|
|
226
|
-
else
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
208
|
+
else {
|
|
209
|
+
data = await Promise.all(req.files.map((file) => processFile(req, file.path)));
|
|
210
|
+
}
|
|
211
|
+
data = data.filter((url) => url !== null);
|
|
212
|
+
}
|
|
213
|
+
else if (req.file) {
|
|
214
|
+
const isImageUploader = this.uploadDir?.includes?.("/images");
|
|
215
|
+
if (isImageUploader) {
|
|
216
|
+
data = await processImage(req, req.file.path, options);
|
|
234
217
|
}
|
|
235
218
|
else {
|
|
236
|
-
|
|
219
|
+
data = await processFile(req, req.file.path);
|
|
237
220
|
}
|
|
238
|
-
resolve(data);
|
|
239
221
|
}
|
|
240
|
-
|
|
241
|
-
reject(
|
|
222
|
+
else {
|
|
223
|
+
return reject(new AppError("No file uploaded", 400));
|
|
242
224
|
}
|
|
243
|
-
|
|
225
|
+
resolve(data);
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
reject(error);
|
|
229
|
+
}
|
|
244
230
|
});
|
|
245
231
|
});
|
|
246
232
|
}
|
|
247
233
|
}
|
|
248
234
|
export const getFileUploaderServices = () => {
|
|
249
235
|
const { fileUpload } = getArkosConfig();
|
|
250
|
-
const baseUploadDir =
|
|
236
|
+
const baseUploadDir = fileUpload?.baseUploadDir || "/uploads";
|
|
251
237
|
const defaultRegexPatterns = {
|
|
252
238
|
images: /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/,
|
|
253
239
|
videos: /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/,
|
|
@@ -276,7 +262,7 @@ export const getFileUploaderServices = () => {
|
|
|
276
262
|
supportedFilesRegex: /.*/,
|
|
277
263
|
},
|
|
278
264
|
};
|
|
279
|
-
const restrictions =
|
|
265
|
+
const restrictions = fileUpload?.restrictions
|
|
280
266
|
? deepmerge(defaultRestrictions, fileUpload.restrictions)
|
|
281
267
|
: defaultRestrictions;
|
|
282
268
|
const imageUploaderService = new FileUploaderService(`${baseUploadDir}/images`, restrictions.images.maxSize, restrictions.images.supportedFilesRegex, restrictions.images.maxCount);
|