mbkbucket 3.3.0 → 3.3.2

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.
Files changed (39) hide show
  1. package/index.js +8 -18
  2. package/lib/cli.js +642 -0
  3. package/{public → lib/public}/bucketadmin.js +1 -1
  4. package/{src → lib/src}/app.js +37 -50
  5. package/{src → lib/src}/cli/auth-helper.js +24 -103
  6. package/lib/src/config/index.js +108 -0
  7. package/{src → lib/src}/config/validation.js +14 -30
  8. package/{src → lib/src}/controllers/api.controller.js +85 -176
  9. package/{src → lib/src}/controllers/dashboard.controller.js +12 -23
  10. package/{src → lib/src}/controllers/info.controller.js +17 -20
  11. package/{src → lib/src}/controllers/view.controller.js +23 -70
  12. package/{src → lib/src}/middleware/async-handler.js +1 -16
  13. package/{src → lib/src}/middleware/bucket-resolver.js +7 -13
  14. package/{src → lib/src}/middleware/error-handler.js +6 -14
  15. package/{src → lib/src}/middleware/rate-limiter.js +2 -10
  16. package/{src → lib/src}/middleware/security.js +1 -17
  17. package/lib/src/routes/api.routes.js +40 -0
  18. package/{src → lib/src}/routes/index.js +1 -9
  19. package/{src → lib/src}/routes/info.routes.js +2 -3
  20. package/{src → lib/src}/routes/view.routes.js +3 -8
  21. package/{src → lib/src}/services/s3.service.js +157 -349
  22. package/lib/src/utils/errors.js +45 -0
  23. package/lib/src/utils/helpers.js +251 -0
  24. package/package.json +18 -3
  25. package/.github/PACKAGE.md +0 -19
  26. package/.github/workflows/publish.yml +0 -88
  27. package/cli.js +0 -977
  28. package/index.d.ts +0 -444
  29. package/lib/index.js +0 -17
  30. package/src/config/index.js +0 -133
  31. package/src/routes/api.routes.js +0 -66
  32. package/src/utils/errors.js +0 -76
  33. package/src/utils/helpers.js +0 -197
  34. package/test/config-validation.test.js +0 -116
  35. /package/{public → lib/public}/bucketadmin.css +0 -0
  36. /package/{public → lib/public}/mbkbucket-helper-demo.html +0 -0
  37. /package/{public → lib/public}/mbkbucket-helper.css +0 -0
  38. /package/{public → lib/public}/mbkbucket-helper.js +0 -0
  39. /package/{src → lib/src}/utils/logger.js +0 -0
package/index.d.ts DELETED
@@ -1,444 +0,0 @@
1
- // Type definitions for mbkbucket
2
- // Project: https://github.com/MIbnEKhalid/mbkbucket
3
-
4
- import { Readable } from "stream";
5
- import { Router, Application } from "express";
6
-
7
- /**
8
- * Shared types used across the package
9
- */
10
- export interface BucketConfig {
11
- BUCKET_NAME: string;
12
- ENDPOINT?: string;
13
- ACCESS_KEY_ID?: string;
14
- SECRET_ACCESS_KEY?: string;
15
- region?: string;
16
- [key: string]: any;
17
- }
18
-
19
- export type BucketConnectionMap = Record<string, BucketConfig>;
20
-
21
- export interface S3ObjectResult {
22
- Body: Readable;
23
- ContentLength?: number;
24
- ContentType?: string;
25
- LastModified?: Date;
26
- Key?: string;
27
- [key: string]: any;
28
- }
29
-
30
- export interface UploadOptions {
31
- metadata?: Record<string, string>;
32
- cacheControl?: string;
33
- storageClass?: string;
34
- serverSideEncryption?: string;
35
- bucketName?: string;
36
- preventOverwrite?: boolean;
37
- [key: string]: any;
38
- }
39
-
40
- export interface ListFilesOptions {
41
- maxKeys?: number;
42
- continuationToken?: string | null;
43
- delimiter?: string | null;
44
- fetchOwner?: boolean;
45
- startAfter?: string | null;
46
- bucketName?: string;
47
- [key: string]: any;
48
- }
49
-
50
- export interface ListFilesResult extends Record<string, any> {
51
- requestedAt: string;
52
- totalFiles: number;
53
- hasMore: boolean;
54
- nextToken: string | null;
55
- }
56
-
57
- export interface IncompleteMultipartUpload {
58
- Key?: string;
59
- UploadId?: string;
60
- Initiated?: string;
61
- Initiator?: { DisplayName?: string; [key: string]: any };
62
- [key: string]: any;
63
- }
64
-
65
- export interface CleanupResult {
66
- abortedCount: number;
67
- uploads: Array<{ key: string; uploadId: string; initiated?: string }>;
68
- cleanedAt?: string;
69
- [key: string]: any;
70
- }
71
-
72
- export interface ConfigVars {
73
- publiView_enabled: boolean;
74
- p_view_inline: boolean;
75
- [key: string]: any;
76
- }
77
-
78
- /**
79
- * S3 exports (re-exported from lib/s3.js at package root)
80
- */
81
- export function getAvailableBucketNames(): string[];
82
- export function resolveBucketName(bucketName?: string | null): string;
83
- export function getBucketConfig(bucketName?: string): BucketConfig;
84
- export const bucketClient: any;
85
- export function getAppName(): string;
86
- export function ensureKeyHasAppPrefix(key?: string): string;
87
- export function ensurePrefix(prefix?: string): string;
88
- export function getBucketClient(bucketName?: string): any;
89
- export function checkHealth(): Promise<{ status: string; responseTime?: number; bucket?: string; error?: string; checkedAt: string; region?: string; }>;
90
-
91
- export function uploadFile(
92
- key: string,
93
- fileBuffer: Buffer | Uint8Array,
94
- contentType: string,
95
- options?: UploadOptions
96
- ): Promise<{ fileSize?: number; key: string; contentType?: string; uploadedAt?: string; } & Record<string, any>>;
97
-
98
- export function downloadFile(
99
- key: string,
100
- options?: {
101
- range?: string | null;
102
- ifNoneMatch?: string | null;
103
- ifModifiedSince?: Date | string | null;
104
- responseCacheControl?: string | null;
105
- responseContentType?: string | null;
106
- bucketName?: string;
107
- [key: string]: any;
108
- }
109
- ): Promise<S3ObjectResult>;
110
-
111
- export function deleteFile(key: string, bucketName?: string): Promise<{ key: string; deletedAt?: string } & Record<string, any>>;
112
-
113
- export function deleteFiles(keys: string[], bucketName?: string): Promise<{
114
- results: any[];
115
- deletedCount: number;
116
- errors: any[];
117
- deletedAt: string;
118
- }>;
119
-
120
- export function deleteFolder(prefix: string, bucketName?: string): Promise<{
121
- results?: any[];
122
- deletedCount: number;
123
- errors?: any[];
124
- deletedAt: string;
125
- prefix?: string;
126
- }>;
127
-
128
- export function listfiles(prefix?: string, options?: ListFilesOptions): Promise<ListFilesResult>;
129
-
130
- export function getFileMetadata(key: string, bucketName?: string): Promise<{
131
- key: string;
132
- exists: boolean;
133
- queriedAt: string;
134
- ContentLength?: number;
135
- ContentType?: string;
136
- LastModified?: Date;
137
- [key: string]: any;
138
- }>;
139
-
140
- export function fileExists(key: string, bucketName?: string): Promise<boolean>;
141
- export function getFileSize(key: string, bucketName?: string): Promise<number | null>;
142
-
143
- export function generateSignedUrl(
144
- key: string,
145
- operation?: "getObject" | "putObject" | string,
146
- expiresIn?: number,
147
- bucketName?: string
148
- ): Promise<{
149
- url: string;
150
- key: string;
151
- operation: string;
152
- expiresIn: number;
153
- expiresAt: string;
154
- generatedAt: string;
155
- }>;
156
-
157
- export function createMultipartUpload(
158
- key: string,
159
- contentType?: string,
160
- metadata?: Record<string, string>,
161
- bucketName?: string
162
- ): Promise<{ uploadId: string; key: string }>;
163
-
164
- export function uploadPart(
165
- key: string,
166
- uploadId: string,
167
- partNumber: number,
168
- buffer: Buffer | Uint8Array,
169
- bucketName?: string
170
- ): Promise<{ ETag: string; partNumber: number }>;
171
-
172
- export function completeMultipartUpload(
173
- key: string,
174
- uploadId: string,
175
- parts: Array<{ partNumber: number; ETag: string }>,
176
- bucketName?: string
177
- ): Promise<{ key: string }>;
178
-
179
- export function abortMultipartUpload(
180
- key: string,
181
- uploadId: string,
182
- bucketName?: string
183
- ): Promise<{ key: string; abortedAt: string }>;
184
-
185
- export function listIncompleteMultipartUploads(
186
- prefix?: string,
187
- bucketName?: string
188
- ): Promise<IncompleteMultipartUpload[]>;
189
-
190
- export function cleanupIncompleteMultipartUploads(
191
- olderThanDays?: number,
192
- prefix?: string,
193
- bucketName?: string
194
- ): Promise<CleanupResult>;
195
-
196
- /**
197
- * Config exports (re-exported from lib/config/index.js at package root)
198
- */
199
- export const packageJson: Record<string, any>;
200
- export const appVersion: string;
201
- export const mbkbucketVar: ConfigVars;
202
- export function getLatestVersion(): Promise<string | null>;
203
- export function checkVersion(): Promise<void>;
204
- export function parseAndValidateMbkbucketVar(rawValue?: string): ConfigVars;
205
- export function parseAndValidateBucketConnection(rawValue?: string): BucketConnectionMap | null;
206
-
207
- /**
208
- * Router export (re-exported from lib/routes/index.js at package root as `bucket`)
209
- */
210
- export const bucket: Router;
211
-
212
- /**
213
- * Root default export from index.js: configured Express application
214
- */
215
- declare const server: Application;
216
- export default server;
217
-
218
- /**
219
- * Subpath module declarations
220
- */
221
- declare module "mbkbucket/lib/s3" {
222
- import { Readable } from "stream";
223
-
224
- export interface BucketConfig {
225
- BUCKET_NAME: string;
226
- ENDPOINT?: string;
227
- ACCESS_KEY_ID?: string;
228
- SECRET_ACCESS_KEY?: string;
229
- region?: string;
230
- [key: string]: any;
231
- }
232
-
233
- export type BucketConnectionMap = Record<string, BucketConfig>;
234
-
235
- export interface S3ObjectResult {
236
- Body: Readable;
237
- ContentLength?: number;
238
- ContentType?: string;
239
- LastModified?: Date;
240
- Key?: string;
241
- [key: string]: any;
242
- }
243
-
244
- export interface UploadOptions {
245
- metadata?: Record<string, string>;
246
- cacheControl?: string;
247
- storageClass?: string;
248
- serverSideEncryption?: string;
249
- bucketName?: string;
250
- preventOverwrite?: boolean;
251
- [key: string]: any;
252
- }
253
-
254
- export interface ListFilesOptions {
255
- maxKeys?: number;
256
- continuationToken?: string | null;
257
- delimiter?: string | null;
258
- fetchOwner?: boolean;
259
- startAfter?: string | null;
260
- bucketName?: string;
261
- [key: string]: any;
262
- }
263
-
264
- export interface ListFilesResult extends Record<string, any> {
265
- requestedAt: string;
266
- totalFiles: number;
267
- hasMore: boolean;
268
- nextToken: string | null;
269
- }
270
-
271
- export interface IncompleteMultipartUpload {
272
- Key?: string;
273
- UploadId?: string;
274
- Initiated?: string;
275
- Initiator?: { DisplayName?: string; [key: string]: any };
276
- [key: string]: any;
277
- }
278
-
279
- export interface CleanupResult {
280
- abortedCount: number;
281
- uploads: Array<{ key: string; uploadId: string; initiated?: string }>;
282
- cleanedAt?: string;
283
- [key: string]: any;
284
- }
285
-
286
- export function getAvailableBucketNames(): string[];
287
- export function resolveBucketName(bucketName?: string | null): string;
288
- export function getBucketConfig(bucketName?: string): BucketConfig;
289
- export const bucketClient: any;
290
- export function getAppName(): string;
291
- export function ensureKeyHasAppPrefix(key?: string): string;
292
- export function ensurePrefix(prefix?: string): string;
293
- export function getBucketClient(bucketName?: string): any;
294
- export function checkHealth(): Promise<{ status: string; responseTime?: number; bucket?: string; error?: string; checkedAt: string; region?: string; }>;
295
-
296
- export function uploadFile(
297
- key: string,
298
- fileBuffer: Buffer | Uint8Array,
299
- contentType: string,
300
- options?: UploadOptions
301
- ): Promise<{ fileSize?: number; key: string; contentType?: string; uploadedAt?: string } & Record<string, any>>;
302
-
303
- export function downloadFile(
304
- key: string,
305
- options?: {
306
- range?: string | null;
307
- ifNoneMatch?: string | null;
308
- ifModifiedSince?: Date | string | null;
309
- responseCacheControl?: string | null;
310
- responseContentType?: string | null;
311
- bucketName?: string;
312
- [key: string]: any;
313
- }
314
- ): Promise<S3ObjectResult>;
315
-
316
- export function deleteFile(key: string, bucketName?: string): Promise<{ key: string; deletedAt?: string } & Record<string, any>>;
317
- export function deleteFiles(keys: string[], bucketName?: string): Promise<{
318
- results: any[];
319
- deletedCount: number;
320
- errors: any[];
321
- deletedAt: string;
322
- }>;
323
-
324
- export function deleteFolder(prefix: string, bucketName?: string): Promise<{
325
- results?: any[];
326
- deletedCount: number;
327
- errors?: any[];
328
- deletedAt: string;
329
- prefix?: string;
330
- }>;
331
-
332
- export function listfiles(prefix?: string, options?: ListFilesOptions): Promise<ListFilesResult>;
333
-
334
- export function getFileMetadata(key: string, bucketName?: string): Promise<{
335
- key: string;
336
- exists: boolean;
337
- queriedAt: string;
338
- ContentLength?: number;
339
- ContentType?: string;
340
- LastModified?: Date;
341
- [key: string]: any;
342
- }>;
343
-
344
- export function fileExists(key: string, bucketName?: string): Promise<boolean>;
345
- export function getFileSize(key: string, bucketName?: string): Promise<number | null>;
346
-
347
- export function generateSignedUrl(
348
- key: string,
349
- operation?: "getObject" | "putObject" | string,
350
- expiresIn?: number,
351
- bucketName?: string
352
- ): Promise<{
353
- url: string;
354
- key: string;
355
- operation: string;
356
- expiresIn: number;
357
- expiresAt: string;
358
- generatedAt: string;
359
- }>;
360
-
361
- export function createMultipartUpload(
362
- key: string,
363
- contentType?: string,
364
- metadata?: Record<string, string>,
365
- bucketName?: string
366
- ): Promise<{ uploadId: string; key: string }>;
367
-
368
- export function uploadPart(
369
- key: string,
370
- uploadId: string,
371
- partNumber: number,
372
- buffer: Buffer | Uint8Array,
373
- bucketName?: string
374
- ): Promise<{ ETag: string; partNumber: number }>;
375
-
376
- export function completeMultipartUpload(
377
- key: string,
378
- uploadId: string,
379
- parts: Array<{ partNumber: number; ETag: string }>,
380
- bucketName?: string
381
- ): Promise<{ key: string }>;
382
-
383
- export function abortMultipartUpload(
384
- key: string,
385
- uploadId: string,
386
- bucketName?: string
387
- ): Promise<{ key: string; abortedAt: string }>;
388
-
389
- export function listIncompleteMultipartUploads(
390
- prefix?: string,
391
- bucketName?: string
392
- ): Promise<IncompleteMultipartUpload[]>;
393
-
394
- export function cleanupIncompleteMultipartUploads(
395
- olderThanDays?: number,
396
- prefix?: string,
397
- bucketName?: string
398
- ): Promise<CleanupResult>;
399
- }
400
-
401
- declare module "mbkbucket/lib/config/index" {
402
- export interface ConfigVars {
403
- publiView_enabled: boolean;
404
- p_view_inline: boolean;
405
- [key: string]: any;
406
- }
407
-
408
- export interface BucketConfig {
409
- BUCKET_NAME: string;
410
- ENDPOINT?: string;
411
- ACCESS_KEY_ID?: string;
412
- SECRET_ACCESS_KEY?: string;
413
- region?: string;
414
- [key: string]: any;
415
- }
416
-
417
- export type BucketConnectionMap = Record<string, BucketConfig>;
418
-
419
- export const packageJson: Record<string, any>;
420
- export const appVersion: string;
421
- export const mbkbucketVar: ConfigVars;
422
- export function getLatestVersion(): Promise<string | null>;
423
- export function checkVersion(): Promise<void>;
424
- export function parseAndValidateMbkbucketVar(rawValue?: string): ConfigVars;
425
- export function parseAndValidateBucketConnection(rawValue?: string): BucketConnectionMap | null;
426
- }
427
-
428
- declare module "mbkbucket/lib/config/validation" {
429
- export function normalizeBooleanLike(value: any): any;
430
- export function parseAndValidateMbkbucketVar(rawValue?: string): { [key: string]: any };
431
- export function parseAndValidateBucketConnection(rawValue?: string): Record<string, any> | null;
432
- }
433
-
434
- declare module "mbkbucket/lib/routes/index" {
435
- import { Router } from "express";
436
- const router: Router;
437
- export default router;
438
- }
439
-
440
- declare module "mbkbucket/lib/bucket" {
441
- import { Router } from "express";
442
- const router: Router;
443
- export default router;
444
- }
package/lib/index.js DELETED
@@ -1,17 +0,0 @@
1
- // Barrel file: re-export all public items from the restructured src/ directory
2
- export * from '../src/services/s3.service.js';
3
- export * from '../src/config/index.js';
4
- export { default as bucket } from '../src/routes/index.js';
5
-
6
- import * as s3 from '../src/services/s3.service.js';
7
- import * as config from '../src/config/index.js';
8
- import bucket from '../src/routes/index.js';
9
-
10
- // Default aggregate export for convenience
11
- const defaultExport = {
12
- ...s3,
13
- ...config,
14
- bucket,
15
- };
16
-
17
- export default defaultExport;
@@ -1,133 +0,0 @@
1
- import { createRequire } from "module";
2
- import dotenv from "dotenv";
3
- import { parseAndValidateMbkbucketVar, parseAndValidateBucketConnection } from "./validation.js";
4
- import { createLogger } from "../utils/logger.js";
5
-
6
- dotenv.config();
7
- const debugConfig = createLogger('config');
8
-
9
- // Load package.json from mbkbucket package (not parent project)
10
- const require = createRequire(import.meta.url);
11
- let packageJson;
12
- try {
13
- // Try to load from mbkbucket package directory
14
- packageJson = require("mbkbucket/package.json");
15
- } catch {
16
- // Fallback to relative path (for development/testing)
17
- packageJson = require("../../package.json");
18
- }
19
-
20
- // Parent project version
21
- let appVersion;
22
- try {
23
- appVersion = require("../../../../package.json")?.version || "unknown";
24
- } catch {
25
- // Fallback if path doesn't work
26
- try {
27
- appVersion = require(process.cwd() + "/package.json")?.version || "unknown";
28
- } catch {
29
- appVersion = "unknown";
30
- }
31
- }
32
-
33
- function compareVersions(a, b) {
34
- const left = String(a || '').split(/[.-]/).map((part) => parseInt(part, 10) || 0);
35
- const right = String(b || '').split(/[.-]/).map((part) => parseInt(part, 10) || 0);
36
- const length = Math.max(left.length, right.length);
37
-
38
- for (let i = 0; i < length; i += 1) {
39
- const diff = (left[i] || 0) - (right[i] || 0);
40
- if (diff !== 0) return diff;
41
- }
42
- return 0;
43
- }
44
-
45
- // Fetch latest version from GitHub
46
- async function getLatestVersion() {
47
- try {
48
- const response = await fetch('https://raw.githubusercontent.com/MIbnEKhalid/mbkbucket/master/package.json');
49
- if (!response.ok) {
50
- debugConfig('GitHub API responded with status %s', response.status);
51
- return "0.0.0";
52
- }
53
-
54
- const latestPackageJson = await response.json();
55
- return latestPackageJson.version;
56
- } catch (error) {
57
- debugConfig('Error fetching latest version from GitHub: %s', error.message);
58
- return null;
59
- }
60
- }
61
-
62
- // Version check with error handling
63
- async function checkVersion() {
64
- try {
65
- const latestVersion = await getLatestVersion();
66
- if (latestVersion && compareVersions(latestVersion, packageJson.version) > 0) {
67
- debugConfig('Current version (%s) is outdated. Latest version: %s.', packageJson.version, latestVersion);
68
- } else if (latestVersion && compareVersions(latestVersion, packageJson.version) < 0) {
69
- debugConfig('Current version (%s) is newer than published version: %s.', packageJson.version, latestVersion);
70
- } else if (latestVersion) {
71
- debugConfig('Running latest version (%s).', packageJson.version);
72
- }
73
- } catch (error) {
74
- debugConfig('Failed to check for updates: %s', error.message);
75
- }
76
- }
77
-
78
- // Comprehensive validation function
79
- function validateConfiguration() {
80
- try {
81
- const parsed = parseAndValidateMbkbucketVar(process.env.mbkbucketVar);
82
- if (!process.env.mbkbucketVar) {
83
- debugConfig('mbkbucketVar not defined, using defaults');
84
- }
85
- debugConfig('Configuration loaded');
86
- return parsed;
87
- } catch (error) {
88
- throw new Error(`[mbkbucket] Configuration Validation Failed:\n - ${error.message}`);
89
- }
90
- }
91
-
92
- // Validate BucketConnection configuration
93
- function validateBucketConnection() {
94
- if (!process.env.BucketConnection) {
95
- console.warn(`[mbkbucket] ⚠️ BucketConnection not configured. You need to set this environment variable.`);
96
- console.warn(`[mbkbucket] Example format:`);
97
- console.warn(`[mbkbucket] BucketConnection={"r2":{"BUCKET_NAME":"my-bucket","ACCESS_KEY_ID":"key","SECRET_ACCESS_KEY":"secret","ENDPOINT":"https://..."}}`);
98
- return;
99
- }
100
-
101
- try {
102
- parseAndValidateBucketConnection(process.env.BucketConnection);
103
- debugConfig('BucketConnection configuration validated successfully');
104
- } catch (error) {
105
- throw new Error(`[mbkbucket] BucketConnection validation failed:\n - ${error.message}`);
106
- }
107
- }
108
-
109
- // Validate all configuration at startup
110
- function validateAllConfiguration() {
111
- try {
112
- validateConfiguration();
113
- validateBucketConnection();
114
- debugConfig('All configurations validated successfully');
115
- return true;
116
- } catch (error) {
117
- console.error(error.message);
118
- return false;
119
- }
120
- }
121
-
122
- const mbkbucketVar = validateConfiguration();
123
-
124
- export {
125
- packageJson,
126
- appVersion,
127
- mbkbucketVar,
128
- checkVersion,
129
- getLatestVersion,
130
- validateConfiguration,
131
- validateBucketConnection,
132
- validateAllConfiguration
133
- };
@@ -1,66 +0,0 @@
1
- import express from "express";
2
- import { sessRole } from "mbkauthe";
3
- import multer from "multer";
4
- import { requireBucketApi } from "../middleware/bucket-resolver.js";
5
- import {
6
- cleanupUploads, listIncompleteUploads, listFiles,
7
- uploadSingleFile, initiateMultipartUpload, uploadChunk,
8
- completeUpload, abortUpload, createFolder, deleteItems,
9
- downloadFileHandler
10
- } from "../controllers/api.controller.js";
11
-
12
- const router = express.Router();
13
-
14
- const MAX_CHUNK_SIZE = 50 * 1024 * 1024; // 50 MB
15
-
16
- const upload = multer({
17
- storage: multer.memoryStorage(),
18
- limits: { fileSize: MAX_CHUNK_SIZE }
19
- });
20
-
21
- const uploadChunkMiddleware = (req, res, next) => {
22
- upload.single('chunk')(req, res, (err) => {
23
- if (err) {
24
- if (err.code === 'LIMIT_FILE_SIZE') {
25
- return res.status(413).json({
26
- success: false,
27
- error: `Chunk too large (max ${Math.round(MAX_CHUNK_SIZE / (1024 * 1024))} MB).`,
28
- });
29
- }
30
- return next(err);
31
- }
32
- next();
33
- });
34
- };
35
-
36
- // Bucket guard for all API routes
37
- router.use(requireBucketApi);
38
-
39
- // Multipart upload cleanup
40
- router.post('/api/cleanup-uploads', sessRole('SuperAdmin'), cleanupUploads);
41
-
42
- // List incomplete multipart uploads
43
- router.get('/api/incomplete-uploads', sessRole('SuperAdmin'), listIncompleteUploads);
44
-
45
- // List files
46
- router.get('/api/files', sessRole('SuperAdmin'), listFiles);
47
-
48
- // Single-file upload
49
- router.post('/upload', sessRole('SuperAdmin'), upload.single('file'), uploadSingleFile);
50
-
51
- // Multipart upload flow
52
- router.post('/upload-init', sessRole('SuperAdmin'), initiateMultipartUpload);
53
- router.post('/upload-chunk', sessRole('SuperAdmin'), uploadChunkMiddleware, uploadChunk);
54
- router.post('/upload-complete', sessRole('SuperAdmin'), completeUpload);
55
- router.post('/upload-abort', sessRole('SuperAdmin'), abortUpload);
56
-
57
- // Folder operations
58
- router.post('/create-folder', sessRole('SuperAdmin'), createFolder);
59
-
60
- // Delete operations
61
- router.post('/delete', sessRole('SuperAdmin'), deleteItems);
62
-
63
- // Download
64
- router.get('/download/*key', sessRole('SuperAdmin'), downloadFileHandler);
65
-
66
- export default router;