elseware-nodejs 1.5.1 → 1.5.3
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 +187 -164
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -46
- package/dist/index.d.ts +48 -46
- package/dist/index.js +185 -162
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
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
9
|
|
|
10
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
11
|
|
|
12
|
-
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
13
|
-
var cloudinaryModule__default = /*#__PURE__*/_interopDefault(cloudinaryModule);
|
|
14
12
|
var mongoose__default = /*#__PURE__*/_interopDefault(mongoose);
|
|
15
13
|
var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
|
|
14
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
15
|
+
var cloudinaryModule__default = /*#__PURE__*/_interopDefault(cloudinaryModule);
|
|
16
16
|
var jwt__default = /*#__PURE__*/_interopDefault(jwt);
|
|
17
17
|
|
|
18
18
|
// src/errors/appError.ts
|
|
@@ -250,160 +250,6 @@ function pickFields(obj, fields, options = {}) {
|
|
|
250
250
|
}
|
|
251
251
|
return result;
|
|
252
252
|
}
|
|
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
253
|
|
|
408
254
|
// src/utils/errorToString.ts
|
|
409
255
|
function errorToString(error) {
|
|
@@ -5297,6 +5143,160 @@ var validate = (schema) => (req, _res, next) => {
|
|
|
5297
5143
|
}
|
|
5298
5144
|
next();
|
|
5299
5145
|
};
|
|
5146
|
+
var AzureBlobStorageService = class {
|
|
5147
|
+
containerName;
|
|
5148
|
+
blobServiceClient;
|
|
5149
|
+
containerClient;
|
|
5150
|
+
sharedKeyCredential;
|
|
5151
|
+
constructor(config) {
|
|
5152
|
+
const { connectionString, accountName, accountKey, containerName } = config;
|
|
5153
|
+
this.containerName = containerName;
|
|
5154
|
+
this.blobServiceClient = storageBlob.BlobServiceClient.fromConnectionString(connectionString);
|
|
5155
|
+
this.containerClient = this.blobServiceClient.getContainerClient(containerName);
|
|
5156
|
+
this.sharedKeyCredential = new storageBlob.StorageSharedKeyCredential(
|
|
5157
|
+
accountName,
|
|
5158
|
+
accountKey
|
|
5159
|
+
);
|
|
5160
|
+
}
|
|
5161
|
+
// Upload file
|
|
5162
|
+
async uploadFile(localPath, blobName, onProgress) {
|
|
5163
|
+
const blockBlobClient = this.containerClient.getBlockBlobClient(blobName);
|
|
5164
|
+
const fileSize = fs__default.default.statSync(localPath).size;
|
|
5165
|
+
const readStream = fs__default.default.createReadStream(localPath);
|
|
5166
|
+
await blockBlobClient.uploadStream(
|
|
5167
|
+
readStream,
|
|
5168
|
+
4 * 1024 * 1024,
|
|
5169
|
+
// buffer size
|
|
5170
|
+
20,
|
|
5171
|
+
// max concurrency
|
|
5172
|
+
{
|
|
5173
|
+
onProgress: (ev) => {
|
|
5174
|
+
if (onProgress) {
|
|
5175
|
+
const percent = (ev.loadedBytes / fileSize * 100).toFixed(2);
|
|
5176
|
+
onProgress(percent);
|
|
5177
|
+
}
|
|
5178
|
+
}
|
|
5179
|
+
}
|
|
5180
|
+
);
|
|
5181
|
+
return blockBlobClient.url;
|
|
5182
|
+
}
|
|
5183
|
+
// Download file
|
|
5184
|
+
async downloadFile(blobName, downloadPath, onProgress) {
|
|
5185
|
+
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
5186
|
+
const response = await blobClient.download();
|
|
5187
|
+
const fileSize = response.contentLength || 0;
|
|
5188
|
+
let downloaded = 0;
|
|
5189
|
+
return new Promise((resolve, reject) => {
|
|
5190
|
+
const writable = fs__default.default.createWriteStream(downloadPath);
|
|
5191
|
+
response.readableStreamBody?.on("data", (chunk) => {
|
|
5192
|
+
downloaded += chunk.length;
|
|
5193
|
+
if (onProgress && fileSize > 0) {
|
|
5194
|
+
const percent = (downloaded / fileSize * 100).toFixed(2);
|
|
5195
|
+
onProgress(percent);
|
|
5196
|
+
}
|
|
5197
|
+
});
|
|
5198
|
+
response.readableStreamBody?.pipe(writable);
|
|
5199
|
+
writable.on("finish", resolve);
|
|
5200
|
+
writable.on("error", reject);
|
|
5201
|
+
});
|
|
5202
|
+
}
|
|
5203
|
+
// Delete file
|
|
5204
|
+
async deleteFile(blobName) {
|
|
5205
|
+
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
5206
|
+
await blobClient.deleteIfExists();
|
|
5207
|
+
return true;
|
|
5208
|
+
}
|
|
5209
|
+
// List blobs
|
|
5210
|
+
async listFiles(prefix = "") {
|
|
5211
|
+
const result = [];
|
|
5212
|
+
for await (const blob of this.containerClient.listBlobsFlat({ prefix })) {
|
|
5213
|
+
result.push(blob.name);
|
|
5214
|
+
}
|
|
5215
|
+
return result;
|
|
5216
|
+
}
|
|
5217
|
+
// Check existence
|
|
5218
|
+
async blobExists(blobName) {
|
|
5219
|
+
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
5220
|
+
return blobClient.exists();
|
|
5221
|
+
}
|
|
5222
|
+
// Generate temporary read-only SAS URL
|
|
5223
|
+
async generateSasUrl(blobName, expiresInMinutes = 60) {
|
|
5224
|
+
const blobClient = this.containerClient.getBlobClient(blobName);
|
|
5225
|
+
const sasToken = storageBlob.generateBlobSASQueryParameters(
|
|
5226
|
+
{
|
|
5227
|
+
containerName: this.containerName,
|
|
5228
|
+
blobName: blobClient.name,
|
|
5229
|
+
expiresOn: new Date(Date.now() + expiresInMinutes * 60 * 1e3),
|
|
5230
|
+
permissions: storageBlob.BlobSASPermissions.parse("r")
|
|
5231
|
+
// read-only
|
|
5232
|
+
},
|
|
5233
|
+
this.sharedKeyCredential
|
|
5234
|
+
).toString();
|
|
5235
|
+
return `${blobClient.url}?${sasToken}`;
|
|
5236
|
+
}
|
|
5237
|
+
};
|
|
5238
|
+
var cloudinary = cloudinaryModule__default.default.v2;
|
|
5239
|
+
var CloudinaryService = class {
|
|
5240
|
+
rootFolder;
|
|
5241
|
+
constructor(config) {
|
|
5242
|
+
const { cloudName, apiKey, apiSecret, rootFolder } = config;
|
|
5243
|
+
cloudinary.config({
|
|
5244
|
+
cloud_name: cloudName,
|
|
5245
|
+
api_key: apiKey,
|
|
5246
|
+
api_secret: apiSecret,
|
|
5247
|
+
secure: true
|
|
5248
|
+
});
|
|
5249
|
+
this.rootFolder = rootFolder;
|
|
5250
|
+
}
|
|
5251
|
+
// Upload file to Cloudinary
|
|
5252
|
+
async uploadFile(filePath, options = {}) {
|
|
5253
|
+
if (!fs__default.default.existsSync(filePath)) {
|
|
5254
|
+
throw new Error(`File not found: ${filePath}`);
|
|
5255
|
+
}
|
|
5256
|
+
const folderPath = this.buildFolderPath(options.folder);
|
|
5257
|
+
const result = await cloudinary.uploader.upload(filePath, {
|
|
5258
|
+
folder: folderPath,
|
|
5259
|
+
public_id: options.publicId,
|
|
5260
|
+
resource_type: options.resourceType || "auto"
|
|
5261
|
+
});
|
|
5262
|
+
return result.public_id;
|
|
5263
|
+
}
|
|
5264
|
+
// Delete asset by public ID
|
|
5265
|
+
async deleteFile(publicId) {
|
|
5266
|
+
const result = await cloudinary.uploader.destroy(publicId);
|
|
5267
|
+
return result.result === "ok";
|
|
5268
|
+
}
|
|
5269
|
+
// Check if asset exists
|
|
5270
|
+
async fileExists(publicId) {
|
|
5271
|
+
try {
|
|
5272
|
+
await cloudinary.api.resource(publicId);
|
|
5273
|
+
return true;
|
|
5274
|
+
} catch {
|
|
5275
|
+
return false;
|
|
5276
|
+
}
|
|
5277
|
+
}
|
|
5278
|
+
// Generate optimized delivery URL
|
|
5279
|
+
generateUrl(publicId, options = {}) {
|
|
5280
|
+
return cloudinary.url(publicId, {
|
|
5281
|
+
secure: true,
|
|
5282
|
+
...options
|
|
5283
|
+
});
|
|
5284
|
+
}
|
|
5285
|
+
// Create folder (idempotent)
|
|
5286
|
+
async createFolder(folder) {
|
|
5287
|
+
try {
|
|
5288
|
+
await cloudinary.api.create_folder(folder);
|
|
5289
|
+
} catch (err) {
|
|
5290
|
+
}
|
|
5291
|
+
}
|
|
5292
|
+
buildFolderPath(subFolder) {
|
|
5293
|
+
if (!this.rootFolder && !subFolder) return void 0;
|
|
5294
|
+
if (this.rootFolder && subFolder) {
|
|
5295
|
+
return `${this.rootFolder}/${subFolder}`;
|
|
5296
|
+
}
|
|
5297
|
+
return this.rootFolder || subFolder;
|
|
5298
|
+
}
|
|
5299
|
+
};
|
|
5300
5300
|
var JWTService = class {
|
|
5301
5301
|
accessSecret;
|
|
5302
5302
|
refreshSecret;
|
|
@@ -5307,8 +5307,8 @@ var JWTService = class {
|
|
|
5307
5307
|
constructor(options) {
|
|
5308
5308
|
this.accessSecret = options.accessSecret;
|
|
5309
5309
|
this.refreshSecret = options.refreshSecret;
|
|
5310
|
-
this.accessExpires = options.accessExpires
|
|
5311
|
-
this.refreshExpires = options.refreshExpires
|
|
5310
|
+
this.accessExpires = this.parseExpires(options.accessExpires, "15m");
|
|
5311
|
+
this.refreshExpires = this.parseExpires(options.refreshExpires, "30d");
|
|
5312
5312
|
this.nodeEnv = options.nodeEnv || "development";
|
|
5313
5313
|
this.refreshCookieName = options.refreshCookieName || "refreshJwt";
|
|
5314
5314
|
}
|
|
@@ -5348,14 +5348,18 @@ var JWTService = class {
|
|
|
5348
5348
|
// Token Extraction
|
|
5349
5349
|
// ---------------------------------
|
|
5350
5350
|
extractToken(req) {
|
|
5351
|
+
let token = null;
|
|
5351
5352
|
if (req.headers.authorization?.startsWith("Bearer ")) {
|
|
5352
|
-
|
|
5353
|
+
token = req.headers.authorization.split(" ")[1];
|
|
5354
|
+
return token ? this.normalizeToken(token) : null;
|
|
5353
5355
|
}
|
|
5354
5356
|
if (req.cookies?.[this.refreshCookieName]) {
|
|
5355
|
-
|
|
5357
|
+
token = req.cookies[this.refreshCookieName];
|
|
5358
|
+
return token ? this.normalizeToken(token) : null;
|
|
5356
5359
|
}
|
|
5357
5360
|
if (req.cookies?.jwt) {
|
|
5358
|
-
|
|
5361
|
+
token = req.cookies.jwt;
|
|
5362
|
+
return token ? this.normalizeToken(token) : null;
|
|
5359
5363
|
}
|
|
5360
5364
|
return null;
|
|
5361
5365
|
}
|
|
@@ -5388,6 +5392,25 @@ var JWTService = class {
|
|
|
5388
5392
|
this.setRefreshTokenCookie(res, refreshToken);
|
|
5389
5393
|
return accessToken;
|
|
5390
5394
|
}
|
|
5395
|
+
// ---------------------------------
|
|
5396
|
+
// Internal Helpers
|
|
5397
|
+
// ---------------------------------
|
|
5398
|
+
normalizeToken(token) {
|
|
5399
|
+
token = token.trim();
|
|
5400
|
+
if (token.startsWith('"') && token.endsWith('"')) {
|
|
5401
|
+
try {
|
|
5402
|
+
return JSON.parse(token);
|
|
5403
|
+
} catch {
|
|
5404
|
+
return token.slice(1, -1);
|
|
5405
|
+
}
|
|
5406
|
+
}
|
|
5407
|
+
return token;
|
|
5408
|
+
}
|
|
5409
|
+
parseExpires(value, fallback) {
|
|
5410
|
+
if (!value) return fallback;
|
|
5411
|
+
if (typeof value === "number") return value;
|
|
5412
|
+
return value;
|
|
5413
|
+
}
|
|
5391
5414
|
};
|
|
5392
5415
|
|
|
5393
5416
|
// src/utils/time.ts
|
|
@@ -5426,7 +5449,7 @@ exports.AVLTree = AVLTree;
|
|
|
5426
5449
|
exports.AdjacencyList = AdjacencyList;
|
|
5427
5450
|
exports.AdjacencyMatrix = AdjacencyMatrix;
|
|
5428
5451
|
exports.AppError = AppError;
|
|
5429
|
-
exports.
|
|
5452
|
+
exports.AzureBlobStorageService = AzureBlobStorageService;
|
|
5430
5453
|
exports.BPlusTree = BPlusTree;
|
|
5431
5454
|
exports.BTree = BTree;
|
|
5432
5455
|
exports.BinaryHeap = BinaryHeap;
|