mbkbucket 4.0.0 → 4.0.1

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.
@@ -1,217 +1,217 @@
1
- /**
2
- * MBKBucket - Core Storage Provider Interface
3
- * Copyright (c) 2026 Muhammad Bin Khalid, MBKTech.org and contributors
4
- * Licensed under the MIT License.
5
- */
6
-
7
- import { StorageUnsupportedOperationError } from "./errors.js";
8
-
9
- /**
10
- * Abstract base class for storage providers (S3, Cloudflare R2, Google Drive, Azure, etc.)
11
- */
12
- export class StorageProvider {
13
- /**
14
- * @param {string} name - Connection/Bucket name identifier
15
- * @param {object} config - Provider-specific configuration
16
- */
17
- constructor(name, config = {}) {
18
- if (new.target === StorageProvider) {
19
- throw new TypeError("Cannot construct StorageProvider instances directly");
20
- }
21
- this.name = name;
22
- this.config = Object.freeze({ ...config });
23
- }
24
-
25
- /**
26
- * Provider type identifier (e.g. 's3', 'gdrive', 'r2')
27
- * @returns {string}
28
- */
29
- get type() {
30
- return 'generic';
31
- }
32
-
33
- /**
34
- * Explicit provider capabilities.
35
- * @returns {object}
36
- */
37
- get capabilities() {
38
- return {
39
- multipart: false,
40
- presignedUrls: false,
41
- nativeFolders: false,
42
- ranges: true,
43
- copy: false,
44
- move: false,
45
- search: false,
46
- directDownloadUrl: false
47
- };
48
- }
49
-
50
- /**
51
- * List files and folders at the given prefix/path.
52
- * @param {string} [prefix='']
53
- * @param {object} [options={}]
54
- * @returns {Promise<import('./models.js').StorageListResult>}
55
- */
56
- async listFiles(prefix = '', options = {}) {
57
- throw new StorageUnsupportedOperationError(`listFiles() not implemented by ${this.constructor.name}`);
58
- }
59
-
60
- /**
61
- * Upload a file.
62
- * @param {string} key
63
- * @param {Buffer|Uint8Array|import('node:stream').Readable} fileBuffer
64
- * @param {string} contentType
65
- * @param {object} [options={}]
66
- * @returns {Promise<{ key: string, fileSize: number, contentType: string, uploadedAt: string, [key: string]: any }>}
67
- */
68
- async uploadFile(key, fileBuffer, contentType, options = {}) {
69
- throw new StorageUnsupportedOperationError(`uploadFile() not implemented by ${this.constructor.name}`);
70
- }
71
-
72
- /**
73
- * Download a file.
74
- * @param {string} key
75
- * @param {object} [options={}]
76
- * @returns {Promise<{ Body: import('node:stream').Readable, ContentType?: string, ContentLength?: number, ETag?: string, LastModified?: Date, notModified?: boolean, key: string }>}
77
- */
78
- async downloadFile(key, options = {}) {
79
- throw new StorageUnsupportedOperationError(`downloadFile() not implemented by ${this.constructor.name}`);
80
- }
81
-
82
- /**
83
- * Delete a single file.
84
- * @param {string} key
85
- * @param {object} [options={}]
86
- * @returns {Promise<{ key: string, deletedAt: string, [key: string]: any }>}
87
- */
88
- async deleteFile(key, options = {}) {
89
- throw new StorageUnsupportedOperationError(`deleteFile() not implemented by ${this.constructor.name}`);
90
- }
91
-
92
- /**
93
- * Delete multiple files.
94
- * @param {string[]} keys
95
- * @param {object} [options={}]
96
- * @returns {Promise<{ results: any[], deletedCount: number, errors: any[], deletedAt: string }>}
97
- */
98
- async deleteFiles(keys, options = {}) {
99
- let deletedCount = 0;
100
- const errors = [];
101
- const results = [];
102
- for (const key of keys) {
103
- try {
104
- const res = await this.deleteFile(key, options);
105
- results.push(res);
106
- deletedCount++;
107
- } catch (err) {
108
- errors.push({ key, error: err.message });
109
- }
110
- }
111
- return { results, deletedCount, errors, deletedAt: new Date().toISOString() };
112
- }
113
-
114
- /**
115
- * Delete a folder and its contents.
116
- * @param {string} prefix
117
- * @param {object} [options={}]
118
- * @returns {Promise<{ deletedCount: number, prefix: string, deletedAt: string }>}
119
- */
120
- async deleteFolder(prefix, options = {}) {
121
- throw new StorageUnsupportedOperationError(`deleteFolder() not implemented by ${this.constructor.name}`);
122
- }
123
-
124
- /**
125
- * Create a folder.
126
- * @param {string} key
127
- * @param {object} [options={}]
128
- * @returns {Promise<{ key: string, success: boolean, [key: string]: any }>}
129
- */
130
- async createFolder(key, options = {}) {
131
- throw new StorageUnsupportedOperationError(`createFolder() not implemented by ${this.constructor.name}`);
132
- }
133
-
134
- /**
135
- * Get file metadata.
136
- * @param {string} key
137
- * @param {object} [options={}]
138
- * @returns {Promise<{ key: string, exists: boolean, ContentLength?: number, ContentType?: string, LastModified?: Date, ETag?: string, Metadata?: object, queriedAt: string }>}
139
- */
140
- async getFileMetadata(key, options = {}) {
141
- throw new StorageUnsupportedOperationError(`getFileMetadata() not implemented by ${this.constructor.name}`);
142
- }
143
-
144
- /**
145
- * Check if a file exists.
146
- * @param {string} key
147
- * @param {object} [options={}]
148
- * @returns {Promise<boolean>}
149
- */
150
- async fileExists(key, options = {}) {
151
- try {
152
- const meta = await this.getFileMetadata(key, options);
153
- return Boolean(meta?.exists);
154
- } catch {
155
- return false;
156
- }
157
- }
158
-
159
- /**
160
- * Get file size in bytes.
161
- * @param {string} key
162
- * @param {object} [options={}]
163
- * @returns {Promise<number|null>}
164
- */
165
- async getFileSize(key, options = {}) {
166
- try {
167
- const meta = await this.getFileMetadata(key, options);
168
- return meta?.exists ? (meta.ContentLength ?? null) : null;
169
- } catch {
170
- return null;
171
- }
172
- }
173
-
174
- /**
175
- * Generate a signed or temporary access URL if supported.
176
- * @param {string} key
177
- * @param {'getObject'|'putObject'} [operation='getObject']
178
- * @param {number} [expiresIn=3600]
179
- * @param {object} [options={}]
180
- * @returns {Promise<{ url: string, key: string, operation: string, expiresIn: number, expiresAt: string, generatedAt: string }>}
181
- */
182
- async generateSignedUrl(key, operation = 'getObject', expiresIn = 3600, options = {}) {
183
- throw new StorageUnsupportedOperationError(`generateSignedUrl() is not supported by provider ${this.type}`);
184
- }
185
-
186
- /**
187
- * Copy a file.
188
- * @param {string} sourceKey
189
- * @param {string} destKey
190
- * @param {object} [options={}]
191
- * @returns {Promise<{ sourceKey: string, destKey: string, copiedAt: string }>}
192
- */
193
- async copyFile(sourceKey, destKey, options = {}) {
194
- throw new StorageUnsupportedOperationError(`copyFile() is not supported by provider ${this.type}`);
195
- }
196
-
197
- /**
198
- * Move a file.
199
- * @param {string} sourceKey
200
- * @param {string} destKey
201
- * @param {object} [options={}]
202
- * @returns {Promise<{ sourceKey: string, destKey: string, movedAt: string }>}
203
- */
204
- async moveFile(sourceKey, destKey, options = {}) {
205
- await this.copyFile(sourceKey, destKey, options);
206
- await this.deleteFile(sourceKey, options);
207
- return { sourceKey, destKey, movedAt: new Date().toISOString() };
208
- }
209
-
210
- /**
211
- * Run health check.
212
- * @returns {Promise<{ status: 'healthy'|'unhealthy', responseTime?: number, error?: string, [key: string]: any }>}
213
- */
214
- async checkHealth() {
215
- throw new StorageUnsupportedOperationError(`checkHealth() not implemented by ${this.constructor.name}`);
216
- }
217
- }
1
+ /**
2
+ * MBKBucket - Core Storage Provider Interface
3
+ * Copyright (c) 2026 Muhammad Bin Khalid, MBKTech.org and contributors
4
+ * Licensed under the MIT License.
5
+ */
6
+
7
+ import { StorageUnsupportedOperationError } from "./errors.js";
8
+
9
+ /**
10
+ * Abstract base class for storage providers (S3, Cloudflare R2, Google Drive, Azure, etc.)
11
+ */
12
+ export class StorageProvider {
13
+ /**
14
+ * @param {string} name - Connection/Bucket name identifier
15
+ * @param {object} config - Provider-specific configuration
16
+ */
17
+ constructor(name, config = {}) {
18
+ if (new.target === StorageProvider) {
19
+ throw new TypeError("Cannot construct StorageProvider instances directly");
20
+ }
21
+ this.name = name;
22
+ this.config = Object.freeze({ ...config });
23
+ }
24
+
25
+ /**
26
+ * Provider type identifier (e.g. 's3', 'gdrive', 'r2')
27
+ * @returns {string}
28
+ */
29
+ get type() {
30
+ return 'generic';
31
+ }
32
+
33
+ /**
34
+ * Explicit provider capabilities.
35
+ * @returns {object}
36
+ */
37
+ get capabilities() {
38
+ return {
39
+ multipart: false,
40
+ presignedUrls: false,
41
+ nativeFolders: false,
42
+ ranges: true,
43
+ copy: false,
44
+ move: false,
45
+ search: false,
46
+ directDownloadUrl: false
47
+ };
48
+ }
49
+
50
+ /**
51
+ * List files and folders at the given prefix/path.
52
+ * @param {string} [prefix='']
53
+ * @param {object} [options={}]
54
+ * @returns {Promise<import('./models.js').StorageListResult>}
55
+ */
56
+ async listFiles(prefix = '', options = {}) {
57
+ throw new StorageUnsupportedOperationError(`listFiles() not implemented by ${this.constructor.name}`);
58
+ }
59
+
60
+ /**
61
+ * Upload a file.
62
+ * @param {string} key
63
+ * @param {Buffer|Uint8Array|import('node:stream').Readable} fileBuffer
64
+ * @param {string} contentType
65
+ * @param {object} [options={}]
66
+ * @returns {Promise<{ key: string, fileSize: number, contentType: string, uploadedAt: string, [key: string]: any }>}
67
+ */
68
+ async uploadFile(key, fileBuffer, contentType, options = {}) {
69
+ throw new StorageUnsupportedOperationError(`uploadFile() not implemented by ${this.constructor.name}`);
70
+ }
71
+
72
+ /**
73
+ * Download a file.
74
+ * @param {string} key
75
+ * @param {object} [options={}]
76
+ * @returns {Promise<{ Body: import('node:stream').Readable, ContentType?: string, ContentLength?: number, ETag?: string, LastModified?: Date, notModified?: boolean, key: string }>}
77
+ */
78
+ async downloadFile(key, options = {}) {
79
+ throw new StorageUnsupportedOperationError(`downloadFile() not implemented by ${this.constructor.name}`);
80
+ }
81
+
82
+ /**
83
+ * Delete a single file.
84
+ * @param {string} key
85
+ * @param {object} [options={}]
86
+ * @returns {Promise<{ key: string, deletedAt: string, [key: string]: any }>}
87
+ */
88
+ async deleteFile(key, options = {}) {
89
+ throw new StorageUnsupportedOperationError(`deleteFile() not implemented by ${this.constructor.name}`);
90
+ }
91
+
92
+ /**
93
+ * Delete multiple files.
94
+ * @param {string[]} keys
95
+ * @param {object} [options={}]
96
+ * @returns {Promise<{ results: any[], deletedCount: number, errors: any[], deletedAt: string }>}
97
+ */
98
+ async deleteFiles(keys, options = {}) {
99
+ let deletedCount = 0;
100
+ const errors = [];
101
+ const results = [];
102
+ for (const key of keys) {
103
+ try {
104
+ const res = await this.deleteFile(key, options);
105
+ results.push(res);
106
+ deletedCount++;
107
+ } catch (err) {
108
+ errors.push({ key, error: err.message });
109
+ }
110
+ }
111
+ return { results, deletedCount, errors, deletedAt: new Date().toISOString() };
112
+ }
113
+
114
+ /**
115
+ * Delete a folder and its contents.
116
+ * @param {string} prefix
117
+ * @param {object} [options={}]
118
+ * @returns {Promise<{ deletedCount: number, prefix: string, deletedAt: string }>}
119
+ */
120
+ async deleteFolder(prefix, options = {}) {
121
+ throw new StorageUnsupportedOperationError(`deleteFolder() not implemented by ${this.constructor.name}`);
122
+ }
123
+
124
+ /**
125
+ * Create a folder.
126
+ * @param {string} key
127
+ * @param {object} [options={}]
128
+ * @returns {Promise<{ key: string, success: boolean, [key: string]: any }>}
129
+ */
130
+ async createFolder(key, options = {}) {
131
+ throw new StorageUnsupportedOperationError(`createFolder() not implemented by ${this.constructor.name}`);
132
+ }
133
+
134
+ /**
135
+ * Get file metadata.
136
+ * @param {string} key
137
+ * @param {object} [options={}]
138
+ * @returns {Promise<{ key: string, exists: boolean, ContentLength?: number, ContentType?: string, LastModified?: Date, ETag?: string, Metadata?: object, queriedAt: string }>}
139
+ */
140
+ async getFileMetadata(key, options = {}) {
141
+ throw new StorageUnsupportedOperationError(`getFileMetadata() not implemented by ${this.constructor.name}`);
142
+ }
143
+
144
+ /**
145
+ * Check if a file exists.
146
+ * @param {string} key
147
+ * @param {object} [options={}]
148
+ * @returns {Promise<boolean>}
149
+ */
150
+ async fileExists(key, options = {}) {
151
+ try {
152
+ const meta = await this.getFileMetadata(key, options);
153
+ return Boolean(meta?.exists);
154
+ } catch {
155
+ return false;
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Get file size in bytes.
161
+ * @param {string} key
162
+ * @param {object} [options={}]
163
+ * @returns {Promise<number|null>}
164
+ */
165
+ async getFileSize(key, options = {}) {
166
+ try {
167
+ const meta = await this.getFileMetadata(key, options);
168
+ return meta?.exists ? (meta.ContentLength ?? null) : null;
169
+ } catch {
170
+ return null;
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Generate a signed or temporary access URL if supported.
176
+ * @param {string} key
177
+ * @param {'getObject'|'putObject'} [operation='getObject']
178
+ * @param {number} [expiresIn=3600]
179
+ * @param {object} [options={}]
180
+ * @returns {Promise<{ url: string, key: string, operation: string, expiresIn: number, expiresAt: string, generatedAt: string }>}
181
+ */
182
+ async generateSignedUrl(key, operation = 'getObject', expiresIn = 3600, options = {}) {
183
+ throw new StorageUnsupportedOperationError(`generateSignedUrl() is not supported by provider ${this.type}`);
184
+ }
185
+
186
+ /**
187
+ * Copy a file.
188
+ * @param {string} sourceKey
189
+ * @param {string} destKey
190
+ * @param {object} [options={}]
191
+ * @returns {Promise<{ sourceKey: string, destKey: string, copiedAt: string }>}
192
+ */
193
+ async copyFile(sourceKey, destKey, options = {}) {
194
+ throw new StorageUnsupportedOperationError(`copyFile() is not supported by provider ${this.type}`);
195
+ }
196
+
197
+ /**
198
+ * Move a file.
199
+ * @param {string} sourceKey
200
+ * @param {string} destKey
201
+ * @param {object} [options={}]
202
+ * @returns {Promise<{ sourceKey: string, destKey: string, movedAt: string }>}
203
+ */
204
+ async moveFile(sourceKey, destKey, options = {}) {
205
+ await this.copyFile(sourceKey, destKey, options);
206
+ await this.deleteFile(sourceKey, options);
207
+ return { sourceKey, destKey, movedAt: new Date().toISOString() };
208
+ }
209
+
210
+ /**
211
+ * Run health check.
212
+ * @returns {Promise<{ status: 'healthy'|'unhealthy', responseTime?: number, error?: string, [key: string]: any }>}
213
+ */
214
+ async checkHealth() {
215
+ throw new StorageUnsupportedOperationError(`checkHealth() not implemented by ${this.constructor.name}`);
216
+ }
217
+ }
@@ -1,37 +1,37 @@
1
- import { resolveStorageName } from "../services/storage.service.js";
2
- import { sendApiError, sendViewError } from "../utils/errors.js";
3
-
4
- const NO_BUCKET_MSG = 'No storage connection selected. Provide ?bucket=<name> or configure a default bucket in mbkautheVar.bucket.';
5
-
6
- /**
7
- * Resolves `?bucket=<name>` query param and attaches `req.activeBucket` and `req.bucketResolveError`.
8
- */
9
- export function bucketResolver(req, _res, next) {
10
- try {
11
- req.activeBucket = resolveStorageName(req.query.bucket);
12
- req.bucketResolveError = null;
13
- } catch (err) {
14
- req.activeBucket = null;
15
- req.bucketResolveError = err;
16
- }
17
- next();
18
- }
19
-
20
- /**
21
- * Guard middleware for API routes — returns 400/503 JSON if bucket is invalid.
22
- */
23
- export function requireBucketApi(req, res, next) {
24
- if (req.bucketResolveError) return sendApiError(res, req.bucketResolveError, 'Invalid storage connection');
25
- if (!req.activeBucket) return sendApiError(res, new Error(NO_BUCKET_MSG));
26
- next();
27
- }
28
-
29
- /**
30
- * Guard middleware for view routes — returns 400/503 JSON if bucket is invalid (skips /p_view/...).
31
- */
32
- export function requireBucketView(req, res, next) {
33
- if (req.path.includes('/p_view/') || req.url.startsWith('/p_view/') || req.originalUrl?.includes('/p_view/')) return next();
34
- if (req.bucketResolveError) return sendViewError(res, req.bucketResolveError, 'Invalid storage connection');
35
- if (!req.activeBucket) return sendViewError(res, new Error(NO_BUCKET_MSG));
36
- next();
37
- }
1
+ import { resolveStorageName } from "../services/storage.service.js";
2
+ import { sendApiError, sendViewError } from "../utils/errors.js";
3
+
4
+ const NO_BUCKET_MSG = 'No storage connection selected. Provide ?bucket=<name> or configure a default bucket in mbkautheVar.bucket.';
5
+
6
+ /**
7
+ * Resolves `?bucket=<name>` query param and attaches `req.activeBucket` and `req.bucketResolveError`.
8
+ */
9
+ export function bucketResolver(req, _res, next) {
10
+ try {
11
+ req.activeBucket = resolveStorageName(req.query.bucket);
12
+ req.bucketResolveError = null;
13
+ } catch (err) {
14
+ req.activeBucket = null;
15
+ req.bucketResolveError = err;
16
+ }
17
+ next();
18
+ }
19
+
20
+ /**
21
+ * Guard middleware for API routes — returns 400/503 JSON if bucket is invalid.
22
+ */
23
+ export function requireBucketApi(req, res, next) {
24
+ if (req.bucketResolveError) return sendApiError(res, req.bucketResolveError, 'Invalid storage connection');
25
+ if (!req.activeBucket) return sendApiError(res, new Error(NO_BUCKET_MSG));
26
+ next();
27
+ }
28
+
29
+ /**
30
+ * Guard middleware for view routes — returns 400/503 JSON if bucket is invalid (skips /p_view/...).
31
+ */
32
+ export function requireBucketView(req, res, next) {
33
+ if (req.path.includes('/p_view/') || req.url.startsWith('/p_view/') || req.originalUrl?.includes('/p_view/')) return next();
34
+ if (req.bucketResolveError) return sendViewError(res, req.bucketResolveError, 'Invalid storage connection');
35
+ if (!req.activeBucket) return sendViewError(res, new Error(NO_BUCKET_MSG));
36
+ next();
37
+ }
@@ -1,60 +1,60 @@
1
- /**
2
- * MBKBucket
3
- * Copyright (c) 2026 Muhammad Bin Khalid, MBKTech.org and contributors
4
- * Licensed under the MIT License.
5
- * Source: https://github.com/MIbnEKhalid/mbkbucket
6
- */
7
-
8
- import express from "express";
9
- import { sessRole } from "mbkauthe";
10
- import path from "path";
11
- import { fileURLToPath } from "url";
12
- import { bucketResolver } from "../middleware/bucket-resolver.js";
13
- import { renderBucketDashboard } from "../controllers/dashboard.controller.js";
14
- import infoRoutes from "./info.routes.js";
15
- import { createViewRoutes } from "./view.routes.js";
16
- import { createApiRoutes } from "./api.routes.js";
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
-
29
- export function createBucketRouter({ authorization, publiViewEnabled } = {}) {
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, publiViewEnabled }),
52
- createApiRoutes({ viewAuthorization: viewAuth, uploadAuthorization: uploadAuth, deleteAuthorization: deleteAuth })
53
- );
54
-
55
- return router;
56
- }
57
-
58
- const router = createBucketRouter();
59
-
60
- export default router;
1
+ /**
2
+ * MBKBucket
3
+ * Copyright (c) 2026 Muhammad Bin Khalid, MBKTech.org and contributors
4
+ * Licensed under the MIT License.
5
+ * Source: https://github.com/MIbnEKhalid/mbkbucket
6
+ */
7
+
8
+ import express from "express";
9
+ import { sessRole } from "mbkauthe";
10
+ import path from "path";
11
+ import { fileURLToPath } from "url";
12
+ import { bucketResolver } from "../middleware/bucket-resolver.js";
13
+ import { renderBucketDashboard } from "../controllers/dashboard.controller.js";
14
+ import infoRoutes from "./info.routes.js";
15
+ import { createViewRoutes } from "./view.routes.js";
16
+ import { createApiRoutes } from "./api.routes.js";
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
+
29
+ export function createBucketRouter({ authorization, publiViewEnabled } = {}) {
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, publiViewEnabled }),
52
+ createApiRoutes({ viewAuthorization: viewAuth, uploadAuthorization: uploadAuth, deleteAuthorization: deleteAuth })
53
+ );
54
+
55
+ return router;
56
+ }
57
+
58
+ const router = createBucketRouter();
59
+
60
+ export default router;