elseware-nodejs 1.5.2 → 1.6.0
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.cjs +217 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -44
- package/dist/index.d.ts +64 -44
- package/dist/index.js +213 -157
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var mongoose = require('mongoose');
|
|
4
|
+
var dotenv = require('dotenv');
|
|
3
5
|
var storageBlob = require('@azure/storage-blob');
|
|
4
6
|
var fs = require('fs');
|
|
5
7
|
var cloudinaryModule = require('cloudinary');
|
|
6
|
-
var mongoose = require('mongoose');
|
|
7
|
-
var dotenv = require('dotenv');
|
|
8
8
|
var jwt = require('jsonwebtoken');
|
|
9
|
+
var multer = require('multer');
|
|
9
10
|
|
|
10
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
12
|
|
|
12
|
-
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
13
|
-
var cloudinaryModule__default = /*#__PURE__*/_interopDefault(cloudinaryModule);
|
|
14
13
|
var mongoose__default = /*#__PURE__*/_interopDefault(mongoose);
|
|
15
14
|
var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
|
|
15
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
16
|
+
var cloudinaryModule__default = /*#__PURE__*/_interopDefault(cloudinaryModule);
|
|
16
17
|
var jwt__default = /*#__PURE__*/_interopDefault(jwt);
|
|
18
|
+
var multer__default = /*#__PURE__*/_interopDefault(multer);
|
|
17
19
|
|
|
18
20
|
// src/errors/appError.ts
|
|
19
21
|
var AppError = class extends Error {
|
|
@@ -250,160 +252,6 @@ function pickFields(obj, fields, options = {}) {
|
|
|
250
252
|
}
|
|
251
253
|
return result;
|
|
252
254
|
}
|
|
253
|
-
var AzureBlobService = class {
|
|
254
|
-
containerName;
|
|
255
|
-
blobServiceClient;
|
|
256
|
-
containerClient;
|
|
257
|
-
sharedKeyCredential;
|
|
258
|
-
constructor(config) {
|
|
259
|
-
const { connectionString, accountName, accountKey, containerName } = config;
|
|
260
|
-
this.containerName = containerName;
|
|
261
|
-
this.blobServiceClient = storageBlob.BlobServiceClient.fromConnectionString(connectionString);
|
|
262
|
-
this.containerClient = this.blobServiceClient.getContainerClient(containerName);
|
|
263
|
-
this.sharedKeyCredential = new storageBlob.StorageSharedKeyCredential(
|
|
264
|
-
accountName,
|
|
265
|
-
accountKey
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
// Upload file
|
|
269
|
-
async uploadFile(localPath, blobName, onProgress) {
|
|
270
|
-
const blockBlobClient = this.containerClient.getBlockBlobClient(blobName);
|
|
271
|
-
const fileSize = fs__default.default.statSync(localPath).size;
|
|
272
|
-
const readStream = fs__default.default.createReadStream(localPath);
|
|
273
|
-
await blockBlobClient.uploadStream(
|
|
274
|
-
readStream,
|
|
275
|
-
4 * 1024 * 1024,
|
|
276
|
-
// buffer size
|
|
277
|
-
20,
|
|
278
|
-
// max concurrency
|
|
279
|
-
{
|
|
280
|
-
onProgress: (ev) => {
|
|
281
|
-
if (onProgress) {
|
|
282
|
-
const percent = (ev.loadedBytes / fileSize * 100).toFixed(2);
|
|
283
|
-
onProgress(percent);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
);
|
|
288
|
-
return blockBlobClient.url;
|
|
289
|
-
}
|
|
290
|
-
// Download file
|
|
291
|
-
async downloadFile(blobName, downloadPath, onProgress) {
|
|
292
|
-
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
293
|
-
const response = await blobClient.download();
|
|
294
|
-
const fileSize = response.contentLength || 0;
|
|
295
|
-
let downloaded = 0;
|
|
296
|
-
return new Promise((resolve, reject) => {
|
|
297
|
-
const writable = fs__default.default.createWriteStream(downloadPath);
|
|
298
|
-
response.readableStreamBody?.on("data", (chunk) => {
|
|
299
|
-
downloaded += chunk.length;
|
|
300
|
-
if (onProgress && fileSize > 0) {
|
|
301
|
-
const percent = (downloaded / fileSize * 100).toFixed(2);
|
|
302
|
-
onProgress(percent);
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
response.readableStreamBody?.pipe(writable);
|
|
306
|
-
writable.on("finish", resolve);
|
|
307
|
-
writable.on("error", reject);
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
// Delete file
|
|
311
|
-
async deleteFile(blobName) {
|
|
312
|
-
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
313
|
-
await blobClient.deleteIfExists();
|
|
314
|
-
return true;
|
|
315
|
-
}
|
|
316
|
-
// List blobs
|
|
317
|
-
async listFiles(prefix = "") {
|
|
318
|
-
const result = [];
|
|
319
|
-
for await (const blob of this.containerClient.listBlobsFlat({ prefix })) {
|
|
320
|
-
result.push(blob.name);
|
|
321
|
-
}
|
|
322
|
-
return result;
|
|
323
|
-
}
|
|
324
|
-
// Check existence
|
|
325
|
-
async blobExists(blobName) {
|
|
326
|
-
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
327
|
-
return blobClient.exists();
|
|
328
|
-
}
|
|
329
|
-
// Generate temporary read-only SAS URL
|
|
330
|
-
async generateSasUrl(blobName, expiresInMinutes = 60) {
|
|
331
|
-
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
332
|
-
const sasToken = storageBlob.generateBlobSASQueryParameters(
|
|
333
|
-
{
|
|
334
|
-
containerName: this.containerName,
|
|
335
|
-
blobName: blobClient.name,
|
|
336
|
-
expiresOn: new Date(Date.now() + expiresInMinutes * 60 * 1e3),
|
|
337
|
-
permissions: storageBlob.BlobSASPermissions.parse("r")
|
|
338
|
-
// read-only
|
|
339
|
-
},
|
|
340
|
-
this.sharedKeyCredential
|
|
341
|
-
).toString();
|
|
342
|
-
return `${blobClient.url}?${sasToken}`;
|
|
343
|
-
}
|
|
344
|
-
};
|
|
345
|
-
var cloudinary = cloudinaryModule__default.default.v2;
|
|
346
|
-
var CloudinaryService = class {
|
|
347
|
-
rootFolder;
|
|
348
|
-
constructor(config) {
|
|
349
|
-
const { cloudName, apiKey, apiSecret, rootFolder } = config;
|
|
350
|
-
cloudinary.config({
|
|
351
|
-
cloud_name: cloudName,
|
|
352
|
-
api_key: apiKey,
|
|
353
|
-
api_secret: apiSecret,
|
|
354
|
-
secure: true
|
|
355
|
-
});
|
|
356
|
-
this.rootFolder = rootFolder;
|
|
357
|
-
}
|
|
358
|
-
// Upload file to Cloudinary
|
|
359
|
-
async uploadFile(filePath, options = {}) {
|
|
360
|
-
if (!fs__default.default.existsSync(filePath)) {
|
|
361
|
-
throw new Error(`File not found: ${filePath}`);
|
|
362
|
-
}
|
|
363
|
-
const folderPath = this.buildFolderPath(options.folder);
|
|
364
|
-
const result = await cloudinary.uploader.upload(filePath, {
|
|
365
|
-
folder: folderPath,
|
|
366
|
-
public_id: options.publicId,
|
|
367
|
-
resource_type: options.resourceType || "auto"
|
|
368
|
-
});
|
|
369
|
-
return result.public_id;
|
|
370
|
-
}
|
|
371
|
-
// Delete asset by public ID
|
|
372
|
-
async deleteFile(publicId) {
|
|
373
|
-
const result = await cloudinary.uploader.destroy(publicId);
|
|
374
|
-
return result.result === "ok";
|
|
375
|
-
}
|
|
376
|
-
// Check if asset exists
|
|
377
|
-
async fileExists(publicId) {
|
|
378
|
-
try {
|
|
379
|
-
await cloudinary.api.resource(publicId);
|
|
380
|
-
return true;
|
|
381
|
-
} catch {
|
|
382
|
-
return false;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
// Generate optimized delivery URL
|
|
386
|
-
generateUrl(publicId, options = {}) {
|
|
387
|
-
return cloudinary.url(publicId, {
|
|
388
|
-
secure: true,
|
|
389
|
-
...options
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
// Create folder (idempotent)
|
|
393
|
-
async createFolder(folder) {
|
|
394
|
-
try {
|
|
395
|
-
await cloudinary.api.create_folder(folder);
|
|
396
|
-
} catch (err) {
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
buildFolderPath(subFolder) {
|
|
400
|
-
if (!this.rootFolder && !subFolder) return void 0;
|
|
401
|
-
if (this.rootFolder && subFolder) {
|
|
402
|
-
return `${this.rootFolder}/${subFolder}`;
|
|
403
|
-
}
|
|
404
|
-
return this.rootFolder || subFolder;
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
255
|
|
|
408
256
|
// src/utils/errorToString.ts
|
|
409
257
|
function errorToString(error) {
|
|
@@ -5297,6 +5145,160 @@ var validate = (schema) => (req, _res, next) => {
|
|
|
5297
5145
|
}
|
|
5298
5146
|
next();
|
|
5299
5147
|
};
|
|
5148
|
+
var AzureBlobStorageService = class {
|
|
5149
|
+
containerName;
|
|
5150
|
+
blobServiceClient;
|
|
5151
|
+
containerClient;
|
|
5152
|
+
sharedKeyCredential;
|
|
5153
|
+
constructor(config) {
|
|
5154
|
+
const { connectionString, accountName, accountKey, containerName } = config;
|
|
5155
|
+
this.containerName = containerName;
|
|
5156
|
+
this.blobServiceClient = storageBlob.BlobServiceClient.fromConnectionString(connectionString);
|
|
5157
|
+
this.containerClient = this.blobServiceClient.getContainerClient(containerName);
|
|
5158
|
+
this.sharedKeyCredential = new storageBlob.StorageSharedKeyCredential(
|
|
5159
|
+
accountName,
|
|
5160
|
+
accountKey
|
|
5161
|
+
);
|
|
5162
|
+
}
|
|
5163
|
+
// Upload file
|
|
5164
|
+
async uploadFile(localPath, blobName, onProgress) {
|
|
5165
|
+
const blockBlobClient = this.containerClient.getBlockBlobClient(blobName);
|
|
5166
|
+
const fileSize = fs__default.default.statSync(localPath).size;
|
|
5167
|
+
const readStream = fs__default.default.createReadStream(localPath);
|
|
5168
|
+
await blockBlobClient.uploadStream(
|
|
5169
|
+
readStream,
|
|
5170
|
+
4 * 1024 * 1024,
|
|
5171
|
+
// buffer size
|
|
5172
|
+
20,
|
|
5173
|
+
// max concurrency
|
|
5174
|
+
{
|
|
5175
|
+
onProgress: (ev) => {
|
|
5176
|
+
if (onProgress) {
|
|
5177
|
+
const percent = (ev.loadedBytes / fileSize * 100).toFixed(2);
|
|
5178
|
+
onProgress(percent);
|
|
5179
|
+
}
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
);
|
|
5183
|
+
return blockBlobClient.url;
|
|
5184
|
+
}
|
|
5185
|
+
// Download file
|
|
5186
|
+
async downloadFile(blobName, downloadPath, onProgress) {
|
|
5187
|
+
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
5188
|
+
const response = await blobClient.download();
|
|
5189
|
+
const fileSize = response.contentLength || 0;
|
|
5190
|
+
let downloaded = 0;
|
|
5191
|
+
return new Promise((resolve, reject) => {
|
|
5192
|
+
const writable = fs__default.default.createWriteStream(downloadPath);
|
|
5193
|
+
response.readableStreamBody?.on("data", (chunk) => {
|
|
5194
|
+
downloaded += chunk.length;
|
|
5195
|
+
if (onProgress && fileSize > 0) {
|
|
5196
|
+
const percent = (downloaded / fileSize * 100).toFixed(2);
|
|
5197
|
+
onProgress(percent);
|
|
5198
|
+
}
|
|
5199
|
+
});
|
|
5200
|
+
response.readableStreamBody?.pipe(writable);
|
|
5201
|
+
writable.on("finish", resolve);
|
|
5202
|
+
writable.on("error", reject);
|
|
5203
|
+
});
|
|
5204
|
+
}
|
|
5205
|
+
// Delete file
|
|
5206
|
+
async deleteFile(blobName) {
|
|
5207
|
+
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
5208
|
+
await blobClient.deleteIfExists();
|
|
5209
|
+
return true;
|
|
5210
|
+
}
|
|
5211
|
+
// List blobs
|
|
5212
|
+
async listFiles(prefix = "") {
|
|
5213
|
+
const result = [];
|
|
5214
|
+
for await (const blob of this.containerClient.listBlobsFlat({ prefix })) {
|
|
5215
|
+
result.push(blob.name);
|
|
5216
|
+
}
|
|
5217
|
+
return result;
|
|
5218
|
+
}
|
|
5219
|
+
// Check existence
|
|
5220
|
+
async blobExists(blobName) {
|
|
5221
|
+
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
5222
|
+
return blobClient.exists();
|
|
5223
|
+
}
|
|
5224
|
+
// Generate temporary read-only SAS URL
|
|
5225
|
+
async generateSasUrl(blobName, expiresInMinutes = 60) {
|
|
5226
|
+
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
5227
|
+
const sasToken = storageBlob.generateBlobSASQueryParameters(
|
|
5228
|
+
{
|
|
5229
|
+
containerName: this.containerName,
|
|
5230
|
+
blobName: blobClient.name,
|
|
5231
|
+
expiresOn: new Date(Date.now() + expiresInMinutes * 60 * 1e3),
|
|
5232
|
+
permissions: storageBlob.BlobSASPermissions.parse("r")
|
|
5233
|
+
// read-only
|
|
5234
|
+
},
|
|
5235
|
+
this.sharedKeyCredential
|
|
5236
|
+
).toString();
|
|
5237
|
+
return `${blobClient.url}?${sasToken}`;
|
|
5238
|
+
}
|
|
5239
|
+
};
|
|
5240
|
+
var cloudinary = cloudinaryModule__default.default.v2;
|
|
5241
|
+
var CloudinaryService = class {
|
|
5242
|
+
rootFolder;
|
|
5243
|
+
constructor(config) {
|
|
5244
|
+
const { cloudName, apiKey, apiSecret, rootFolder } = config;
|
|
5245
|
+
cloudinary.config({
|
|
5246
|
+
cloud_name: cloudName,
|
|
5247
|
+
api_key: apiKey,
|
|
5248
|
+
api_secret: apiSecret,
|
|
5249
|
+
secure: true
|
|
5250
|
+
});
|
|
5251
|
+
this.rootFolder = rootFolder;
|
|
5252
|
+
}
|
|
5253
|
+
// Upload file to Cloudinary
|
|
5254
|
+
async uploadFile(filePath, options = {}) {
|
|
5255
|
+
if (!fs__default.default.existsSync(filePath)) {
|
|
5256
|
+
throw new Error(`File not found: ${filePath}`);
|
|
5257
|
+
}
|
|
5258
|
+
const folderPath = this.buildFolderPath(options.folder);
|
|
5259
|
+
const result = await cloudinary.uploader.upload(filePath, {
|
|
5260
|
+
folder: folderPath,
|
|
5261
|
+
public_id: options.publicId,
|
|
5262
|
+
resource_type: options.resourceType || "auto"
|
|
5263
|
+
});
|
|
5264
|
+
return result.public_id;
|
|
5265
|
+
}
|
|
5266
|
+
// Delete asset by public ID
|
|
5267
|
+
async deleteFile(publicId) {
|
|
5268
|
+
const result = await cloudinary.uploader.destroy(publicId);
|
|
5269
|
+
return result.result === "ok";
|
|
5270
|
+
}
|
|
5271
|
+
// Check if asset exists
|
|
5272
|
+
async fileExists(publicId) {
|
|
5273
|
+
try {
|
|
5274
|
+
await cloudinary.api.resource(publicId);
|
|
5275
|
+
return true;
|
|
5276
|
+
} catch {
|
|
5277
|
+
return false;
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
5280
|
+
// Generate optimized delivery URL
|
|
5281
|
+
generateUrl(publicId, options = {}) {
|
|
5282
|
+
return cloudinary.url(publicId, {
|
|
5283
|
+
secure: true,
|
|
5284
|
+
...options
|
|
5285
|
+
});
|
|
5286
|
+
}
|
|
5287
|
+
// Create folder (idempotent)
|
|
5288
|
+
async createFolder(folder) {
|
|
5289
|
+
try {
|
|
5290
|
+
await cloudinary.api.create_folder(folder);
|
|
5291
|
+
} catch (err) {
|
|
5292
|
+
}
|
|
5293
|
+
}
|
|
5294
|
+
buildFolderPath(subFolder) {
|
|
5295
|
+
if (!this.rootFolder && !subFolder) return void 0;
|
|
5296
|
+
if (this.rootFolder && subFolder) {
|
|
5297
|
+
return `${this.rootFolder}/${subFolder}`;
|
|
5298
|
+
}
|
|
5299
|
+
return this.rootFolder || subFolder;
|
|
5300
|
+
}
|
|
5301
|
+
};
|
|
5300
5302
|
var JWTService = class {
|
|
5301
5303
|
accessSecret;
|
|
5302
5304
|
refreshSecret;
|
|
@@ -5412,6 +5414,61 @@ var JWTService = class {
|
|
|
5412
5414
|
return value;
|
|
5413
5415
|
}
|
|
5414
5416
|
};
|
|
5417
|
+
var MulterFileHandlerService = class {
|
|
5418
|
+
storage;
|
|
5419
|
+
options;
|
|
5420
|
+
constructor(options = {}) {
|
|
5421
|
+
this.options = options;
|
|
5422
|
+
this.storage = options.storage === "memory" ? multer__default.default.memoryStorage() : multer__default.default.diskStorage({});
|
|
5423
|
+
}
|
|
5424
|
+
// File Filter
|
|
5425
|
+
fileFilter = (req, file, cb) => {
|
|
5426
|
+
const { allowedMimeTypes, allowedExtensions } = this.options;
|
|
5427
|
+
const mimeType = file.mimetype;
|
|
5428
|
+
const extFromMime = mimeType.split("/")[1]?.toLowerCase();
|
|
5429
|
+
if (allowedMimeTypes?.length) {
|
|
5430
|
+
if (!allowedMimeTypes.includes(mimeType)) {
|
|
5431
|
+
return cb(
|
|
5432
|
+
new AppError(
|
|
5433
|
+
`Invalid file type! Allowed: ${allowedMimeTypes.join(", ")}`,
|
|
5434
|
+
400
|
|
5435
|
+
),
|
|
5436
|
+
false
|
|
5437
|
+
);
|
|
5438
|
+
}
|
|
5439
|
+
}
|
|
5440
|
+
if (allowedExtensions?.length) {
|
|
5441
|
+
if (!extFromMime || !allowedExtensions.includes(extFromMime)) {
|
|
5442
|
+
return cb(
|
|
5443
|
+
new AppError(
|
|
5444
|
+
`Invalid file extension! Allowed: ${allowedExtensions.join(", ")}`,
|
|
5445
|
+
400
|
|
5446
|
+
),
|
|
5447
|
+
false
|
|
5448
|
+
);
|
|
5449
|
+
}
|
|
5450
|
+
}
|
|
5451
|
+
cb(null, true);
|
|
5452
|
+
};
|
|
5453
|
+
// Build multer instance
|
|
5454
|
+
buildUploader() {
|
|
5455
|
+
return multer__default.default({
|
|
5456
|
+
storage: this.storage,
|
|
5457
|
+
fileFilter: this.fileFilter,
|
|
5458
|
+
limits: this.options.fileSizeLimit ? { fileSize: this.options.fileSizeLimit } : void 0
|
|
5459
|
+
});
|
|
5460
|
+
}
|
|
5461
|
+
// Public API
|
|
5462
|
+
single(fieldName) {
|
|
5463
|
+
return this.buildUploader().single(fieldName);
|
|
5464
|
+
}
|
|
5465
|
+
array(fieldName, maxCount) {
|
|
5466
|
+
return this.buildUploader().array(fieldName, maxCount);
|
|
5467
|
+
}
|
|
5468
|
+
fields(fields) {
|
|
5469
|
+
return this.buildUploader().fields(fields);
|
|
5470
|
+
}
|
|
5471
|
+
};
|
|
5415
5472
|
|
|
5416
5473
|
// src/utils/time.ts
|
|
5417
5474
|
function milliseconds(value) {
|
|
@@ -5449,7 +5506,7 @@ exports.AVLTree = AVLTree;
|
|
|
5449
5506
|
exports.AdjacencyList = AdjacencyList;
|
|
5450
5507
|
exports.AdjacencyMatrix = AdjacencyMatrix;
|
|
5451
5508
|
exports.AppError = AppError;
|
|
5452
|
-
exports.
|
|
5509
|
+
exports.AzureBlobStorageService = AzureBlobStorageService;
|
|
5453
5510
|
exports.BPlusTree = BPlusTree;
|
|
5454
5511
|
exports.BTree = BTree;
|
|
5455
5512
|
exports.BinaryHeap = BinaryHeap;
|
|
@@ -5484,6 +5541,7 @@ exports.MaxHeap = MaxHeap;
|
|
|
5484
5541
|
exports.MaxStack = MaxStack;
|
|
5485
5542
|
exports.MinHeap = MinHeap;
|
|
5486
5543
|
exports.MinStack = MinStack;
|
|
5544
|
+
exports.MulterFileHandlerService = MulterFileHandlerService;
|
|
5487
5545
|
exports.MultiSet = MultiSet;
|
|
5488
5546
|
exports.Node = Node;
|
|
5489
5547
|
exports.OrderedSet = OrderedSet;
|