@hdriel/aws-utils 1.1.6 → 1.1.8
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/README.md +320 -166
- package/dist/index.cjs +157 -119
- package/dist/index.d.cts +41 -23
- package/dist/index.d.ts +41 -23
- package/dist/index.js +158 -120
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -271,7 +271,7 @@ var LambdaUtil = class {
|
|
|
271
271
|
var import_client_s36 = require("@aws-sdk/client-s3");
|
|
272
272
|
|
|
273
273
|
// src/aws/s3/s3-stream.ts
|
|
274
|
-
var import_pathe2 =
|
|
274
|
+
var import_pathe2 = require("pathe");
|
|
275
275
|
var import_stream = require("stream");
|
|
276
276
|
var import_util = require("util");
|
|
277
277
|
var import_buffer2 = require("buffer");
|
|
@@ -321,6 +321,23 @@ var getTotalSeconds = (msValue) => {
|
|
|
321
321
|
const value = (0, import_ms.default)(msValue);
|
|
322
322
|
return value / 1e3;
|
|
323
323
|
};
|
|
324
|
+
var getUnitBytes = (bytes2, unit) => {
|
|
325
|
+
switch (unit == null ? void 0 : unit.toUpperCase()) {
|
|
326
|
+
case "KB":
|
|
327
|
+
return bytes2 / 1024;
|
|
328
|
+
case "MB":
|
|
329
|
+
return bytes2 / __pow(1024, 2);
|
|
330
|
+
case "GB":
|
|
331
|
+
return bytes2 / __pow(1024, 3);
|
|
332
|
+
case "TB":
|
|
333
|
+
return bytes2 / __pow(1024, 4);
|
|
334
|
+
case "PB":
|
|
335
|
+
return bytes2 / __pow(1024, 5);
|
|
336
|
+
case "B":
|
|
337
|
+
default:
|
|
338
|
+
return bytes2;
|
|
339
|
+
}
|
|
340
|
+
};
|
|
324
341
|
|
|
325
342
|
// src/aws/s3/s3-file.ts
|
|
326
343
|
var import_buffer = require("buffer");
|
|
@@ -681,7 +698,6 @@ var S3Directory = class extends S3Bucket {
|
|
|
681
698
|
constructor(props) {
|
|
682
699
|
super(props);
|
|
683
700
|
}
|
|
684
|
-
// todo: checked!
|
|
685
701
|
directoryExists(directoryPath) {
|
|
686
702
|
return __async(this, null, function* () {
|
|
687
703
|
var _a2;
|
|
@@ -699,7 +715,6 @@ var S3Directory = class extends S3Bucket {
|
|
|
699
715
|
}
|
|
700
716
|
});
|
|
701
717
|
}
|
|
702
|
-
// todo: checked!
|
|
703
718
|
createDirectory(directoryPath) {
|
|
704
719
|
return __async(this, null, function* () {
|
|
705
720
|
let normalizedPath = getNormalizedPath(directoryPath);
|
|
@@ -709,7 +724,6 @@ var S3Directory = class extends S3Bucket {
|
|
|
709
724
|
return result;
|
|
710
725
|
});
|
|
711
726
|
}
|
|
712
|
-
// todo: checked!
|
|
713
727
|
deleteDirectory(directoryPath) {
|
|
714
728
|
return __async(this, null, function* () {
|
|
715
729
|
var _a2, _b, _c, _d, _e, _f, _g;
|
|
@@ -779,7 +793,6 @@ var S3Directory = class extends S3Bucket {
|
|
|
779
793
|
};
|
|
780
794
|
});
|
|
781
795
|
}
|
|
782
|
-
// todo: checked!
|
|
783
796
|
directoryList(directoryPath) {
|
|
784
797
|
return __async(this, null, function* () {
|
|
785
798
|
var _a2;
|
|
@@ -836,7 +849,6 @@ var S3Directory = class extends S3Bucket {
|
|
|
836
849
|
return { directories, files };
|
|
837
850
|
});
|
|
838
851
|
}
|
|
839
|
-
// todo: checked!
|
|
840
852
|
directoryListPaginated(_0) {
|
|
841
853
|
return __async(this, arguments, function* (directoryPath, {
|
|
842
854
|
pageSize = 100,
|
|
@@ -955,9 +967,9 @@ var S3File = class extends S3Directory {
|
|
|
955
967
|
constructor(props) {
|
|
956
968
|
super(props);
|
|
957
969
|
}
|
|
958
|
-
fileInfo(
|
|
970
|
+
fileInfo(fileKey) {
|
|
959
971
|
return __async(this, null, function* () {
|
|
960
|
-
const normalizedKey = getNormalizedPath(
|
|
972
|
+
const normalizedKey = getNormalizedPath(fileKey);
|
|
961
973
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
962
974
|
const command = new import_client_s34.HeadObjectCommand({ Bucket: this.bucket, Key: normalizedKey });
|
|
963
975
|
const result = yield this.execute(command);
|
|
@@ -996,7 +1008,6 @@ var S3File = class extends S3Directory {
|
|
|
996
1008
|
return files;
|
|
997
1009
|
});
|
|
998
1010
|
}
|
|
999
|
-
// todo: checked!
|
|
1000
1011
|
fileListPaginated(_0) {
|
|
1001
1012
|
return __async(this, arguments, function* (directoryPath, {
|
|
1002
1013
|
fileNamePrefix,
|
|
@@ -1052,14 +1063,13 @@ var S3File = class extends S3Directory {
|
|
|
1052
1063
|
};
|
|
1053
1064
|
});
|
|
1054
1065
|
}
|
|
1055
|
-
|
|
1056
|
-
taggingFile(filePath, tag) {
|
|
1066
|
+
taggingFile(fileKey, tag) {
|
|
1057
1067
|
return __async(this, null, function* () {
|
|
1058
1068
|
var _a2;
|
|
1059
1069
|
let normalizedKey = "";
|
|
1060
1070
|
const tags = [].concat(tag);
|
|
1061
1071
|
try {
|
|
1062
|
-
normalizedKey = getNormalizedPath(
|
|
1072
|
+
normalizedKey = getNormalizedPath(fileKey);
|
|
1063
1073
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1064
1074
|
const command = new import_client_s34.PutObjectTaggingCommand({
|
|
1065
1075
|
Bucket: this.bucket,
|
|
@@ -1074,11 +1084,10 @@ var S3File = class extends S3Directory {
|
|
|
1074
1084
|
}
|
|
1075
1085
|
});
|
|
1076
1086
|
}
|
|
1077
|
-
|
|
1078
|
-
fileVersion(filePath) {
|
|
1087
|
+
fileVersion(fileKey) {
|
|
1079
1088
|
return __async(this, null, function* () {
|
|
1080
1089
|
var _a2, _b;
|
|
1081
|
-
const normalizedKey = getNormalizedPath(
|
|
1090
|
+
const normalizedKey = getNormalizedPath(fileKey);
|
|
1082
1091
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1083
1092
|
const command = new import_client_s34.GetObjectTaggingCommand({ Bucket: this.bucket, Key: normalizedKey });
|
|
1084
1093
|
const result = yield this.execute(command);
|
|
@@ -1086,11 +1095,10 @@ var S3File = class extends S3Directory {
|
|
|
1086
1095
|
return (_b = tag == null ? void 0 : tag.Value) != null ? _b : "";
|
|
1087
1096
|
});
|
|
1088
1097
|
}
|
|
1089
|
-
|
|
1090
|
-
fileUrl(filePath, expiresIn = "15m") {
|
|
1098
|
+
fileUrl(fileKey, expiresIn = "15m") {
|
|
1091
1099
|
return __async(this, null, function* () {
|
|
1092
1100
|
var _a2;
|
|
1093
|
-
let normalizedKey = getNormalizedPath(
|
|
1101
|
+
let normalizedKey = getNormalizedPath(fileKey);
|
|
1094
1102
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1095
1103
|
const expiresInSeconds = typeof expiresIn === "number" ? expiresIn : (0, import_ms2.default)(expiresIn) / 1e3;
|
|
1096
1104
|
const command = new import_client_s34.GetObjectCommand({ Bucket: this.bucket, Key: normalizedKey });
|
|
@@ -1098,44 +1106,34 @@ var S3File = class extends S3Directory {
|
|
|
1098
1106
|
expiresIn: expiresInSeconds
|
|
1099
1107
|
// is using 3600 it's will expire in 1 hour (default is 900 seconds = 15 minutes)
|
|
1100
1108
|
});
|
|
1101
|
-
(_a2 = this.logger) == null ? void 0 : _a2.info(null, "generate signed file url", { url,
|
|
1109
|
+
(_a2 = this.logger) == null ? void 0 : _a2.info(null, "generate signed file url", { url, fileKey: normalizedKey, expiresIn });
|
|
1102
1110
|
return url;
|
|
1103
1111
|
});
|
|
1104
1112
|
}
|
|
1105
|
-
sizeOf(
|
|
1113
|
+
sizeOf(fileKey, unit) {
|
|
1106
1114
|
return __async(this, null, function* () {
|
|
1107
1115
|
var _a2, _b, _c;
|
|
1108
|
-
const normalizedKey = getNormalizedPath(
|
|
1116
|
+
const normalizedKey = getNormalizedPath(fileKey);
|
|
1109
1117
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1110
1118
|
try {
|
|
1111
1119
|
const command = new import_client_s34.HeadObjectCommand({ Bucket: this.bucket, Key: normalizedKey });
|
|
1112
1120
|
const headObject = yield this.execute(command);
|
|
1113
1121
|
const bytes2 = (_a2 = headObject.ContentLength) != null ? _a2 : 0;
|
|
1114
|
-
|
|
1115
|
-
case "KB":
|
|
1116
|
-
return bytes2 / 1024;
|
|
1117
|
-
case "MB":
|
|
1118
|
-
return bytes2 / (1024 * 1024);
|
|
1119
|
-
case "GB":
|
|
1120
|
-
return bytes2 / (1024 * 1024 * 1024);
|
|
1121
|
-
default:
|
|
1122
|
-
return bytes2;
|
|
1123
|
-
}
|
|
1122
|
+
return getUnitBytes(bytes2, unit);
|
|
1124
1123
|
} catch (error) {
|
|
1125
1124
|
if (error.name === "NotFound" || ((_b = error.$metadata) == null ? void 0 : _b.httpStatusCode) === 404) {
|
|
1126
|
-
(_c = this.logger) == null ? void 0 : _c.warn(this.reqId, "File not found", {
|
|
1125
|
+
(_c = this.logger) == null ? void 0 : _c.warn(this.reqId, "File not found", { fileKey: normalizedKey });
|
|
1127
1126
|
return 0;
|
|
1128
1127
|
}
|
|
1129
1128
|
throw error;
|
|
1130
1129
|
}
|
|
1131
1130
|
});
|
|
1132
1131
|
}
|
|
1133
|
-
|
|
1134
|
-
fileExists(filePath) {
|
|
1132
|
+
fileExists(fileKey) {
|
|
1135
1133
|
return __async(this, null, function* () {
|
|
1136
1134
|
var _a2;
|
|
1137
1135
|
try {
|
|
1138
|
-
const normalizedKey = getNormalizedPath(
|
|
1136
|
+
const normalizedKey = getNormalizedPath(fileKey);
|
|
1139
1137
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1140
1138
|
const command = new import_client_s34.HeadObjectCommand({ Bucket: this.bucket, Key: normalizedKey });
|
|
1141
1139
|
yield this.execute(command);
|
|
@@ -1148,10 +1146,9 @@ var S3File = class extends S3Directory {
|
|
|
1148
1146
|
}
|
|
1149
1147
|
});
|
|
1150
1148
|
}
|
|
1151
|
-
|
|
1152
|
-
fileContent(filePath, format = "buffer") {
|
|
1149
|
+
fileContent(fileKey, format = "buffer") {
|
|
1153
1150
|
return __async(this, null, function* () {
|
|
1154
|
-
let normalizedKey = getNormalizedPath(
|
|
1151
|
+
let normalizedKey = getNormalizedPath(fileKey);
|
|
1155
1152
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1156
1153
|
const command = new import_client_s34.GetObjectCommand({ Bucket: this.bucket, Key: normalizedKey });
|
|
1157
1154
|
const result = yield this.execute(command);
|
|
@@ -1182,18 +1179,33 @@ var S3File = class extends S3Directory {
|
|
|
1182
1179
|
return buffer;
|
|
1183
1180
|
});
|
|
1184
1181
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1182
|
+
uploadFileContent(_0, _1) {
|
|
1183
|
+
return __async(this, arguments, function* (fileKey, fileData, {
|
|
1184
|
+
acl = "private" /* private */,
|
|
1185
|
+
version = "1.0.0",
|
|
1186
|
+
prettier = true
|
|
1187
|
+
} = {}) {
|
|
1188
|
+
const normalizedKey = getNormalizedPath(fileKey);
|
|
1189
1189
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1190
|
+
let body;
|
|
1191
|
+
if (import_buffer.Buffer.isBuffer(fileData)) {
|
|
1192
|
+
body = fileData;
|
|
1193
|
+
} else if (fileData instanceof Uint8Array) {
|
|
1194
|
+
body = fileData;
|
|
1195
|
+
} else if (fileData instanceof import_node_stream.Readable) {
|
|
1196
|
+
body = fileData;
|
|
1197
|
+
} else if (typeof fileData === "string") {
|
|
1198
|
+
body = fileData;
|
|
1199
|
+
} else {
|
|
1200
|
+
body = prettier ? JSON.stringify(fileData, null, 2) : JSON.stringify(fileData);
|
|
1201
|
+
}
|
|
1190
1202
|
const upload = new import_lib_storage.Upload({
|
|
1191
1203
|
client: this.s3Client,
|
|
1192
1204
|
params: {
|
|
1193
1205
|
Bucket: this.bucket,
|
|
1194
1206
|
ACL: acl,
|
|
1195
1207
|
Key: normalizedKey,
|
|
1196
|
-
Body:
|
|
1208
|
+
Body: body,
|
|
1197
1209
|
Tagging: `version=${version}`
|
|
1198
1210
|
}
|
|
1199
1211
|
});
|
|
@@ -1206,10 +1218,9 @@ var S3File = class extends S3Directory {
|
|
|
1206
1218
|
};
|
|
1207
1219
|
});
|
|
1208
1220
|
}
|
|
1209
|
-
|
|
1210
|
-
deleteFile(filePath) {
|
|
1221
|
+
deleteFile(fileKey) {
|
|
1211
1222
|
return __async(this, null, function* () {
|
|
1212
|
-
const normalizedKey = getNormalizedPath(
|
|
1223
|
+
const normalizedKey = getNormalizedPath(fileKey);
|
|
1213
1224
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1214
1225
|
const command = new import_client_s34.DeleteObjectCommand({ Bucket: this.bucket, Key: normalizedKey });
|
|
1215
1226
|
return yield this.execute(command);
|
|
@@ -1224,24 +1235,24 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1224
1235
|
var _b = _a2, { maxUploadFileSizeRestriction = "10GB" } = _b, props = __objRest(_b, ["maxUploadFileSizeRestriction"]);
|
|
1225
1236
|
super(props);
|
|
1226
1237
|
__publicField(this, "maxUploadFileSizeRestriction");
|
|
1227
|
-
|
|
1228
|
-
__publicField(this, "getImageFileViewCtrl", ({
|
|
1238
|
+
__publicField(this, "streamImageFileCtrl", ({
|
|
1229
1239
|
fileKey: _fileKey,
|
|
1230
1240
|
queryField = "file",
|
|
1231
|
-
|
|
1241
|
+
paramsField = "file",
|
|
1242
|
+
headerField = "x-fileKey",
|
|
1232
1243
|
cachingAgeSeconds = "1y"
|
|
1233
1244
|
} = {}) => {
|
|
1234
1245
|
return (req, res, next) => __async(this, null, function* () {
|
|
1235
|
-
var _a2, _b, _c, _d, _e, _f;
|
|
1236
|
-
let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[
|
|
1246
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
1247
|
+
let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[paramsField]) ? decodeURIComponent((_b = req.params) == null ? void 0 : _b[paramsField]) : void 0) || (((_c = req.query) == null ? void 0 : _c[queryField]) ? decodeURIComponent((_d = req.query) == null ? void 0 : _d[queryField]) : void 0) || (((_e = req.headers) == null ? void 0 : _e[headerField]) ? decodeURIComponent((_f = req.headers) == null ? void 0 : _f[headerField]) : void 0);
|
|
1237
1248
|
if (!fileKey || fileKey === "/") {
|
|
1238
|
-
(
|
|
1239
|
-
next("image fileKey is required");
|
|
1249
|
+
(_g = this.logger) == null ? void 0 : _g.warn(req.id, "image fileKey is required");
|
|
1250
|
+
next(Error("image fileKey is required"));
|
|
1240
1251
|
return;
|
|
1241
1252
|
}
|
|
1242
1253
|
try {
|
|
1243
1254
|
const imageBuffer = yield this.fileContent(fileKey, "buffer");
|
|
1244
|
-
const ext = import_pathe2.
|
|
1255
|
+
const ext = (0, import_pathe2.extname)(fileKey).slice(1).toLowerCase();
|
|
1245
1256
|
const mimeTypeMap = {
|
|
1246
1257
|
jpg: "image/jpeg",
|
|
1247
1258
|
jpeg: "image/jpeg",
|
|
@@ -1258,31 +1269,31 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1258
1269
|
if (cachingAge) res.setHeader("Cache-Control", `public, max-age=${cachingAge}`);
|
|
1259
1270
|
res.status(200).send(imageBuffer);
|
|
1260
1271
|
} catch (error) {
|
|
1261
|
-
(
|
|
1272
|
+
(_h = this.logger) == null ? void 0 : _h.warn(req.id, "image fileKey not found", __spreadValues({
|
|
1262
1273
|
fileKey
|
|
1263
1274
|
}, this.localstack && { localstack: this.localstack }));
|
|
1264
|
-
next(`Failed to retrieve image file: ${error.message}`);
|
|
1275
|
+
next(Error(`Failed to retrieve image file: ${error.message}`));
|
|
1265
1276
|
}
|
|
1266
1277
|
});
|
|
1267
1278
|
});
|
|
1268
|
-
|
|
1269
|
-
__publicField(this, "getPdfFileViewCtrl", ({
|
|
1279
|
+
__publicField(this, "streamPdfFileCtrl", ({
|
|
1270
1280
|
fileKey: _fileKey,
|
|
1271
1281
|
queryField = "file",
|
|
1272
|
-
|
|
1282
|
+
paramsField = "file",
|
|
1283
|
+
headerField = "x-fileKey",
|
|
1273
1284
|
cachingAgeSeconds = "1y"
|
|
1274
1285
|
} = {}) => {
|
|
1275
1286
|
return (req, res, next) => __async(this, null, function* () {
|
|
1276
|
-
var _a2, _b, _c, _d, _e, _f;
|
|
1277
|
-
let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[
|
|
1287
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
1288
|
+
let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[paramsField]) ? decodeURIComponent((_b = req.params) == null ? void 0 : _b[paramsField]) : void 0) || (((_c = req.query) == null ? void 0 : _c[queryField]) ? decodeURIComponent((_d = req.query) == null ? void 0 : _d[queryField]) : void 0) || (((_e = req.headers) == null ? void 0 : _e[headerField]) ? decodeURIComponent((_f = req.headers) == null ? void 0 : _f[headerField]) : void 0);
|
|
1278
1289
|
if (!fileKey) {
|
|
1279
|
-
(
|
|
1280
|
-
next("pdf fileKey is required");
|
|
1290
|
+
(_g = this.logger) == null ? void 0 : _g.warn(req.id, "pdf fileKey is required");
|
|
1291
|
+
next(Error("pdf fileKey is required"));
|
|
1281
1292
|
return;
|
|
1282
1293
|
}
|
|
1283
1294
|
try {
|
|
1284
1295
|
const fileBuffer = yield this.fileContent(fileKey, "buffer");
|
|
1285
|
-
const ext = import_pathe2.
|
|
1296
|
+
const ext = (0, import_pathe2.extname)(fileKey).slice(1).toLowerCase();
|
|
1286
1297
|
const mimeTypeMap = {
|
|
1287
1298
|
pdf: "application/pdf",
|
|
1288
1299
|
txt: "text/plain",
|
|
@@ -1294,17 +1305,18 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1294
1305
|
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
1295
1306
|
};
|
|
1296
1307
|
const contentType = mimeTypeMap[ext] || "application/octet-stream";
|
|
1308
|
+
const filename = (0, import_pathe2.basename)(fileKey);
|
|
1297
1309
|
res.setHeader("Content-Type", contentType);
|
|
1298
|
-
res.setHeader("Content-Disposition", `inline; filename="${
|
|
1310
|
+
res.setHeader("Content-Disposition", `inline; filename="${encodeURIComponent(filename)}"`);
|
|
1299
1311
|
res.setHeader("Content-Length", fileBuffer.length);
|
|
1300
1312
|
const cachingAge = !cachingAgeSeconds || typeof cachingAgeSeconds === "number" ? cachingAgeSeconds : getTotalSeconds(cachingAgeSeconds);
|
|
1301
1313
|
res.setHeader("Cache-Control", `public, max-age=${cachingAge}`);
|
|
1302
1314
|
res.status(200).send(fileBuffer);
|
|
1303
1315
|
} catch (error) {
|
|
1304
|
-
(
|
|
1316
|
+
(_h = this.logger) == null ? void 0 : _h.warn(req.id, "pdf fileKey not found", __spreadValues({
|
|
1305
1317
|
fileKey
|
|
1306
1318
|
}, this.localstack && { localstack: this.localstack }));
|
|
1307
|
-
next(`Failed to retrieve pdf file: ${error.message}`);
|
|
1319
|
+
next(Error(`Failed to retrieve pdf file: ${error.message}`));
|
|
1308
1320
|
}
|
|
1309
1321
|
});
|
|
1310
1322
|
});
|
|
@@ -1333,7 +1345,6 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1333
1345
|
return response.Body;
|
|
1334
1346
|
});
|
|
1335
1347
|
}
|
|
1336
|
-
// todo: LOCALSTACK SANITY CHECKED - WORKING WELL, DON'T TOUCH!
|
|
1337
1348
|
streamVideoFile(_0) {
|
|
1338
1349
|
return __async(this, arguments, function* (fileKey, {
|
|
1339
1350
|
Range,
|
|
@@ -1362,7 +1373,7 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1362
1373
|
}
|
|
1363
1374
|
};
|
|
1364
1375
|
} catch (error) {
|
|
1365
|
-
(_a2 = this.logger) == null ? void 0 : _a2.warn(this.reqId, "
|
|
1376
|
+
(_a2 = this.logger) == null ? void 0 : _a2.warn(this.reqId, "streamVideoFile error", {
|
|
1366
1377
|
Bucket: this.bucket,
|
|
1367
1378
|
fileKey: normalizedKey,
|
|
1368
1379
|
Range,
|
|
@@ -1372,29 +1383,39 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1372
1383
|
}
|
|
1373
1384
|
});
|
|
1374
1385
|
}
|
|
1375
|
-
|
|
1376
|
-
getStreamVideoFileCtrl(_0) {
|
|
1386
|
+
streamVideoFileCtrl() {
|
|
1377
1387
|
return __async(this, arguments, function* ({
|
|
1378
|
-
fileKey,
|
|
1379
1388
|
allowedWhitelist,
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1389
|
+
bufferMB = 5,
|
|
1390
|
+
contentType,
|
|
1391
|
+
fileKey: _fileKey,
|
|
1392
|
+
queryField = "file",
|
|
1393
|
+
paramsField = "file",
|
|
1394
|
+
headerField = "x-fileKey",
|
|
1395
|
+
streamTimeoutMS = 3e4
|
|
1396
|
+
} = {}) {
|
|
1384
1397
|
return (req, res, next) => __async(this, null, function* () {
|
|
1385
|
-
var _a2, _b, _c, _d, _e, _f;
|
|
1398
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
1399
|
+
let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[paramsField]) ? (_b = req.params) == null ? void 0 : _b[paramsField] : void 0) || (((_c = req.query) == null ? void 0 : _c[queryField]) ? (_d = req.query) == null ? void 0 : _d[queryField] : void 0);
|
|
1400
|
+
((_e = req.headers) == null ? void 0 : _e[headerField]) ? (_f = req.headers) == null ? void 0 : _f[headerField] : void 0;
|
|
1401
|
+
if (!fileKey || fileKey === "/") {
|
|
1402
|
+
(_g = this.logger) == null ? void 0 : _g.warn(req.id, "fileKey video stream is required");
|
|
1403
|
+
next(Error("fileKey video stream is required"));
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1386
1406
|
let normalizedKey = getNormalizedPath(fileKey);
|
|
1387
1407
|
if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
|
|
1388
|
-
const isExists = yield this.fileExists(normalizedKey);
|
|
1389
|
-
const fileSize = yield this.sizeOf(normalizedKey);
|
|
1390
1408
|
let Range;
|
|
1391
|
-
|
|
1392
|
-
next(Error(`File does not exist: "${normalizedKey}"`));
|
|
1393
|
-
return;
|
|
1394
|
-
}
|
|
1409
|
+
let fileSize;
|
|
1395
1410
|
try {
|
|
1411
|
+
const fileInfo = yield this.fileInfo(normalizedKey);
|
|
1412
|
+
if (!fileInfo) {
|
|
1413
|
+
next(Error(`File does not exist: "${normalizedKey}"`));
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
fileSize = getUnitBytes(fileInfo.ContentLength);
|
|
1396
1417
|
if (req.method === "HEAD") {
|
|
1397
|
-
res.setHeader("Content-Type",
|
|
1418
|
+
res.setHeader("Content-Type", fileInfo.ContentType);
|
|
1398
1419
|
res.setHeader("Accept-Ranges", "bytes");
|
|
1399
1420
|
if (fileSize) res.setHeader("Content-Length", String(fileSize));
|
|
1400
1421
|
return res.status(200).end();
|
|
@@ -1427,14 +1448,14 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1427
1448
|
abortSignal: abort.signal
|
|
1428
1449
|
});
|
|
1429
1450
|
const { body, meta } = result;
|
|
1430
|
-
const origin = Array.isArray(allowedWhitelist) ? allowedWhitelist.includes((
|
|
1451
|
+
const origin = Array.isArray(allowedWhitelist) ? allowedWhitelist.includes((_h = req.headers.origin) != null ? _h : "") ? req.headers.origin : void 0 : allowedWhitelist;
|
|
1431
1452
|
if (origin) {
|
|
1432
1453
|
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
1433
1454
|
res.setHeader("Vary", "Origin");
|
|
1434
1455
|
}
|
|
1435
|
-
const finalContentType = contentType.startsWith("video/") ? contentType : `video/${contentType}`;
|
|
1436
|
-
res.setHeader("Content-Type", (
|
|
1437
|
-
res.setHeader("Accept-Ranges", (
|
|
1456
|
+
const finalContentType = (contentType == null ? void 0 : contentType.startsWith("video/")) ? contentType : `video/${contentType || "mp4"}`;
|
|
1457
|
+
res.setHeader("Content-Type", (_i = meta.contentType) != null ? _i : finalContentType);
|
|
1458
|
+
res.setHeader("Accept-Ranges", (_j = meta.acceptRanges) != null ? _j : "bytes");
|
|
1438
1459
|
if (Range && meta.contentRange) {
|
|
1439
1460
|
res.status(206);
|
|
1440
1461
|
res.setHeader("Content-Range", meta.contentRange);
|
|
@@ -1465,11 +1486,11 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1465
1486
|
return;
|
|
1466
1487
|
}
|
|
1467
1488
|
if (!res.headersSent) {
|
|
1468
|
-
(
|
|
1469
|
-
error: (
|
|
1489
|
+
(_m = this.logger) == null ? void 0 : _m.warn(req.id, "caught exception in stream controller", {
|
|
1490
|
+
error: (_k = error == null ? void 0 : error.message) != null ? _k : String(error),
|
|
1470
1491
|
key: fileKey,
|
|
1471
1492
|
url: req.originalUrl,
|
|
1472
|
-
userId: (
|
|
1493
|
+
userId: (_l = req.user) == null ? void 0 : _l._id
|
|
1473
1494
|
});
|
|
1474
1495
|
next(error);
|
|
1475
1496
|
return;
|
|
@@ -1485,14 +1506,23 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1485
1506
|
});
|
|
1486
1507
|
});
|
|
1487
1508
|
}
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1509
|
+
streamFileCtrl() {
|
|
1510
|
+
return __async(this, arguments, function* ({
|
|
1511
|
+
fileKey: _fileKey,
|
|
1491
1512
|
filename,
|
|
1492
|
-
forDownloading = false
|
|
1513
|
+
forDownloading = false,
|
|
1514
|
+
paramsField = "file",
|
|
1515
|
+
queryField = "file",
|
|
1516
|
+
headerField = "x-fileKey"
|
|
1493
1517
|
} = {}) {
|
|
1494
1518
|
return (req, res, next) => __async(this, null, function* () {
|
|
1495
|
-
var _a2, _b;
|
|
1519
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1520
|
+
let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[paramsField]) ? (_b = req.params) == null ? void 0 : _b[paramsField] : void 0) || (((_c = req.query) == null ? void 0 : _c[queryField]) ? (_d = req.query) == null ? void 0 : _d[queryField] : void 0) || (((_e = req.headers) == null ? void 0 : _e[headerField]) ? decodeURIComponent((_f = req.headers) == null ? void 0 : _f[headerField]) : void 0);
|
|
1521
|
+
if (!fileKey || fileKey === "/") {
|
|
1522
|
+
(_g = this.logger) == null ? void 0 : _g.warn(req.id, "fileKey stream is required");
|
|
1523
|
+
next(Error("fileKey stream is required"));
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1496
1526
|
const abort = new AbortController();
|
|
1497
1527
|
let stream = null;
|
|
1498
1528
|
const onClose = () => {
|
|
@@ -1523,7 +1553,7 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1523
1553
|
const fileName = filename || normalizedKey.split("/").pop() || "download";
|
|
1524
1554
|
res.setHeader("Content-Type", fileInfo.ContentType || "application/octet-stream");
|
|
1525
1555
|
if (forDownloading) {
|
|
1526
|
-
res.setHeader("Content-Disposition", `attachment; filename="${fileName}"`);
|
|
1556
|
+
res.setHeader("Content-Disposition", `attachment; filename="${encodeURIComponent(fileName)}"`);
|
|
1527
1557
|
}
|
|
1528
1558
|
if (fileInfo.ContentLength) {
|
|
1529
1559
|
res.setHeader("Content-Length", String(fileInfo.ContentLength));
|
|
@@ -1544,13 +1574,13 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1544
1574
|
} catch (error) {
|
|
1545
1575
|
abort.abort();
|
|
1546
1576
|
if (stream) {
|
|
1547
|
-
(
|
|
1577
|
+
(_h = stream.destroy) == null ? void 0 : _h.call(stream);
|
|
1548
1578
|
}
|
|
1549
1579
|
const isBenignStreamError = (error == null ? void 0 : error.code) === "ERR_STREAM_PREMATURE_CLOSE" || (error == null ? void 0 : error.name) === "AbortError" || (error == null ? void 0 : error.code) === "ECONNRESET";
|
|
1550
1580
|
if (isBenignStreamError) {
|
|
1551
1581
|
return;
|
|
1552
1582
|
}
|
|
1553
|
-
(
|
|
1583
|
+
(_i = this.logger) == null ? void 0 : _i.error(this.reqId, "Failed to stream file", { fileKey: normalizedKey, error });
|
|
1554
1584
|
if (!res.headersSent) {
|
|
1555
1585
|
next(error);
|
|
1556
1586
|
} else if (!res.writableEnded) {
|
|
@@ -1565,17 +1595,26 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1565
1595
|
});
|
|
1566
1596
|
});
|
|
1567
1597
|
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1598
|
+
streamZipFileCtr() {
|
|
1599
|
+
return __async(this, arguments, function* ({
|
|
1600
|
+
fileKey: _fileKey,
|
|
1571
1601
|
filename: _filename,
|
|
1602
|
+
queryField = "file",
|
|
1603
|
+
paramsField = "file",
|
|
1604
|
+
headerField = "x-fileKey",
|
|
1572
1605
|
compressionLevel = 5
|
|
1573
1606
|
} = {}) {
|
|
1574
1607
|
return (req, res, next) => __async(this, null, function* () {
|
|
1575
|
-
var _a2, _b, _c, _d, _e;
|
|
1608
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
1576
1609
|
const abort = new AbortController();
|
|
1577
1610
|
const onClose = () => abort.abort();
|
|
1578
1611
|
try {
|
|
1612
|
+
let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[paramsField]) ? (_b = req.params) == null ? void 0 : _b[paramsField] : void 0) || (((_c = req.query) == null ? void 0 : _c[queryField]) ? (_d = req.query) == null ? void 0 : _d[queryField] : void 0) || (((_e = req.headers) == null ? void 0 : _e[headerField]) ? decodeURIComponent((_f = req.headers) == null ? void 0 : _f[headerField]) : void 0);
|
|
1613
|
+
if (!fileKey || fileKey === "/") {
|
|
1614
|
+
(_g = this.logger) == null ? void 0 : _g.warn(req.id, "fileKey video stream is required");
|
|
1615
|
+
next(Error("fileKey video stream is required"));
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1579
1618
|
const fileKeys = [].concat(fileKey).map((fileKey2) => getNormalizedPath(fileKey2)).filter((v) => v && v !== "/");
|
|
1580
1619
|
if (!fileKeys.length) {
|
|
1581
1620
|
throw new Error("No file keys provided");
|
|
@@ -1583,7 +1622,7 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1583
1622
|
let filename = _filename || (/* @__PURE__ */ new Date()).toISOString();
|
|
1584
1623
|
filename = filename.endsWith(".zip") ? filename : `${filename}.zip`;
|
|
1585
1624
|
req.once("close", onClose);
|
|
1586
|
-
(
|
|
1625
|
+
(_h = this.logger) == null ? void 0 : _h.info(this.reqId, "Starting parallel file download...", { fileCount: fileKeys.length });
|
|
1587
1626
|
const downloadPromises = fileKeys.map((fileKey2) => __async(this, null, function* () {
|
|
1588
1627
|
var _a3, _b2, _c2;
|
|
1589
1628
|
try {
|
|
@@ -1633,7 +1672,7 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1633
1672
|
}
|
|
1634
1673
|
return;
|
|
1635
1674
|
}
|
|
1636
|
-
(
|
|
1675
|
+
(_i = this.logger) == null ? void 0 : _i.info(this.reqId, "All files downloaded, measuring zip size...", {
|
|
1637
1676
|
fileCount: fileBuffers.length,
|
|
1638
1677
|
totalSizeMB: (fileBuffers.reduce((sum, f) => sum + f.buffer.length, 0) / (1024 * 1024)).toFixed(2)
|
|
1639
1678
|
});
|
|
@@ -1651,13 +1690,13 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1651
1690
|
req.off("close", onClose);
|
|
1652
1691
|
return;
|
|
1653
1692
|
}
|
|
1654
|
-
(
|
|
1693
|
+
(_j = this.logger) == null ? void 0 : _j.info(this.reqId, "Zip size calculated", {
|
|
1655
1694
|
actualZipSize,
|
|
1656
1695
|
sizeMB: (actualZipSize / (1024 * 1024)).toFixed(2)
|
|
1657
1696
|
});
|
|
1658
1697
|
const actualArchive = (0, import_archiver.default)("zip", { zlib: { level: compressionLevel } });
|
|
1659
1698
|
res.setHeader("Content-Type", "application/zip");
|
|
1660
|
-
res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);
|
|
1699
|
+
res.setHeader("Content-Disposition", `attachment; filename="${encodeURIComponent(filename)}"`);
|
|
1661
1700
|
res.setHeader("Content-Length", String(actualZipSize));
|
|
1662
1701
|
res.setHeader("Access-Control-Expose-Headers", "Content-Type, Content-Disposition, Content-Length");
|
|
1663
1702
|
actualArchive.on("error", (err) => {
|
|
@@ -1674,7 +1713,7 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1674
1713
|
actualArchive.append(file.buffer, { name: file.name });
|
|
1675
1714
|
}
|
|
1676
1715
|
yield actualArchive.finalize();
|
|
1677
|
-
(
|
|
1716
|
+
(_k = this.logger) == null ? void 0 : _k.info(this.reqId, "Zip download completed", {
|
|
1678
1717
|
fileCount: fileBuffers.length,
|
|
1679
1718
|
totalSize: actualZipSize
|
|
1680
1719
|
});
|
|
@@ -1686,7 +1725,7 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1686
1725
|
return;
|
|
1687
1726
|
}
|
|
1688
1727
|
if (!res.headersSent) {
|
|
1689
|
-
(
|
|
1728
|
+
(_l = this.logger) == null ? void 0 : _l.error(this.reqId, "Failed to create zip archive", { error });
|
|
1690
1729
|
next(error);
|
|
1691
1730
|
} else if (!res.writableEnded) {
|
|
1692
1731
|
try {
|
|
@@ -1703,13 +1742,13 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1703
1742
|
static fileFilter(types, fileExt) {
|
|
1704
1743
|
const fileTypesChecker = (fileExt == null ? void 0 : fileExt.length) ? new RegExp(`\\.(${fileExt.join("|")})$`, "i") : void 0;
|
|
1705
1744
|
return function(_req, file, cb) {
|
|
1706
|
-
const fileExtension = import_pathe2.
|
|
1707
|
-
const
|
|
1745
|
+
const fileExtension = (0, import_pathe2.extname)(file.originalname).substring(1);
|
|
1746
|
+
const ext = fileTypesChecker ? fileTypesChecker.test(`.${fileExtension}`) : true;
|
|
1708
1747
|
const mimeType = (types == null ? void 0 : types.length) ? types.some((type) => file.mimetype.startsWith(`${type}/`)) : true;
|
|
1709
|
-
if (mimeType &&
|
|
1748
|
+
if (mimeType && ext) {
|
|
1710
1749
|
return cb(null, true);
|
|
1711
1750
|
}
|
|
1712
|
-
const errorMsg = !
|
|
1751
|
+
const errorMsg = !ext ? `Upload File Ext Error: Allowed extensions: [${fileExt == null ? void 0 : fileExt.join(", ")}]. Got: ${fileExtension}` : `Upload File Type Error: Allowed types: [${types == null ? void 0 : types.join(", ")}]. Got: ${file.mimetype}`;
|
|
1713
1752
|
return cb(new Error(errorMsg));
|
|
1714
1753
|
};
|
|
1715
1754
|
}
|
|
@@ -1764,7 +1803,7 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1764
1803
|
* Middleware for uploading a single file
|
|
1765
1804
|
* Adds the uploaded file info to req.s3File
|
|
1766
1805
|
*/
|
|
1767
|
-
|
|
1806
|
+
uploadSingleFileMW(fieldName, directoryPath, options = {}) {
|
|
1768
1807
|
var _a2;
|
|
1769
1808
|
let normalizedPath = getNormalizedPath(directoryPath);
|
|
1770
1809
|
if (normalizedPath !== "/" && directoryPath !== "" && directoryPath !== void 0) normalizedPath += "/";
|
|
@@ -1796,13 +1835,14 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1796
1835
|
* Middleware for uploading multiple files with the same field name
|
|
1797
1836
|
* Adds the uploaded files info to req.s3Files
|
|
1798
1837
|
*/
|
|
1799
|
-
|
|
1838
|
+
uploadMultipleFilesMW(fieldName, directoryPath, _c = {}) {
|
|
1839
|
+
var _d = _c, { maxFilesCount } = _d, options = __objRest(_d, ["maxFilesCount"]);
|
|
1800
1840
|
let normalizedPath = getNormalizedPath(directoryPath);
|
|
1801
1841
|
if (normalizedPath !== "/" && directoryPath !== "" && directoryPath !== void 0) normalizedPath += "/";
|
|
1802
1842
|
else normalizedPath = "";
|
|
1803
1843
|
const upload = this.getUploadFileMW(normalizedPath, options);
|
|
1804
1844
|
return (req, res, next) => {
|
|
1805
|
-
const mw = upload.array(fieldName,
|
|
1845
|
+
const mw = upload.array(fieldName, maxFilesCount || void 0);
|
|
1806
1846
|
mw(req, res, (err) => {
|
|
1807
1847
|
var _a2, _b;
|
|
1808
1848
|
if (err) {
|
|
@@ -1825,7 +1865,7 @@ var S3Stream = class _S3Stream extends S3File {
|
|
|
1825
1865
|
* Middleware for uploading any files (mixed field names)
|
|
1826
1866
|
* Adds the uploaded files info to req.s3AllFiles
|
|
1827
1867
|
*/
|
|
1828
|
-
|
|
1868
|
+
uploadAnyFilesMW(directoryPath, maxCount, options = {}) {
|
|
1829
1869
|
let normalizedPath = getNormalizedPath(directoryPath);
|
|
1830
1870
|
if (normalizedPath !== "/" && normalizedPath !== "" && directoryPath !== void 0) normalizedPath += "/";
|
|
1831
1871
|
else normalizedPath = "";
|
|
@@ -1917,7 +1957,6 @@ var S3LocalstackUtil = class extends S3Util {
|
|
|
1917
1957
|
constructor(props) {
|
|
1918
1958
|
super(__spreadProps(__spreadValues({}, props), { localstack: true }));
|
|
1919
1959
|
}
|
|
1920
|
-
// todo: checked!
|
|
1921
1960
|
directoryList(directoryPath) {
|
|
1922
1961
|
return __async(this, null, function* () {
|
|
1923
1962
|
var _a2;
|
|
@@ -1953,7 +1992,6 @@ var S3LocalstackUtil = class extends S3Util {
|
|
|
1953
1992
|
return { directories, files };
|
|
1954
1993
|
});
|
|
1955
1994
|
}
|
|
1956
|
-
// todo: checked!
|
|
1957
1995
|
directoryListPaginated(_0) {
|
|
1958
1996
|
return __async(this, arguments, function* (directoryPath, {
|
|
1959
1997
|
pageSize = 100,
|