mbkbucket 3.6.0 → 3.7.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/README.md +1 -1
- package/lib/cli.js +650 -649
- package/lib/public/bucketadmin.css +282 -7
- package/lib/src/cli/auth-helper.js +9 -18
- package/lib/src/config/index.js +0 -2
- package/lib/src/config/validation.js +3 -3
- package/lib/src/controllers/api.controller.js +1 -1
- package/lib/src/controllers/dashboard.controller.js +4 -3
- package/lib/src/controllers/info.controller.js +1 -2
- package/lib/src/controllers/view.controller.js +1 -3
- package/lib/src/middleware/async-handler.js +4 -8
- package/lib/src/middleware/error-handler.js +2 -6
- package/lib/src/middleware/rate-limiter.js +2 -2
- package/lib/src/middleware/security.js +1 -7
- package/lib/src/routes/api.routes.js +4 -5
- package/lib/src/routes/index.js +39 -19
- package/lib/src/services/s3.service.js +10 -19
- package/lib/src/utils/errors.js +3 -11
- package/lib/src/utils/helpers.js +29 -68
- package/package.json +5 -5
package/lib/src/routes/index.js
CHANGED
|
@@ -7,32 +7,52 @@
|
|
|
7
7
|
|
|
8
8
|
import express from "express";
|
|
9
9
|
import { sessRole } from "mbkauthe";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
10
12
|
import { bucketResolver } from "../middleware/bucket-resolver.js";
|
|
11
13
|
import { renderBucketDashboard } from "../controllers/dashboard.controller.js";
|
|
12
14
|
import infoRoutes from "./info.routes.js";
|
|
13
15
|
import { createViewRoutes } from "./view.routes.js";
|
|
14
16
|
import { createApiRoutes } from "./api.routes.js";
|
|
15
17
|
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
+
const __dirname = path.dirname(__filename);
|
|
20
|
+
const publicDir = path.resolve(__dirname, "..", "..", "public");
|
|
21
|
+
|
|
22
|
+
const serveAsset = (filename) => (_req, res) => {
|
|
23
|
+
res.set("Cache-Control", "public, max-age=300, must-revalidate");
|
|
24
|
+
res.sendFile(path.join(publicDir, filename), (err) => {
|
|
25
|
+
if (err) res.status(err.status || 404).end();
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
16
29
|
export function createBucketRouter({ authorization } = {}) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
const router = express.Router();
|
|
31
|
+
const defaultAuth = sessRole('superadmin');
|
|
32
|
+
const auths = typeof authorization === 'function'
|
|
33
|
+
? { view: authorization, upload: authorization, delete: authorization }
|
|
34
|
+
: authorization ?? {};
|
|
35
|
+
const viewAuth = auths.view ?? defaultAuth;
|
|
36
|
+
const uploadAuth = auths.upload ?? defaultAuth;
|
|
37
|
+
const deleteAuth = auths.delete ?? defaultAuth;
|
|
38
|
+
|
|
39
|
+
// Static dashboard & helper assets
|
|
40
|
+
router.get('/mbkbucket/bucketadmin.css', serveAsset('bucketadmin.css'));
|
|
41
|
+
router.get('/mbkbucket/bucketadmin.js', serveAsset('bucketadmin.js'));
|
|
42
|
+
router.get('/mbkbucket/mbkbucket-helper.css', serveAsset('mbkbucket-helper.css'));
|
|
43
|
+
router.get('/mbkbucket/mbkbucket-helper.js', serveAsset('mbkbucket-helper.js'));
|
|
44
|
+
router.get('/mbkbucket/helper-demo', serveAsset('mbkbucket-helper-demo.html'));
|
|
45
|
+
|
|
46
|
+
router.get('/mbkbucket', viewAuth, renderBucketDashboard);
|
|
47
|
+
router.use(
|
|
48
|
+
'/mbkbucket',
|
|
49
|
+
bucketResolver,
|
|
50
|
+
infoRoutes,
|
|
51
|
+
createViewRoutes({ authorization: viewAuth }),
|
|
52
|
+
createApiRoutes({ viewAuthorization: viewAuth, uploadAuthorization: uploadAuth, deleteAuthorization: deleteAuth })
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return router;
|
|
36
56
|
}
|
|
37
57
|
|
|
38
58
|
const router = createBucketRouter();
|
|
@@ -12,7 +12,7 @@ function parseJsonEnv(envVar, fallback = {}) {
|
|
|
12
12
|
try {
|
|
13
13
|
return JSON.parse(envVar);
|
|
14
14
|
} catch (e) {
|
|
15
|
-
console.error(`❌ Error parsing JSON for envVar: ${
|
|
15
|
+
console.error(`❌ Error parsing JSON for envVar: ${String(envVar).slice(0, 200)} - ${e.message}`);
|
|
16
16
|
console.error(`💡 Tip: Check that inner objects are NOT quoted as strings. Use {"key":{"field":"value"}} not {"key":"{"field":"value"}"}`);
|
|
17
17
|
return fallback;
|
|
18
18
|
}
|
|
@@ -24,13 +24,9 @@ const hasBucketConfigs = availableBucketNames.length > 0;
|
|
|
24
24
|
|
|
25
25
|
const escapeRegExp = value => String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
26
26
|
|
|
27
|
-
export
|
|
28
|
-
return availableBucketNames;
|
|
29
|
-
}
|
|
27
|
+
export const getAvailableBucketNames = () => availableBucketNames;
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
return mbkautheVar?.bucket || (availableBucketNames.length > 0 ? availableBucketNames[0] : null);
|
|
33
|
-
}
|
|
29
|
+
const getDefaultBucketName = () => mbkautheVar?.bucket || (availableBucketNames.length > 0 ? availableBucketNames[0] : null);
|
|
34
30
|
|
|
35
31
|
export function resolveBucketName(bucketName) {
|
|
36
32
|
const raw = typeof bucketName === 'string' ? bucketName.trim() : bucketName;
|
|
@@ -53,10 +49,7 @@ export function getAppName() {
|
|
|
53
49
|
return typeof app === 'string' && app.trim() ? app.trim() : '';
|
|
54
50
|
}
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
const app = String(appName || '').toLowerCase();
|
|
58
|
-
return app === 'portal' || app === 'mbkbucket';
|
|
59
|
-
}
|
|
52
|
+
const isRootModeApp = appName => ['portal', 'mbkbucket'].includes(String(appName || '').toLowerCase());
|
|
60
53
|
|
|
61
54
|
function validateKeySafety(str, isKey = false) {
|
|
62
55
|
if (isKey && !str) throw new Error('Key is required');
|
|
@@ -73,7 +66,7 @@ export function ensureKeyHasAppPrefix(key = '') {
|
|
|
73
66
|
validateKeySafety(key, true);
|
|
74
67
|
|
|
75
68
|
const app = getAppName();
|
|
76
|
-
|
|
69
|
+
const cleaned = trimLeadingSlashes(key);
|
|
77
70
|
if (isRootModeApp(app)) return cleaned;
|
|
78
71
|
if (!app) throw new Error('APP_NAME is not configured; set mbkautheVar.APP_NAME or MBKAUTHE_APP_NAME');
|
|
79
72
|
|
|
@@ -86,16 +79,14 @@ export function ensurePrefix(prefix = '') {
|
|
|
86
79
|
validateKeySafety(prefix, false);
|
|
87
80
|
|
|
88
81
|
const app = getAppName();
|
|
89
|
-
|
|
82
|
+
const p = trimLeadingSlashes(prefix);
|
|
90
83
|
if (isRootModeApp(app)) return p;
|
|
91
84
|
if (!app) throw new Error('APP_NAME is not configured; set mbkautheVar.APP_NAME or MBKAUTHE_APP_NAME');
|
|
92
|
-
if (!p) return app;
|
|
93
|
-
if (p === app || p === `${app}/`) return p;
|
|
85
|
+
if (!p || p === app || p === `${app}/`) return p || app;
|
|
94
86
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return `${app}/${p}`;
|
|
87
|
+
return p.startsWith(`${app}/`)
|
|
88
|
+
? p.replace(new RegExp(`^(?:${escapeRegExp(app)}\/)+`), `${app}/`)
|
|
89
|
+
: `${app}/${p}`;
|
|
99
90
|
}
|
|
100
91
|
|
|
101
92
|
// ---------------------------------------------------------------------------
|
package/lib/src/utils/errors.js
CHANGED
|
@@ -26,23 +26,15 @@ function matchError(rules, error, fallbackMessage) {
|
|
|
26
26
|
return { status: found?.status ?? 500, code: found?.code ?? 'INTERNAL_ERROR', message };
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function classifyViewError(error, fallbackMessage = 'Request failed') {
|
|
34
|
-
return matchError(VIEW_ERROR_RULES, error, fallbackMessage);
|
|
35
|
-
}
|
|
29
|
+
export const classifyApiError = (error, fallbackMessage = 'Request failed') => matchError(API_ERROR_RULES, error, fallbackMessage);
|
|
30
|
+
export const classifyViewError = (error, fallbackMessage = 'Request failed') => matchError(VIEW_ERROR_RULES, error, fallbackMessage);
|
|
36
31
|
|
|
37
32
|
export function sendApiError(res, error, fallbackMessage = 'Request failed') {
|
|
38
33
|
const { status, code, message } = classifyApiError(error, fallbackMessage);
|
|
39
34
|
return res.status(status).json({
|
|
40
35
|
success: false,
|
|
41
36
|
code,
|
|
42
|
-
error: {
|
|
43
|
-
code,
|
|
44
|
-
message,
|
|
45
|
-
},
|
|
37
|
+
error: { code, message },
|
|
46
38
|
message,
|
|
47
39
|
timestamp: new Date().toISOString(),
|
|
48
40
|
});
|
package/lib/src/utils/helpers.js
CHANGED
|
@@ -4,14 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
const HTML_ESCAPE_MAP = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' };
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
return String(value ?? '').replace(/[&<>"']/g, c => HTML_ESCAPE_MAP[c]);
|
|
9
|
-
}
|
|
7
|
+
export const escapeHtml = (value = '') => String(value ?? '').replace(/[&<>"']/g, c => HTML_ESCAPE_MAP[c]);
|
|
10
8
|
|
|
11
9
|
export function getBaseName(path = '') {
|
|
12
10
|
const value = String(path ?? '');
|
|
13
|
-
const
|
|
14
|
-
return
|
|
11
|
+
const lastSlash = value.lastIndexOf('/');
|
|
12
|
+
return lastSlash === -1 ? value : value.slice(lastSlash + 1);
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
export function getFileExt(fileName = '') {
|
|
@@ -20,13 +18,8 @@ export function getFileExt(fileName = '') {
|
|
|
20
18
|
return dotIndex === -1 ? '' : name.slice(dotIndex + 1).toLowerCase();
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function trimLeadingSlashes(str = '') {
|
|
28
|
-
return String(str ?? '').replace(/^\/+/, '');
|
|
29
|
-
}
|
|
21
|
+
export const trimSlashes = (str = '') => String(str ?? '').replace(/^\/+|\/+$/g, '');
|
|
22
|
+
export const trimLeadingSlashes = (str = '') => String(str ?? '').replace(/^\/+/, '');
|
|
30
23
|
|
|
31
24
|
export function getFolderPath(key = '') {
|
|
32
25
|
const s = String(key ?? '');
|
|
@@ -34,9 +27,7 @@ export function getFolderPath(key = '') {
|
|
|
34
27
|
return lastSlash === -1 ? '' : s.slice(0, lastSlash + 1);
|
|
35
28
|
}
|
|
36
29
|
|
|
37
|
-
export
|
|
38
|
-
return Array.isArray(rawKey) ? rawKey.join('/') : String(rawKey || '');
|
|
39
|
-
}
|
|
30
|
+
export const normalizeKeyParam = rawKey => Array.isArray(rawKey) ? rawKey.join('/') : String(rawKey || '');
|
|
40
31
|
|
|
41
32
|
export function buildKey(prefix, fileName) {
|
|
42
33
|
const cleanPrefix = trimSlashes(prefix);
|
|
@@ -44,15 +35,13 @@ export function buildKey(prefix, fileName) {
|
|
|
44
35
|
return cleanPrefix ? `${cleanPrefix}/${cleanName}` : cleanName;
|
|
45
36
|
}
|
|
46
37
|
|
|
47
|
-
export
|
|
48
|
-
return new Date().toISOString();
|
|
49
|
-
}
|
|
38
|
+
export const nowIso = () => new Date().toISOString();
|
|
50
39
|
|
|
51
40
|
export function formatBytes(bytes) {
|
|
52
|
-
if (!bytes
|
|
41
|
+
if (!bytes) return '0 B';
|
|
53
42
|
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
54
43
|
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
55
|
-
return `${(bytes /
|
|
44
|
+
return `${(bytes / 1024 ** i).toFixed(i > 0 ? 1 : 0)} ${units[i]}`;
|
|
56
45
|
}
|
|
57
46
|
|
|
58
47
|
export function formatDate(iso) {
|
|
@@ -67,25 +56,18 @@ export async function streamToBuffer(stream) {
|
|
|
67
56
|
if (Buffer.isBuffer(stream)) return stream;
|
|
68
57
|
const chunks = [];
|
|
69
58
|
if (stream?.[Symbol.asyncIterator] || stream?.transformToWeb) {
|
|
70
|
-
for await (const chunk of stream)
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
return Buffer.concat(chunks);
|
|
74
|
-
}
|
|
75
|
-
if (stream?.getReader) {
|
|
59
|
+
for await (const chunk of stream) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
60
|
+
} else if (stream?.getReader) {
|
|
76
61
|
const reader = stream.getReader();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (done) break;
|
|
80
|
-
chunks.push(Buffer.isBuffer(value) ? value : Buffer.from(value));
|
|
62
|
+
for (let res = await reader.read(); !res.done; res = await reader.read()) {
|
|
63
|
+
chunks.push(Buffer.isBuffer(res.value) ? res.value : Buffer.from(res.value));
|
|
81
64
|
}
|
|
82
|
-
return Buffer.concat(chunks);
|
|
83
65
|
}
|
|
84
66
|
return Buffer.concat(chunks);
|
|
85
67
|
}
|
|
86
68
|
|
|
87
69
|
export function destroyStream(stream) {
|
|
88
|
-
if (
|
|
70
|
+
if (typeof stream?.destroy === 'function') {
|
|
89
71
|
stream.removeAllListeners?.();
|
|
90
72
|
stream.destroy();
|
|
91
73
|
}
|
|
@@ -111,17 +93,10 @@ export const VIDEO_TYPES = new Set(['mp4', 'webm', 'ogg', 'avi', 'mov']);
|
|
|
111
93
|
export const AUDIO_TYPES = new Set(['mp3', 'wav', 'flac', 'aac', 'm4a']);
|
|
112
94
|
|
|
113
95
|
export const MIME_TYPES = {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// Videos
|
|
119
|
-
mp4: 'video/mp4', webm: 'video/webm', ogg: 'video/ogg',
|
|
120
|
-
avi: 'video/x-msvideo', mov: 'video/quicktime',
|
|
121
|
-
// Audio
|
|
122
|
-
mp3: 'audio/mpeg', wav: 'audio/wav', flac: 'audio/flac',
|
|
123
|
-
aac: 'audio/aac', m4a: 'audio/mp4',
|
|
124
|
-
// Text / Code
|
|
96
|
+
jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png', gif: 'image/gif',
|
|
97
|
+
webp: 'image/webp', svg: 'image/svg+xml', bmp: 'image/bmp', ico: 'image/x-icon',
|
|
98
|
+
mp4: 'video/mp4', webm: 'video/webm', ogg: 'video/ogg', avi: 'video/x-msvideo', mov: 'video/quicktime',
|
|
99
|
+
mp3: 'audio/mpeg', wav: 'audio/wav', flac: 'audio/flac', aac: 'audio/aac', m4a: 'audio/mp4',
|
|
125
100
|
txt: 'text/plain; charset=utf-8', md: 'text/markdown; charset=utf-8',
|
|
126
101
|
json: 'application/json; charset=utf-8', xml: 'application/xml; charset=utf-8',
|
|
127
102
|
csv: 'text/csv; charset=utf-8', log: 'text/plain; charset=utf-8',
|
|
@@ -137,14 +112,10 @@ export const MIME_TYPES = {
|
|
|
137
112
|
ps1: 'text/x-powershell; charset=utf-8', yaml: 'text/x-yaml; charset=utf-8',
|
|
138
113
|
yml: 'text/x-yaml; charset=utf-8', toml: 'text/x-toml; charset=utf-8',
|
|
139
114
|
ini: 'text/x-ini; charset=utf-8', conf: 'text/x-conf; charset=utf-8',
|
|
140
|
-
|
|
141
|
-
zip: 'application/zip', gz: 'application/gzip', tar: 'application/x-tar',
|
|
142
|
-
pdf: 'application/pdf'
|
|
115
|
+
zip: 'application/zip', gz: 'application/gzip', tar: 'application/x-tar', pdf: 'application/pdf'
|
|
143
116
|
};
|
|
144
117
|
|
|
145
|
-
export
|
|
146
|
-
return MIME_TYPES[getFileExt(fileName)] || fallback;
|
|
147
|
-
}
|
|
118
|
+
export const getMimeType = (fileName, fallback = 'application/octet-stream') => MIME_TYPES[getFileExt(fileName)] || fallback;
|
|
148
119
|
|
|
149
120
|
export function isSensitiveTextType(contentType = '') {
|
|
150
121
|
const type = String(contentType ?? '').toLowerCase();
|
|
@@ -154,8 +125,7 @@ export function isSensitiveTextType(contentType = '') {
|
|
|
154
125
|
export function buildCacheControl(contentType, { isStaticAsset = false, supportsRanges = false, publicCache = false } = {}) {
|
|
155
126
|
if (publicCache) {
|
|
156
127
|
if (isStaticAsset) return 'public, max-age=3600, immutable';
|
|
157
|
-
|
|
158
|
-
return 'public, max-age=300, must-revalidate';
|
|
128
|
+
return supportsRanges ? 'public, max-age=86400, must-revalidate' : 'public, max-age=300, must-revalidate';
|
|
159
129
|
}
|
|
160
130
|
if (isSensitiveTextType(contentType)) return 'private, no-store';
|
|
161
131
|
return supportsRanges ? 'private, max-age=1800, must-revalidate' : 'private, max-age=300, must-revalidate';
|
|
@@ -185,15 +155,11 @@ export function parseRangeHeader(rangeHeader, totalSize) {
|
|
|
185
155
|
} else {
|
|
186
156
|
start = parseInt(startStr, 10);
|
|
187
157
|
if (isNaN(start) || start < 0) return null;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
} else {
|
|
191
|
-
end = parseInt(endStr, 10);
|
|
192
|
-
if (isNaN(end) || end < start) return null;
|
|
193
|
-
}
|
|
158
|
+
end = endStr === '' ? Math.min(start + DEFAULT_CHUNK_SIZE - 1, totalSize - 1) : parseInt(endStr, 10);
|
|
159
|
+
if (isNaN(end) || end < start) return null;
|
|
194
160
|
}
|
|
195
161
|
|
|
196
|
-
if (start >= totalSize ||
|
|
162
|
+
if (start >= totalSize || end >= totalSize) return null;
|
|
197
163
|
return { start, end, total: totalSize, size: end - start + 1 };
|
|
198
164
|
}
|
|
199
165
|
|
|
@@ -201,8 +167,7 @@ export function parseRangeHeader(rangeHeader, totalSize) {
|
|
|
201
167
|
// Player page HTML template
|
|
202
168
|
// ---------------------------------------------------------------------------
|
|
203
169
|
|
|
204
|
-
export
|
|
205
|
-
return `<!doctype html>
|
|
170
|
+
export const renderPlayerPage = (safeFileName, encodedKey, bucketQuery) => `<!doctype html>
|
|
206
171
|
<html lang="en">
|
|
207
172
|
<head>
|
|
208
173
|
<meta charset="utf-8">
|
|
@@ -225,7 +190,6 @@ export function renderPlayerPage(safeFileName, encodedKey, bucketQuery) {
|
|
|
225
190
|
</div>
|
|
226
191
|
</body>
|
|
227
192
|
</html>`;
|
|
228
|
-
}
|
|
229
193
|
|
|
230
194
|
// ---------------------------------------------------------------------------
|
|
231
195
|
// Common Handlebars helpers
|
|
@@ -236,16 +200,13 @@ export const commonHandlebarsHelpers = {
|
|
|
236
200
|
neq: (a, b) => a !== b,
|
|
237
201
|
or: (...args) => args.slice(0, -1).some(Boolean),
|
|
238
202
|
and: (...args) => args.slice(0, -1).every(Boolean),
|
|
239
|
-
not:
|
|
203
|
+
not: val => !val,
|
|
240
204
|
gt: (a, b) => a > b,
|
|
241
205
|
gte: (a, b) => a >= b,
|
|
242
206
|
lt: (a, b) => a < b,
|
|
243
207
|
lte: (a, b) => a <= b,
|
|
244
208
|
includes: (arr, val) => Array.isArray(arr) && arr.includes(val),
|
|
245
|
-
json:
|
|
246
|
-
jsonStringify:
|
|
247
|
-
getInitials: (
|
|
248
|
-
if (!username) return '?';
|
|
249
|
-
return username.split(/[._]/).map(p => p.charAt(0)).join('').toUpperCase().slice(0, 2);
|
|
250
|
-
},
|
|
209
|
+
json: obj => JSON.stringify(obj, null, 2),
|
|
210
|
+
jsonStringify: obj => JSON.stringify(obj),
|
|
211
|
+
getInitials: username => username ? username.split(/[._]/).map(p => p.charAt(0)).join('').toUpperCase().slice(0, 2) : '?',
|
|
251
212
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mbkbucket",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "Flexible S3/R2 bucket management — library, Express router, and CLI for mbktech.org applications. Provides upload, download, listing, multipart utilities, signed URLs, and a command-line interface with built-in configuration validation and health checks",
|
|
5
5
|
"author": "Muhammad Bin Khalid",
|
|
6
6
|
"homepage": "https://github.com/MIbnEKhalid/mbkbucket#readme",
|
|
@@ -20,15 +20,15 @@
|
|
|
20
20
|
"#logger": "./lib/src/utils/logger.js"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@aws-sdk/client-s3": "^3.
|
|
24
|
-
"@aws-sdk/s3-request-presigner": "^3.
|
|
23
|
+
"@aws-sdk/client-s3": "^3.1127.0",
|
|
24
|
+
"@aws-sdk/s3-request-presigner": "^3.1127.0",
|
|
25
25
|
"compression": "^1.8.0",
|
|
26
26
|
"debug": "^4.4.3",
|
|
27
27
|
"dotenv": "^16.6.1",
|
|
28
28
|
"express": "^5.1.0",
|
|
29
29
|
"express-handlebars": "^9.0.1",
|
|
30
|
-
"express-rate-limit": "^7.5.
|
|
31
|
-
"mbkauthe": "^5.
|
|
30
|
+
"express-rate-limit": "^7.5.1",
|
|
31
|
+
"mbkauthe": "^5.10.0",
|
|
32
32
|
"multer": "^2.0.2",
|
|
33
33
|
"pg": "^8.16.3"
|
|
34
34
|
},
|