@hdriel/aws-utils 1.1.7 → 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/dist/index.js CHANGED
@@ -232,7 +232,7 @@ var LambdaUtil = class {
232
232
  import { ListObjectsV2Command as ListObjectsV2Command4 } from "@aws-sdk/client-s3";
233
233
 
234
234
  // src/aws/s3/s3-stream.ts
235
- import path from "pathe";
235
+ import { basename as basename2, extname } from "pathe";
236
236
  import { pipeline } from "stream";
237
237
  import { promisify } from "util";
238
238
  import { Buffer as Buffer3 } from "buffer";
@@ -282,10 +282,27 @@ var getTotalSeconds = (msValue) => {
282
282
  const value = ms(msValue);
283
283
  return value / 1e3;
284
284
  };
285
+ var getUnitBytes = (bytes2, unit) => {
286
+ switch (unit == null ? void 0 : unit.toUpperCase()) {
287
+ case "KB":
288
+ return bytes2 / 1024;
289
+ case "MB":
290
+ return bytes2 / __pow(1024, 2);
291
+ case "GB":
292
+ return bytes2 / __pow(1024, 3);
293
+ case "TB":
294
+ return bytes2 / __pow(1024, 4);
295
+ case "PB":
296
+ return bytes2 / __pow(1024, 5);
297
+ case "B":
298
+ default:
299
+ return bytes2;
300
+ }
301
+ };
285
302
 
286
303
  // src/aws/s3/s3-file.ts
287
304
  import { Buffer as Buffer2 } from "buffer";
288
- import "stream";
305
+ import { Readable } from "stream";
289
306
  import ms2 from "ms";
290
307
  import { basename } from "pathe";
291
308
  import { Upload } from "@aws-sdk/lib-storage";
@@ -670,7 +687,6 @@ var S3Directory = class extends S3Bucket {
670
687
  constructor(props) {
671
688
  super(props);
672
689
  }
673
- // todo: checked!
674
690
  directoryExists(directoryPath) {
675
691
  return __async(this, null, function* () {
676
692
  var _a2;
@@ -688,7 +704,6 @@ var S3Directory = class extends S3Bucket {
688
704
  }
689
705
  });
690
706
  }
691
- // todo: checked!
692
707
  createDirectory(directoryPath) {
693
708
  return __async(this, null, function* () {
694
709
  let normalizedPath = getNormalizedPath(directoryPath);
@@ -698,7 +713,6 @@ var S3Directory = class extends S3Bucket {
698
713
  return result;
699
714
  });
700
715
  }
701
- // todo: checked!
702
716
  deleteDirectory(directoryPath) {
703
717
  return __async(this, null, function* () {
704
718
  var _a2, _b, _c, _d, _e, _f, _g;
@@ -768,7 +782,6 @@ var S3Directory = class extends S3Bucket {
768
782
  };
769
783
  });
770
784
  }
771
- // todo: checked!
772
785
  directoryList(directoryPath) {
773
786
  return __async(this, null, function* () {
774
787
  var _a2;
@@ -825,7 +838,6 @@ var S3Directory = class extends S3Bucket {
825
838
  return { directories, files };
826
839
  });
827
840
  }
828
- // todo: checked!
829
841
  directoryListPaginated(_0) {
830
842
  return __async(this, arguments, function* (directoryPath, {
831
843
  pageSize = 100,
@@ -944,9 +956,9 @@ var S3File = class extends S3Directory {
944
956
  constructor(props) {
945
957
  super(props);
946
958
  }
947
- fileInfo(filePath) {
959
+ fileInfo(fileKey) {
948
960
  return __async(this, null, function* () {
949
- const normalizedKey = getNormalizedPath(filePath);
961
+ const normalizedKey = getNormalizedPath(fileKey);
950
962
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
951
963
  const command = new HeadObjectCommand2({ Bucket: this.bucket, Key: normalizedKey });
952
964
  const result = yield this.execute(command);
@@ -985,7 +997,6 @@ var S3File = class extends S3Directory {
985
997
  return files;
986
998
  });
987
999
  }
988
- // todo: checked!
989
1000
  fileListPaginated(_0) {
990
1001
  return __async(this, arguments, function* (directoryPath, {
991
1002
  fileNamePrefix,
@@ -1041,14 +1052,13 @@ var S3File = class extends S3Directory {
1041
1052
  };
1042
1053
  });
1043
1054
  }
1044
- // todo: checked!
1045
- taggingFile(filePath, tag) {
1055
+ taggingFile(fileKey, tag) {
1046
1056
  return __async(this, null, function* () {
1047
1057
  var _a2;
1048
1058
  let normalizedKey = "";
1049
1059
  const tags = [].concat(tag);
1050
1060
  try {
1051
- normalizedKey = getNormalizedPath(filePath);
1061
+ normalizedKey = getNormalizedPath(fileKey);
1052
1062
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1053
1063
  const command = new PutObjectTaggingCommand({
1054
1064
  Bucket: this.bucket,
@@ -1063,11 +1073,10 @@ var S3File = class extends S3Directory {
1063
1073
  }
1064
1074
  });
1065
1075
  }
1066
- // todo: checked!
1067
- fileVersion(filePath) {
1076
+ fileVersion(fileKey) {
1068
1077
  return __async(this, null, function* () {
1069
1078
  var _a2, _b;
1070
- const normalizedKey = getNormalizedPath(filePath);
1079
+ const normalizedKey = getNormalizedPath(fileKey);
1071
1080
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1072
1081
  const command = new GetObjectTaggingCommand({ Bucket: this.bucket, Key: normalizedKey });
1073
1082
  const result = yield this.execute(command);
@@ -1075,11 +1084,10 @@ var S3File = class extends S3Directory {
1075
1084
  return (_b = tag == null ? void 0 : tag.Value) != null ? _b : "";
1076
1085
  });
1077
1086
  }
1078
- // todo: checked!
1079
- fileUrl(filePath, expiresIn = "15m") {
1087
+ fileUrl(fileKey, expiresIn = "15m") {
1080
1088
  return __async(this, null, function* () {
1081
1089
  var _a2;
1082
- let normalizedKey = getNormalizedPath(filePath);
1090
+ let normalizedKey = getNormalizedPath(fileKey);
1083
1091
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1084
1092
  const expiresInSeconds = typeof expiresIn === "number" ? expiresIn : ms2(expiresIn) / 1e3;
1085
1093
  const command = new GetObjectCommand({ Bucket: this.bucket, Key: normalizedKey });
@@ -1087,44 +1095,34 @@ var S3File = class extends S3Directory {
1087
1095
  expiresIn: expiresInSeconds
1088
1096
  // is using 3600 it's will expire in 1 hour (default is 900 seconds = 15 minutes)
1089
1097
  });
1090
- (_a2 = this.logger) == null ? void 0 : _a2.info(null, "generate signed file url", { url, filePath: normalizedKey, expiresIn });
1098
+ (_a2 = this.logger) == null ? void 0 : _a2.info(null, "generate signed file url", { url, fileKey: normalizedKey, expiresIn });
1091
1099
  return url;
1092
1100
  });
1093
1101
  }
1094
- sizeOf(filePath, unit = "bytes") {
1102
+ sizeOf(fileKey, unit) {
1095
1103
  return __async(this, null, function* () {
1096
1104
  var _a2, _b, _c;
1097
- const normalizedKey = getNormalizedPath(filePath);
1105
+ const normalizedKey = getNormalizedPath(fileKey);
1098
1106
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1099
1107
  try {
1100
1108
  const command = new HeadObjectCommand2({ Bucket: this.bucket, Key: normalizedKey });
1101
1109
  const headObject = yield this.execute(command);
1102
1110
  const bytes2 = (_a2 = headObject.ContentLength) != null ? _a2 : 0;
1103
- switch (unit) {
1104
- case "KB":
1105
- return bytes2 / 1024;
1106
- case "MB":
1107
- return bytes2 / (1024 * 1024);
1108
- case "GB":
1109
- return bytes2 / (1024 * 1024 * 1024);
1110
- default:
1111
- return bytes2;
1112
- }
1111
+ return getUnitBytes(bytes2, unit);
1113
1112
  } catch (error) {
1114
1113
  if (error.name === "NotFound" || ((_b = error.$metadata) == null ? void 0 : _b.httpStatusCode) === 404) {
1115
- (_c = this.logger) == null ? void 0 : _c.warn(this.reqId, "File not found", { filePath: normalizedKey });
1114
+ (_c = this.logger) == null ? void 0 : _c.warn(this.reqId, "File not found", { fileKey: normalizedKey });
1116
1115
  return 0;
1117
1116
  }
1118
1117
  throw error;
1119
1118
  }
1120
1119
  });
1121
1120
  }
1122
- // todo: checked!
1123
- fileExists(filePath) {
1121
+ fileExists(fileKey) {
1124
1122
  return __async(this, null, function* () {
1125
1123
  var _a2;
1126
1124
  try {
1127
- const normalizedKey = getNormalizedPath(filePath);
1125
+ const normalizedKey = getNormalizedPath(fileKey);
1128
1126
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1129
1127
  const command = new HeadObjectCommand2({ Bucket: this.bucket, Key: normalizedKey });
1130
1128
  yield this.execute(command);
@@ -1137,10 +1135,9 @@ var S3File = class extends S3Directory {
1137
1135
  }
1138
1136
  });
1139
1137
  }
1140
- // todo: checked!
1141
- fileContent(filePath, format = "buffer") {
1138
+ fileContent(fileKey, format = "buffer") {
1142
1139
  return __async(this, null, function* () {
1143
- let normalizedKey = getNormalizedPath(filePath);
1140
+ let normalizedKey = getNormalizedPath(fileKey);
1144
1141
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1145
1142
  const command = new GetObjectCommand({ Bucket: this.bucket, Key: normalizedKey });
1146
1143
  const result = yield this.execute(command);
@@ -1171,18 +1168,33 @@ var S3File = class extends S3Directory {
1171
1168
  return buffer;
1172
1169
  });
1173
1170
  }
1174
- // todo: checked!
1175
- uploadFile(_0, _1) {
1176
- return __async(this, arguments, function* (filePath, fileData, acl = "private" /* private */, version = "1.0.0") {
1177
- const normalizedKey = getNormalizedPath(filePath);
1171
+ uploadFileContent(_0, _1) {
1172
+ return __async(this, arguments, function* (fileKey, fileData, {
1173
+ acl = "private" /* private */,
1174
+ version = "1.0.0",
1175
+ prettier = true
1176
+ } = {}) {
1177
+ const normalizedKey = getNormalizedPath(fileKey);
1178
1178
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1179
+ let body;
1180
+ if (Buffer2.isBuffer(fileData)) {
1181
+ body = fileData;
1182
+ } else if (fileData instanceof Uint8Array) {
1183
+ body = fileData;
1184
+ } else if (fileData instanceof Readable) {
1185
+ body = fileData;
1186
+ } else if (typeof fileData === "string") {
1187
+ body = fileData;
1188
+ } else {
1189
+ body = prettier ? JSON.stringify(fileData, null, 2) : JSON.stringify(fileData);
1190
+ }
1179
1191
  const upload = new Upload({
1180
1192
  client: this.s3Client,
1181
1193
  params: {
1182
1194
  Bucket: this.bucket,
1183
1195
  ACL: acl,
1184
1196
  Key: normalizedKey,
1185
- Body: fileData,
1197
+ Body: body,
1186
1198
  Tagging: `version=${version}`
1187
1199
  }
1188
1200
  });
@@ -1195,10 +1207,9 @@ var S3File = class extends S3Directory {
1195
1207
  };
1196
1208
  });
1197
1209
  }
1198
- // todo: checked!
1199
- deleteFile(filePath) {
1210
+ deleteFile(fileKey) {
1200
1211
  return __async(this, null, function* () {
1201
- const normalizedKey = getNormalizedPath(filePath);
1212
+ const normalizedKey = getNormalizedPath(fileKey);
1202
1213
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1203
1214
  const command = new DeleteObjectCommand2({ Bucket: this.bucket, Key: normalizedKey });
1204
1215
  return yield this.execute(command);
@@ -1213,24 +1224,24 @@ var S3Stream = class _S3Stream extends S3File {
1213
1224
  var _b = _a2, { maxUploadFileSizeRestriction = "10GB" } = _b, props = __objRest(_b, ["maxUploadFileSizeRestriction"]);
1214
1225
  super(props);
1215
1226
  __publicField(this, "maxUploadFileSizeRestriction");
1216
- // todo: LOCALSTACK SANITY CHECKED - WORKING WELL, DON'T TOUCH!
1217
- __publicField(this, "getImageFileViewCtrl", ({
1227
+ __publicField(this, "streamImageFileCtrl", ({
1218
1228
  fileKey: _fileKey,
1219
1229
  queryField = "file",
1220
- paramField = "file",
1230
+ paramsField = "file",
1231
+ headerField = "x-fileKey",
1221
1232
  cachingAgeSeconds = "1y"
1222
1233
  } = {}) => {
1223
1234
  return (req, res, next) => __async(this, null, function* () {
1224
- var _a2, _b, _c, _d, _e, _f;
1225
- let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[paramField]) ? decodeURIComponent((_b = req.params) == null ? void 0 : _b[paramField]) : void 0) || (((_c = req.query) == null ? void 0 : _c[queryField]) ? decodeURIComponent((_d = req.query) == null ? void 0 : _d[queryField]) : void 0);
1235
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
1236
+ 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);
1226
1237
  if (!fileKey || fileKey === "/") {
1227
- (_e = this.logger) == null ? void 0 : _e.warn(req.id, "image fileKey is required");
1228
- next("image fileKey is required");
1238
+ (_g = this.logger) == null ? void 0 : _g.warn(req.id, "image fileKey is required");
1239
+ next(Error("image fileKey is required"));
1229
1240
  return;
1230
1241
  }
1231
1242
  try {
1232
1243
  const imageBuffer = yield this.fileContent(fileKey, "buffer");
1233
- const ext = path.extname(fileKey).slice(1).toLowerCase();
1244
+ const ext = extname(fileKey).slice(1).toLowerCase();
1234
1245
  const mimeTypeMap = {
1235
1246
  jpg: "image/jpeg",
1236
1247
  jpeg: "image/jpeg",
@@ -1247,31 +1258,31 @@ var S3Stream = class _S3Stream extends S3File {
1247
1258
  if (cachingAge) res.setHeader("Cache-Control", `public, max-age=${cachingAge}`);
1248
1259
  res.status(200).send(imageBuffer);
1249
1260
  } catch (error) {
1250
- (_f = this.logger) == null ? void 0 : _f.warn(req.id, "image fileKey not found", __spreadValues({
1261
+ (_h = this.logger) == null ? void 0 : _h.warn(req.id, "image fileKey not found", __spreadValues({
1251
1262
  fileKey
1252
1263
  }, this.localstack && { localstack: this.localstack }));
1253
- next(`Failed to retrieve image file: ${error.message}`);
1264
+ next(Error(`Failed to retrieve image file: ${error.message}`));
1254
1265
  }
1255
1266
  });
1256
1267
  });
1257
- // todo: LOCALSTACK SANITY CHECKED - WORKING WELL, DON'T TOUCH!
1258
- __publicField(this, "getPdfFileViewCtrl", ({
1268
+ __publicField(this, "streamPdfFileCtrl", ({
1259
1269
  fileKey: _fileKey,
1260
1270
  queryField = "file",
1261
- paramField = "file",
1271
+ paramsField = "file",
1272
+ headerField = "x-fileKey",
1262
1273
  cachingAgeSeconds = "1y"
1263
1274
  } = {}) => {
1264
1275
  return (req, res, next) => __async(this, null, function* () {
1265
- var _a2, _b, _c, _d, _e, _f;
1266
- let fileKey = _fileKey || (((_a2 = req.params) == null ? void 0 : _a2[paramField]) ? decodeURIComponent((_b = req.params) == null ? void 0 : _b[paramField]) : void 0) || (((_c = req.query) == null ? void 0 : _c[queryField]) ? decodeURIComponent((_d = req.query) == null ? void 0 : _d[queryField]) : void 0);
1276
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
1277
+ 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);
1267
1278
  if (!fileKey) {
1268
- (_e = this.logger) == null ? void 0 : _e.warn(req.id, "pdf fileKey is required");
1269
- next("pdf fileKey is required");
1279
+ (_g = this.logger) == null ? void 0 : _g.warn(req.id, "pdf fileKey is required");
1280
+ next(Error("pdf fileKey is required"));
1270
1281
  return;
1271
1282
  }
1272
1283
  try {
1273
1284
  const fileBuffer = yield this.fileContent(fileKey, "buffer");
1274
- const ext = path.extname(fileKey).slice(1).toLowerCase();
1285
+ const ext = extname(fileKey).slice(1).toLowerCase();
1275
1286
  const mimeTypeMap = {
1276
1287
  pdf: "application/pdf",
1277
1288
  txt: "text/plain",
@@ -1283,17 +1294,18 @@ var S3Stream = class _S3Stream extends S3File {
1283
1294
  pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
1284
1295
  };
1285
1296
  const contentType = mimeTypeMap[ext] || "application/octet-stream";
1297
+ const filename = basename2(fileKey);
1286
1298
  res.setHeader("Content-Type", contentType);
1287
- res.setHeader("Content-Disposition", `inline; filename="${path.basename(fileKey)}"`);
1299
+ res.setHeader("Content-Disposition", `inline; filename="${encodeURIComponent(filename)}"`);
1288
1300
  res.setHeader("Content-Length", fileBuffer.length);
1289
1301
  const cachingAge = !cachingAgeSeconds || typeof cachingAgeSeconds === "number" ? cachingAgeSeconds : getTotalSeconds(cachingAgeSeconds);
1290
1302
  res.setHeader("Cache-Control", `public, max-age=${cachingAge}`);
1291
1303
  res.status(200).send(fileBuffer);
1292
1304
  } catch (error) {
1293
- (_f = this.logger) == null ? void 0 : _f.warn(req.id, "pdf fileKey not found", __spreadValues({
1305
+ (_h = this.logger) == null ? void 0 : _h.warn(req.id, "pdf fileKey not found", __spreadValues({
1294
1306
  fileKey
1295
1307
  }, this.localstack && { localstack: this.localstack }));
1296
- next(`Failed to retrieve pdf file: ${error.message}`);
1308
+ next(Error(`Failed to retrieve pdf file: ${error.message}`));
1297
1309
  }
1298
1310
  });
1299
1311
  });
@@ -1322,7 +1334,6 @@ var S3Stream = class _S3Stream extends S3File {
1322
1334
  return response.Body;
1323
1335
  });
1324
1336
  }
1325
- // todo: LOCALSTACK SANITY CHECKED - WORKING WELL, DON'T TOUCH!
1326
1337
  streamVideoFile(_0) {
1327
1338
  return __async(this, arguments, function* (fileKey, {
1328
1339
  Range,
@@ -1351,7 +1362,7 @@ var S3Stream = class _S3Stream extends S3File {
1351
1362
  }
1352
1363
  };
1353
1364
  } catch (error) {
1354
- (_a2 = this.logger) == null ? void 0 : _a2.warn(this.reqId, "getS3VideoStream error", {
1365
+ (_a2 = this.logger) == null ? void 0 : _a2.warn(this.reqId, "streamVideoFile error", {
1355
1366
  Bucket: this.bucket,
1356
1367
  fileKey: normalizedKey,
1357
1368
  Range,
@@ -1361,29 +1372,39 @@ var S3Stream = class _S3Stream extends S3File {
1361
1372
  }
1362
1373
  });
1363
1374
  }
1364
- // todo: LOCALSTACK SANITY CHECKED - WORKING WELL, DON'T TOUCH!
1365
- getStreamVideoFileCtrl(_0) {
1375
+ streamVideoFileCtrl() {
1366
1376
  return __async(this, arguments, function* ({
1367
- fileKey,
1368
1377
  allowedWhitelist,
1369
- contentType = "video/mp4",
1370
- streamTimeoutMS = 3e4,
1371
- bufferMB = 5
1372
- }) {
1378
+ bufferMB = 5,
1379
+ contentType,
1380
+ fileKey: _fileKey,
1381
+ queryField = "file",
1382
+ paramsField = "file",
1383
+ headerField = "x-fileKey",
1384
+ streamTimeoutMS = 3e4
1385
+ } = {}) {
1373
1386
  return (req, res, next) => __async(this, null, function* () {
1374
- var _a2, _b, _c, _d, _e, _f;
1387
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
1388
+ 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);
1389
+ ((_e = req.headers) == null ? void 0 : _e[headerField]) ? (_f = req.headers) == null ? void 0 : _f[headerField] : void 0;
1390
+ if (!fileKey || fileKey === "/") {
1391
+ (_g = this.logger) == null ? void 0 : _g.warn(req.id, "fileKey video stream is required");
1392
+ next(Error("fileKey video stream is required"));
1393
+ return;
1394
+ }
1375
1395
  let normalizedKey = getNormalizedPath(fileKey);
1376
1396
  if (!normalizedKey || normalizedKey === "/") throw new Error("No file key provided");
1377
- const isExists = yield this.fileExists(normalizedKey);
1378
- const fileSize = yield this.sizeOf(normalizedKey);
1379
1397
  let Range;
1380
- if (!isExists) {
1381
- next(Error(`File does not exist: "${normalizedKey}"`));
1382
- return;
1383
- }
1398
+ let fileSize;
1384
1399
  try {
1400
+ const fileInfo = yield this.fileInfo(normalizedKey);
1401
+ if (!fileInfo) {
1402
+ next(Error(`File does not exist: "${normalizedKey}"`));
1403
+ return;
1404
+ }
1405
+ fileSize = getUnitBytes(fileInfo.ContentLength);
1385
1406
  if (req.method === "HEAD") {
1386
- res.setHeader("Content-Type", contentType);
1407
+ res.setHeader("Content-Type", fileInfo.ContentType);
1387
1408
  res.setHeader("Accept-Ranges", "bytes");
1388
1409
  if (fileSize) res.setHeader("Content-Length", String(fileSize));
1389
1410
  return res.status(200).end();
@@ -1416,14 +1437,14 @@ var S3Stream = class _S3Stream extends S3File {
1416
1437
  abortSignal: abort.signal
1417
1438
  });
1418
1439
  const { body, meta } = result;
1419
- const origin = Array.isArray(allowedWhitelist) ? allowedWhitelist.includes((_a2 = req.headers.origin) != null ? _a2 : "") ? req.headers.origin : void 0 : allowedWhitelist;
1440
+ const origin = Array.isArray(allowedWhitelist) ? allowedWhitelist.includes((_h = req.headers.origin) != null ? _h : "") ? req.headers.origin : void 0 : allowedWhitelist;
1420
1441
  if (origin) {
1421
1442
  res.setHeader("Access-Control-Allow-Origin", origin);
1422
1443
  res.setHeader("Vary", "Origin");
1423
1444
  }
1424
- const finalContentType = contentType.startsWith("video/") ? contentType : `video/${contentType}`;
1425
- res.setHeader("Content-Type", (_b = meta.contentType) != null ? _b : finalContentType);
1426
- res.setHeader("Accept-Ranges", (_c = meta.acceptRanges) != null ? _c : "bytes");
1445
+ const finalContentType = (contentType == null ? void 0 : contentType.startsWith("video/")) ? contentType : `video/${contentType || "mp4"}`;
1446
+ res.setHeader("Content-Type", (_i = meta.contentType) != null ? _i : finalContentType);
1447
+ res.setHeader("Accept-Ranges", (_j = meta.acceptRanges) != null ? _j : "bytes");
1427
1448
  if (Range && meta.contentRange) {
1428
1449
  res.status(206);
1429
1450
  res.setHeader("Content-Range", meta.contentRange);
@@ -1454,11 +1475,11 @@ var S3Stream = class _S3Stream extends S3File {
1454
1475
  return;
1455
1476
  }
1456
1477
  if (!res.headersSent) {
1457
- (_f = this.logger) == null ? void 0 : _f.warn(req.id, "caught exception in stream controller", {
1458
- error: (_d = error == null ? void 0 : error.message) != null ? _d : String(error),
1478
+ (_m = this.logger) == null ? void 0 : _m.warn(req.id, "caught exception in stream controller", {
1479
+ error: (_k = error == null ? void 0 : error.message) != null ? _k : String(error),
1459
1480
  key: fileKey,
1460
1481
  url: req.originalUrl,
1461
- userId: (_e = req.user) == null ? void 0 : _e._id
1482
+ userId: (_l = req.user) == null ? void 0 : _l._id
1462
1483
  });
1463
1484
  next(error);
1464
1485
  return;
@@ -1474,14 +1495,23 @@ var S3Stream = class _S3Stream extends S3File {
1474
1495
  });
1475
1496
  });
1476
1497
  }
1477
- // todo: LOCALSTACK SANITY CHECKED - WORKING WELL, DON'T TOUCH!
1478
- getStreamFileCtrl(_0) {
1479
- return __async(this, arguments, function* (fileKey, {
1498
+ streamFileCtrl() {
1499
+ return __async(this, arguments, function* ({
1500
+ fileKey: _fileKey,
1480
1501
  filename,
1481
- forDownloading = false
1502
+ forDownloading = false,
1503
+ paramsField = "file",
1504
+ queryField = "file",
1505
+ headerField = "x-fileKey"
1482
1506
  } = {}) {
1483
1507
  return (req, res, next) => __async(this, null, function* () {
1484
- var _a2, _b;
1508
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
1509
+ 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);
1510
+ if (!fileKey || fileKey === "/") {
1511
+ (_g = this.logger) == null ? void 0 : _g.warn(req.id, "fileKey stream is required");
1512
+ next(Error("fileKey stream is required"));
1513
+ return;
1514
+ }
1485
1515
  const abort = new AbortController();
1486
1516
  let stream = null;
1487
1517
  const onClose = () => {
@@ -1512,7 +1542,7 @@ var S3Stream = class _S3Stream extends S3File {
1512
1542
  const fileName = filename || normalizedKey.split("/").pop() || "download";
1513
1543
  res.setHeader("Content-Type", fileInfo.ContentType || "application/octet-stream");
1514
1544
  if (forDownloading) {
1515
- res.setHeader("Content-Disposition", `attachment; filename="${fileName}"`);
1545
+ res.setHeader("Content-Disposition", `attachment; filename="${encodeURIComponent(fileName)}"`);
1516
1546
  }
1517
1547
  if (fileInfo.ContentLength) {
1518
1548
  res.setHeader("Content-Length", String(fileInfo.ContentLength));
@@ -1533,13 +1563,13 @@ var S3Stream = class _S3Stream extends S3File {
1533
1563
  } catch (error) {
1534
1564
  abort.abort();
1535
1565
  if (stream) {
1536
- (_a2 = stream.destroy) == null ? void 0 : _a2.call(stream);
1566
+ (_h = stream.destroy) == null ? void 0 : _h.call(stream);
1537
1567
  }
1538
1568
  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";
1539
1569
  if (isBenignStreamError) {
1540
1570
  return;
1541
1571
  }
1542
- (_b = this.logger) == null ? void 0 : _b.error(this.reqId, "Failed to stream file", { fileKey: normalizedKey, error });
1572
+ (_i = this.logger) == null ? void 0 : _i.error(this.reqId, "Failed to stream file", { fileKey: normalizedKey, error });
1543
1573
  if (!res.headersSent) {
1544
1574
  next(error);
1545
1575
  } else if (!res.writableEnded) {
@@ -1554,17 +1584,26 @@ var S3Stream = class _S3Stream extends S3File {
1554
1584
  });
1555
1585
  });
1556
1586
  }
1557
- // todo: LOCALSTACK SANITY CHECKED - WORKING WELL, DON'T TOUCH!
1558
- getStreamZipFileCtr(_0) {
1559
- return __async(this, arguments, function* (fileKey, {
1587
+ streamZipFileCtr() {
1588
+ return __async(this, arguments, function* ({
1589
+ fileKey: _fileKey,
1560
1590
  filename: _filename,
1591
+ queryField = "file",
1592
+ paramsField = "file",
1593
+ headerField = "x-fileKey",
1561
1594
  compressionLevel = 5
1562
1595
  } = {}) {
1563
1596
  return (req, res, next) => __async(this, null, function* () {
1564
- var _a2, _b, _c, _d, _e;
1597
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
1565
1598
  const abort = new AbortController();
1566
1599
  const onClose = () => abort.abort();
1567
1600
  try {
1601
+ 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);
1602
+ if (!fileKey || fileKey === "/") {
1603
+ (_g = this.logger) == null ? void 0 : _g.warn(req.id, "fileKey video stream is required");
1604
+ next(Error("fileKey video stream is required"));
1605
+ return;
1606
+ }
1568
1607
  const fileKeys = [].concat(fileKey).map((fileKey2) => getNormalizedPath(fileKey2)).filter((v) => v && v !== "/");
1569
1608
  if (!fileKeys.length) {
1570
1609
  throw new Error("No file keys provided");
@@ -1572,7 +1611,7 @@ var S3Stream = class _S3Stream extends S3File {
1572
1611
  let filename = _filename || (/* @__PURE__ */ new Date()).toISOString();
1573
1612
  filename = filename.endsWith(".zip") ? filename : `${filename}.zip`;
1574
1613
  req.once("close", onClose);
1575
- (_a2 = this.logger) == null ? void 0 : _a2.info(this.reqId, "Starting parallel file download...", { fileCount: fileKeys.length });
1614
+ (_h = this.logger) == null ? void 0 : _h.info(this.reqId, "Starting parallel file download...", { fileCount: fileKeys.length });
1576
1615
  const downloadPromises = fileKeys.map((fileKey2) => __async(this, null, function* () {
1577
1616
  var _a3, _b2, _c2;
1578
1617
  try {
@@ -1622,7 +1661,7 @@ var S3Stream = class _S3Stream extends S3File {
1622
1661
  }
1623
1662
  return;
1624
1663
  }
1625
- (_b = this.logger) == null ? void 0 : _b.info(this.reqId, "All files downloaded, measuring zip size...", {
1664
+ (_i = this.logger) == null ? void 0 : _i.info(this.reqId, "All files downloaded, measuring zip size...", {
1626
1665
  fileCount: fileBuffers.length,
1627
1666
  totalSizeMB: (fileBuffers.reduce((sum, f) => sum + f.buffer.length, 0) / (1024 * 1024)).toFixed(2)
1628
1667
  });
@@ -1640,13 +1679,13 @@ var S3Stream = class _S3Stream extends S3File {
1640
1679
  req.off("close", onClose);
1641
1680
  return;
1642
1681
  }
1643
- (_c = this.logger) == null ? void 0 : _c.info(this.reqId, "Zip size calculated", {
1682
+ (_j = this.logger) == null ? void 0 : _j.info(this.reqId, "Zip size calculated", {
1644
1683
  actualZipSize,
1645
1684
  sizeMB: (actualZipSize / (1024 * 1024)).toFixed(2)
1646
1685
  });
1647
1686
  const actualArchive = archiver("zip", { zlib: { level: compressionLevel } });
1648
1687
  res.setHeader("Content-Type", "application/zip");
1649
- res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);
1688
+ res.setHeader("Content-Disposition", `attachment; filename="${encodeURIComponent(filename)}"`);
1650
1689
  res.setHeader("Content-Length", String(actualZipSize));
1651
1690
  res.setHeader("Access-Control-Expose-Headers", "Content-Type, Content-Disposition, Content-Length");
1652
1691
  actualArchive.on("error", (err) => {
@@ -1663,7 +1702,7 @@ var S3Stream = class _S3Stream extends S3File {
1663
1702
  actualArchive.append(file.buffer, { name: file.name });
1664
1703
  }
1665
1704
  yield actualArchive.finalize();
1666
- (_d = this.logger) == null ? void 0 : _d.info(this.reqId, "Zip download completed", {
1705
+ (_k = this.logger) == null ? void 0 : _k.info(this.reqId, "Zip download completed", {
1667
1706
  fileCount: fileBuffers.length,
1668
1707
  totalSize: actualZipSize
1669
1708
  });
@@ -1675,7 +1714,7 @@ var S3Stream = class _S3Stream extends S3File {
1675
1714
  return;
1676
1715
  }
1677
1716
  if (!res.headersSent) {
1678
- (_e = this.logger) == null ? void 0 : _e.error(this.reqId, "Failed to create zip archive", { error });
1717
+ (_l = this.logger) == null ? void 0 : _l.error(this.reqId, "Failed to create zip archive", { error });
1679
1718
  next(error);
1680
1719
  } else if (!res.writableEnded) {
1681
1720
  try {
@@ -1692,13 +1731,13 @@ var S3Stream = class _S3Stream extends S3File {
1692
1731
  static fileFilter(types, fileExt) {
1693
1732
  const fileTypesChecker = (fileExt == null ? void 0 : fileExt.length) ? new RegExp(`\\.(${fileExt.join("|")})$`, "i") : void 0;
1694
1733
  return function(_req, file, cb) {
1695
- const fileExtension = path.extname(file.originalname).substring(1);
1696
- const extname = fileTypesChecker ? fileTypesChecker.test(`.${fileExtension}`) : true;
1734
+ const fileExtension = extname(file.originalname).substring(1);
1735
+ const ext = fileTypesChecker ? fileTypesChecker.test(`.${fileExtension}`) : true;
1697
1736
  const mimeType = (types == null ? void 0 : types.length) ? types.some((type) => file.mimetype.startsWith(`${type}/`)) : true;
1698
- if (mimeType && extname) {
1737
+ if (mimeType && ext) {
1699
1738
  return cb(null, true);
1700
1739
  }
1701
- const errorMsg = !extname ? `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}`;
1740
+ 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}`;
1702
1741
  return cb(new Error(errorMsg));
1703
1742
  };
1704
1743
  }
@@ -1753,7 +1792,7 @@ var S3Stream = class _S3Stream extends S3File {
1753
1792
  * Middleware for uploading a single file
1754
1793
  * Adds the uploaded file info to req.s3File
1755
1794
  */
1756
- uploadSingleFile(fieldName, directoryPath, options = {}) {
1795
+ uploadSingleFileMW(fieldName, directoryPath, options = {}) {
1757
1796
  var _a2;
1758
1797
  let normalizedPath = getNormalizedPath(directoryPath);
1759
1798
  if (normalizedPath !== "/" && directoryPath !== "" && directoryPath !== void 0) normalizedPath += "/";
@@ -1785,13 +1824,14 @@ var S3Stream = class _S3Stream extends S3File {
1785
1824
  * Middleware for uploading multiple files with the same field name
1786
1825
  * Adds the uploaded files info to req.s3Files
1787
1826
  */
1788
- uploadMultipleFiles(fieldName, directoryPath, options = {}) {
1827
+ uploadMultipleFilesMW(fieldName, directoryPath, _c = {}) {
1828
+ var _d = _c, { maxFilesCount } = _d, options = __objRest(_d, ["maxFilesCount"]);
1789
1829
  let normalizedPath = getNormalizedPath(directoryPath);
1790
1830
  if (normalizedPath !== "/" && directoryPath !== "" && directoryPath !== void 0) normalizedPath += "/";
1791
1831
  else normalizedPath = "";
1792
1832
  const upload = this.getUploadFileMW(normalizedPath, options);
1793
1833
  return (req, res, next) => {
1794
- const mw = upload.array(fieldName, options.maxFilesCount || void 0);
1834
+ const mw = upload.array(fieldName, maxFilesCount || void 0);
1795
1835
  mw(req, res, (err) => {
1796
1836
  var _a2, _b;
1797
1837
  if (err) {
@@ -1814,7 +1854,7 @@ var S3Stream = class _S3Stream extends S3File {
1814
1854
  * Middleware for uploading any files (mixed field names)
1815
1855
  * Adds the uploaded files info to req.s3AllFiles
1816
1856
  */
1817
- uploadAnyFiles(directoryPath, maxCount, options = {}) {
1857
+ uploadAnyFilesMW(directoryPath, maxCount, options = {}) {
1818
1858
  let normalizedPath = getNormalizedPath(directoryPath);
1819
1859
  if (normalizedPath !== "/" && normalizedPath !== "" && directoryPath !== void 0) normalizedPath += "/";
1820
1860
  else normalizedPath = "";
@@ -1906,7 +1946,6 @@ var S3LocalstackUtil = class extends S3Util {
1906
1946
  constructor(props) {
1907
1947
  super(__spreadProps(__spreadValues({}, props), { localstack: true }));
1908
1948
  }
1909
- // todo: checked!
1910
1949
  directoryList(directoryPath) {
1911
1950
  return __async(this, null, function* () {
1912
1951
  var _a2;
@@ -1942,7 +1981,6 @@ var S3LocalstackUtil = class extends S3Util {
1942
1981
  return { directories, files };
1943
1982
  });
1944
1983
  }
1945
- // todo: checked!
1946
1984
  directoryListPaginated(_0) {
1947
1985
  return __async(this, arguments, function* (directoryPath, {
1948
1986
  pageSize = 100,