mbkbucket 4.0.1 → 4.1.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/.env.example CHANGED
@@ -4,8 +4,9 @@ mbkauthShared={"Main_SECRET_TOKEN": 123,"DOMAIN":"mbktech.org","IS_DEPLOYED":"fa
4
4
  # See @node_modules/mbkauthe/docs/env.md for more details
5
5
  NODE_ENV=development
6
6
 
7
- # Storage Connections (S3, Cloudflare R2, MinIO, Google Drive)
8
- BucketConnection={"Google_Drive":{"type":"gdrive","client_id":"your-client-id.apps.googleusercontent.com","client_secret":"your-client-secret","refresh_token":"your-refresh-token","folder_id":"root"},"R2_Bucket":{"BUCKET_NAME":"my-r2-bucket","ACCESS_KEY_ID":"your-r2-access-key","SECRET_ACCESS_KEY":"your-r2-secret","ENDPOINT":"https://accountid.r2.cloudflarestorage.com"},"S3_Bucket":{"BUCKET_NAME":"my-s3-bucket","ACCESS_KEY_ID":"your-s3-access-key","SECRET_ACCESS_KEY":"your-s3-secret","ENDPOINT":"https://s3.ap-southeast-1.amazonaws.com"}}
7
+ # Storage Connections (Local Disk, S3, Cloudflare R2, MinIO, Google Drive)
8
+ BucketConnection={"Local_Disk":{"type":"local","basePath":"./mbkbucket_storage"},"Google_Drive":{"type":"gdrive","client_id":"your-client-id.apps.googleusercontent.com","client_secret":"your-client-secret","refresh_token":"your-refresh-token","folder_id":"root"},"R2_Bucket":{"BUCKET_NAME":"my-r2-bucket","ACCESS_KEY_ID":"your-r2-access-key","SECRET_ACCESS_KEY":"your-r2-secret","ENDPOINT":"https://accountid.r2.cloudflarestorage.com"},"S3_Bucket":{"BUCKET_NAME":"my-s3-bucket","ACCESS_KEY_ID":"your-s3-access-key","SECRET_ACCESS_KEY":"your-s3-secret","ENDPOINT":"https://s3.ap-southeast-1.amazonaws.com"}}
9
+
9
10
 
10
11
  mbkbucketVar={"publiView_enabled":"true","p_view_inline":"true"}
11
12
  # publiView_enabled mean if this app storage is public or private. If true, then anyone can access the files if they have the link. If false, then only authenticated users can access the files.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mbkbucket
2
2
 
3
- > Flexible S3, Cloudflare R2, and Google Drive cloud storage management — library, Express router, dashboard, and standalone server CLI for mbktech.org applications.
3
+ > Flexible S3, Cloudflare R2, Google Drive, and Local Disk storage management — library, Express router, dashboard, and standalone server CLI for mbktech.org applications.
4
4
 
5
5
  [![Version](https://img.shields.io/npm/v/mbkbucket.svg)](https://www.npmjs.com/package/mbkbucket)
6
6
  [![Downloads](https://img.shields.io/npm/dm/mbkbucket.svg)](https://www.npmjs.com/package/mbkbucket)
@@ -12,7 +12,7 @@
12
12
 
13
13
  ## Table of Contents
14
14
 
15
- - [What's New in v4.0.0](#whats-new-in-v400-)
15
+ - [What's New in v4.1.0](#whats-new-in-v410-)
16
16
  - [Installation](#installation-)
17
17
  - [Quick Start](#quick-start-)
18
18
  - [Supported Storage Providers](#supported-storage-providers-)
@@ -20,9 +20,10 @@
20
20
  - [Library API](#library-api-)
21
21
  - [File Operations](#file-operations)
22
22
  - [Folder, Copy & Move Operations](#folder-copy--move-operations)
23
- - [Multipart Upload](#multipart-upload)
23
+ - [Multipart Upload & Cleanup Scheduler](#multipart-upload--cleanup-scheduler)
24
24
  - [Storage & Connection Management](#storage--connection-management)
25
25
  - [Storage Core & Custom Drivers](#storage-core--custom-drivers)
26
+ - [Metrics & Observability](#metrics--observability)
26
27
  - [Google Drive Authentication Helpers](#google-drive-authentication-helpers)
27
28
  - [Key Prefixing & App Isolation](#key-prefixing--app-isolation)
28
29
  - [Config & Diagnostics](#config--diagnostics)
@@ -42,16 +43,14 @@
42
43
 
43
44
  ---
44
45
 
45
- ## What's New in v4.0.0 🌟
46
+ ## What's New in v4.1.0 🌟
46
47
 
47
- - **Provider-Independent Storage Architecture**: Unified `StorageProvider` base class and dynamic `StorageManager` registry. Seamlessly switch between or combine multiple storage backends.
48
- - **Native Google Drive Support**: First-class Google Drive provider supporting both OAuth 2.0 (user authorization code / refresh token flow) and Google Cloud Service Account credentials with folder-level targeting (`folder_id`).
49
- - **File Move & Copy Operations**: Built-in `moveFile` and `copyFile` operations across both library functions, REST APIs, and UI modals.
50
- - **Native Folder Creation**: Create directory markers and structure via `createFolder` with automatic folder marker resolution.
51
- - **Redesigned Admin Dashboard**: Clean modern UI with connection health badges, provider tags, storage connection switcher dropdown, dedicated Move/Rename modal, and enhanced media previews (video range streaming, PDF, audio, and code view).
52
- - **Frontend Drop-in Client Library (`mbkbucket-helper.js`)**: Bundled client helper with a modal gallery browser, input file picker, drag-and-drop chunked uploader, URL builders, and toast notifications. Demo page included at `/mbkbucket/helper-demo`.
53
- - **Custom Storage Drivers**: Register custom storage engines via `storageManager.registerDriver('custom', factory)`.
54
- - **Full Backward Compatibility**: All legacy S3 helper methods remain available and map cleanly to the underlying storage provider.
48
+ - **Cross-Platform Local Disk Provider (`LocalStorageProvider`)**: First-class local filesystem storage provider with full Windows, Linux, and macOS compatibility, path sanitization against directory traversal, quota enforcement (`maxBytes`), recursive directory scanning, and byte-range streaming.
49
+ - **Metrics & Observability Registry (`MetricsRegistry`)**: Built-in Prometheus-compatible metrics registry (`metricsRegistry`) and endpoints (`/mbkbucket/api/metrics` and `/mbkbucket/metrics`) tracking operation counts, duration summaries, transferred byte throughput, error counts, and active multipart sessions.
50
+ - **Event-Driven Lifecycle & Storage Orchestration**: `StorageManager` now extends `EventEmitter`, broadcasting real-time lifecycle events (`file:uploaded`, `file:deleted`, `files:deleted`, `folder:created`, `folder:deleted`, `connection:registered`, `driver:registered`) with full lifecycle methods (`initialize()`, `dispose()`, `ping()`).
51
+ - **Automated Incomplete Multipart Cleanup Scheduler (`CleanupScheduler`)**: Background cron-like scheduler (`cleanupScheduler`) to automatically identify and abort abandoned multipart upload chunks older than a configurable threshold.
52
+ - **RFC 7233 Open-Ended Byte-Range Streaming**: High-performance range streaming for PDF documents (Chrome PDF viewer, Firefox PDF.js), HTML5 video, and audio players (`206 Partial Content`) with proper inline content disposition.
53
+ - **Native Google Drive & S3/R2 Enhancements**: Unified error handling, exponential backoff retries on rate limits (429/503), and automatic driver inference for local paths.
55
54
 
56
55
  ---
57
56
 
@@ -68,14 +67,14 @@ npm install mbkbucket
68
67
  ### As a Library
69
68
 
70
69
  ```js
71
- import { uploadFile, downloadFile, listfiles, copyFile, moveFile, createFolder, deleteFile, generateSignedUrl, storageManager } from 'mbkbucket';
70
+ import { uploadFile, downloadFile, listfiles, copyFile, moveFile, createFolder, deleteFile, storageManager, metricsRegistry } from 'mbkbucket';
72
71
 
73
72
  // Upload a file to default storage (or specify connectionName / bucketName)
74
73
  const upload = await uploadFile(
75
74
  'documents/invoice.pdf',
76
75
  fileBuffer,
77
76
  'application/pdf',
78
- { connectionName: 'R2_Bucket' }
77
+ { connectionName: 'Local_Disk' } // or 'R2_Bucket', 'Google_Drive'
79
78
  );
80
79
 
81
80
  // List files and directories
@@ -91,15 +90,19 @@ await moveFile('documents/invoice.pdf', 'archive/invoice-2026.pdf');
91
90
  // Create a folder marker
92
91
  await createFolder('projects/2026');
93
92
 
94
- // Download a file stream
95
- const { Body, ContentType, ContentLength } = await downloadFile('archive/invoice-2026.pdf');
93
+ // Download a file stream (with optional byte ranges for streaming)
94
+ const { Body, ContentType, ContentLength } = await downloadFile('archive/invoice-2026.pdf', {
95
+ range: 'bytes=0-1048575'
96
+ });
96
97
 
97
- // Generate pre-signed URL (for S3-compatible providers)
98
- const { url } = await generateSignedUrl('archive/invoice-2026.pdf', 'getObject', 3600);
98
+ // Listen to storage lifecycle events
99
+ storageManager.on('file:uploaded', ({ key, provider, size }) => {
100
+ console.log(`[Event] File uploaded: ${key} (${size} bytes) to ${provider}`);
101
+ });
99
102
 
100
103
  // Check health across active connections
101
- const health = await storageManager.checkHealth('Google_Drive');
102
- console.log('Google Drive status:', health.status);
104
+ const health = await storageManager.checkHealth('Local_Disk');
105
+ console.log('Storage status:', health.status);
103
106
  ```
104
107
 
105
108
  ### As Express Middleware
@@ -141,14 +144,15 @@ mbkbucket.listen(3004, () => {
141
144
 
142
145
  ## Supported Storage Providers 🗄️
143
146
 
144
- mbkbucket v4.0.0 supports multiple object and file storage providers simultaneously:
147
+ mbkbucket v4.1.0 supports multiple object and file storage providers simultaneously:
145
148
 
146
149
  | Provider | Type Identifier | Features / Capabilities |
147
150
  |---|---|---|
148
- | **AWS S3** | `s3` | Multipart upload, signed URLs, range streaming, server-side copy/move |
149
- | **Cloudflare R2** | `s3` / `r2` | S3-compatible, zero egress fees, signed URLs, multipart upload |
151
+ | **Local Filesystem** | `local` / `local-disk` / `disk` | Cross-platform (Win/Linux/macOS), local directory storage, quota limits, range streaming, zero cloud latency |
152
+ | **AWS S3** | `s3` | Multipart upload, range streaming, server-side copy/move |
153
+ | **Cloudflare R2** | `s3` / `r2` | S3-compatible, zero egress fees, multipart upload, range streaming |
150
154
  | **Google Drive** | `gdrive` / `google-drive` | OAuth 2.0 & Service Account auth, native folder hierarchy, direct download URLs, range requests |
151
- | **MinIO** | `s3` / `minio` | Self-hosted S3-compatible storage, multipart, signed URLs |
155
+ | **MinIO** | `s3` / `minio` | Self-hosted S3-compatible storage, multipart upload |
152
156
  | **IDrive e2** | `s3` | S3-compatible high-performance object storage |
153
157
  | **Backblaze B2** | `s3` | S3-compatible API endpoints |
154
158
  | **DigitalOcean Spaces** | `s3` | S3-compatible object storage |
@@ -212,7 +216,6 @@ Full TypeScript declarations are available in [index.d.ts](index.d.ts).
212
216
  | `getFileMetadata(key, connectionName?)` | Retrieve file metadata without downloading content |
213
217
  | `fileExists(key, connectionName?)` | Check if a file exists |
214
218
  | `getFileSize(key, connectionName?)` | Get file size in bytes (returns `number` or `null`) |
215
- | `generateSignedUrl(key, operation?, expiresIn?, connectionName?)` | Generate a pre-signed URL (`getObject` or `putObject`) |
216
219
 
217
220
  ### Folder, Copy & Move Operations
218
221
 
@@ -223,11 +226,11 @@ Full TypeScript declarations are available in [index.d.ts](index.d.ts).
223
226
  | `moveFile(sourceKey, destKey, options?, connectionName?)` | Move or rename a file within storage |
224
227
  | `deleteFolder(prefix, connectionName?)` | Recursively delete all files under a folder prefix |
225
228
 
226
- ### Multipart Upload
229
+ ### Multipart Upload & Cleanup Scheduler
227
230
 
228
231
  *(Supported on S3-compatible providers)*
229
232
 
230
- | Function | Description |
233
+ | Function / Export | Description |
231
234
  |---|---|
232
235
  | `createMultipartUpload(key, contentType?, metadata?, connectionName?)` | Initialize a multipart upload session |
233
236
  | `uploadPart(key, uploadId, partNumber, buffer, connectionName?)` | Upload an individual chunk part |
@@ -235,6 +238,17 @@ Full TypeScript declarations are available in [index.d.ts](index.d.ts).
235
238
  | `abortMultipartUpload(key, uploadId, connectionName?)` | Abort and cancel a multipart upload |
236
239
  | `listIncompleteMultipartUploads(prefix?, connectionName?)` | List pending / incomplete multipart uploads |
237
240
  | `cleanupIncompleteMultipartUploads(olderThanDays?, prefix?, connectionName?)` | Clean up abandoned multipart chunks |
241
+ | `CleanupScheduler` / `cleanupScheduler` | Automated background scheduler to purge incomplete uploads on a recurring interval |
242
+
243
+ ```js
244
+ import { cleanupScheduler } from 'mbkbucket';
245
+
246
+ // Start automated daily background cleanup for uploads older than 7 days
247
+ cleanupScheduler.start({
248
+ intervalHours: 24,
249
+ olderThanDays: 7
250
+ });
251
+ ```
238
252
 
239
253
  ### Storage & Connection Management
240
254
 
@@ -250,31 +264,55 @@ Full TypeScript declarations are available in [index.d.ts](index.d.ts).
250
264
 
251
265
  ### Storage Core & Custom Drivers
252
266
 
253
- mbkbucket exposes its core abstraction classes so you can extend or inspect providers programmatically:
267
+ mbkbucket exposes its core abstraction classes so you can extend, inspect, or listen to storage events programmatically:
254
268
 
255
269
  ```js
256
- import { StorageProvider, StorageManager, storageManager } from 'mbkbucket';
270
+ import { StorageProvider, LocalStorageProvider, StorageManager, storageManager } from 'mbkbucket';
271
+
272
+ // Listen to lifecycle events
273
+ storageManager.on('file:uploaded', (e) => console.log('Uploaded:', e.key, e.provider));
274
+ storageManager.on('file:deleted', (e) => console.log('Deleted:', e.key));
275
+ storageManager.on('folder:created', (e) => console.log('Folder created:', e.prefix));
257
276
 
258
277
  // Register a custom storage driver
259
- storageManager.registerDriver('local-disk', (name, config) => {
260
- return new MyCustomLocalStorageProvider(name, config);
278
+ storageManager.registerDriver('custom-ftp', (name, config) => {
279
+ return new MyCustomFtpProvider(name, config);
261
280
  });
262
281
 
263
282
  // Register a runtime connection using the driver
264
- storageManager.registerConnection('local_backup', {
265
- type: 'local-disk',
266
- basePath: '/var/storage'
283
+ storageManager.registerConnection('backup_ftp', {
284
+ type: 'custom-ftp',
285
+ host: 'ftp.example.com'
267
286
  });
268
287
  ```
269
288
 
270
289
  Exported classes:
271
- - `StorageProvider`: Abstract base class with required contracts (`uploadFile`, `downloadFile`, `listFiles`, `deleteFile`, `copyFile`, `moveFile`, `createFolder`, etc.) and `capabilities` flags.
272
- - `S3StorageProvider`: S3, Cloudflare R2, MinIO implementation.
273
- - `GoogleDriveStorageProvider`: Google Drive implementation.
274
- - `StorageManager` / `storageManager`: Connection registry, driver repository, and health orchestrator.
275
- - `StorageFile`, `StorageFolder`, `StorageListResult`: Standardized metadata models.
290
+ - `StorageProvider`: Abstract base class with required contracts (`uploadFile`, `downloadFile`, `listFiles`, `deleteFile`, `copyFile`, `moveFile`, `createFolder`, `checkHealth`, etc.) and capability assertions.
291
+ - `LocalStorageProvider`: Cross-platform local disk provider (Windows, Linux, macOS) with quota calculation and path sanitization.
292
+ - `S3StorageProvider`: AWS S3, Cloudflare R2, MinIO, IDrive e2 implementation.
293
+ - `GoogleDriveStorageProvider`: Google Drive OAuth 2.0 and Service Account implementation.
294
+ - `StorageManager` / `storageManager`: Connection registry, driver repository, `EventEmitter` lifecycle orchestrator, and health monitor.
295
+ - `StorageItem`, `StorageFile`, `StorageFolder`, `StorageListResult`: Standardized metadata models.
276
296
  - Custom Errors: `StorageError`, `StorageNotFoundError`, `StorageAccessDeniedError`, `StorageConflictError`, `StorageValidationError`, `StorageConfigError`, `StorageQuotaExceededError`, `StorageUnsupportedOperationError`.
277
297
 
298
+ ### Metrics & Observability
299
+
300
+ mbkbucket includes a Prometheus-compatible metrics registry tracking storage operations, throughput, durations, errors, and active sessions:
301
+
302
+ ```js
303
+ import { metricsRegistry } from 'mbkbucket';
304
+
305
+ // Retrieve snapshot statistics
306
+ const stats = metricsRegistry.getStats();
307
+ console.log('Total ops:', stats.operations);
308
+ console.log('Bytes transferred:', stats.bytesTransferred);
309
+
310
+ // Export Prometheus exposition format
311
+ const prometheusText = metricsRegistry.toPrometheusText();
312
+ ```
313
+
314
+ Endpoints `/mbkbucket/api/metrics` (JSON) and `/mbkbucket/metrics` (Prometheus text) are automatically exposed when mounting the router.
315
+
278
316
  ### Google Drive Authentication Helpers
279
317
 
280
318
  mbkbucket exports helper functions for handling Google Drive OAuth 2.0 flows:
@@ -335,6 +373,9 @@ All routes are mounted relative to the router path (typically `/mbkbucket`):
335
373
  | `/mbkbucket/api/files` | `GET` | `view` auth | List files and folders with pagination, search, and continuation tokens |
336
374
  | `/mbkbucket/api/file-info/*key`| `GET` | `view` auth | Get metadata (Content-Type, size, ETag, last modified) for a key |
337
375
  | `/mbkbucket/api/health` | `GET` | `view` auth | Check connectivity for active storage connection |
376
+ | `/mbkbucket/api/metrics` | `GET` | `view` auth | Prometheus metrics serialized as JSON |
377
+ | `/mbkbucket/metrics` | `GET` | `view` auth | Prometheus exposition format text output |
378
+ | `/mbkbucket/api/signed-url` | `GET` | `upload` auth | Generate pre-signed URL for direct client uploads/downloads |
338
379
  | `/mbkbucket/api/incomplete-uploads` | `GET` | `view` auth | List incomplete multipart uploads |
339
380
  | `/mbkbucket/api/cleanup-uploads` | `POST` | `delete` auth | Clean up incomplete multipart uploads older than specified days |
340
381
  | `/mbkbucket/upload` | `POST` | `upload` auth | Upload a single file via `multipart/form-data` with conflict detection |
@@ -457,12 +498,20 @@ MBKBucket.url.player('media/intro.mp4'); // -> /mbkbucket/player/media/int
457
498
 
458
499
  ### `BucketConnection` (required)
459
500
 
460
- A JSON string defining one or more storage connections. You can configure **S3/R2** connections and **Google Drive** connections together:
501
+ A JSON string defining one or more storage connections. You can configure **Local Disk**, **S3/R2**, and **Google Drive** connections together:
461
502
 
462
503
  ```env
463
- BucketConnection={"R2_Bucket":{"BUCKET_NAME":"my-bucket","ACCESS_KEY_ID":"your-key","SECRET_ACCESS_KEY":"your-secret","ENDPOINT":"https://<account-id>.r2.cloudflarestorage.com"},"Google_Drive":{"type":"gdrive","client_id":"your-client-id.apps.googleusercontent.com","client_secret":"your-client-secret","refresh_token":"your-refresh-token","folder_id":"root"}}
504
+ BucketConnection={"Local_Disk":{"type":"local","basePath":"./mbkbucket_storage","maxBytes":10737418240},"R2_Bucket":{"BUCKET_NAME":"my-bucket","ACCESS_KEY_ID":"your-key","SECRET_ACCESS_KEY":"your-secret","ENDPOINT":"https://<account-id>.r2.cloudflarestorage.com"},"Google_Drive":{"type":"gdrive","client_id":"your-client-id.apps.googleusercontent.com","client_secret":"your-client-secret","refresh_token":"your-refresh-token","folder_id":"root"}}
464
505
  ```
465
506
 
507
+ #### Local Disk Connection Fields
508
+
509
+ | Field | Required | Description |
510
+ |---|---|---|
511
+ | `type` | Yes | Provider tag: `"local"`, `"local-disk"`, or `"disk"` |
512
+ | `basePath` | No | Base directory path on local disk (supports relative `./storage` or absolute `D:\storage` / `/var/storage`). Defaults to `./mbkbucket_storage`. |
513
+ | `maxBytes` | No | Storage quota limit in bytes (e.g. `10737418240` for 10 GB) |
514
+
466
515
  #### S3 / Cloudflare R2 Connection Fields
467
516
 
468
517
  | Field | Required | Description |
@@ -527,10 +576,13 @@ npm test
527
576
  ### Test Suites Covered
528
577
 
529
578
  - **Storage Provider & Core Abstractions**: `StorageProvider` interface contracts, capability inspection, `PathStrategy` traversal security, `StorageError` hierarchy, Google Drive consent URL generation.
530
- - **S3 & Google Drive Drivers**: Health checks, mock provider operations, connection switching, custom driver registration.
579
+ - **Local Storage Provider & Features**: Cross-platform path resolution, directory isolation, quota tracking (`maxBytes`), recursive directory scanning, and byte-range streaming.
580
+ - **Architecture Hardening & Reliability**: Exponential backoff on rate-limits (429/503), `StorageManager` `EventEmitter` lifecycle events, `MetricsRegistry` tracking, and `CleanupScheduler`.
531
581
  - **API Routes Logic**: File listing, single and chunked multipart uploads, conflict detection (409), folder creation, single/batch deletion, move and copy operations, health endpoint, metadata inspection.
532
- - **View Controller & Streaming**: Inline viewer, video byte-range streaming (`206 Partial Content`), unsupported MIME rejection (`415`), public file viewing.
533
- - **Configuration Validation**: S3 and Google Drive connection validation, malformed JSON recovery, boolean normalization, and error messaging.
582
+ - **View Controller & Streaming**: Inline viewer, open-ended RFC 7233 byte-range streaming for PDF documents and media (`206 Partial Content`), unsupported MIME rejection (`415`), public file viewing.
583
+ - **Helpers & Error Hierarchy**: Utility helpers, range header parsing, stream buffers, cache control builders, and domain-specific error classes.
584
+ - **Configuration Validation**: S3, Local Disk, and Google Drive connection validation, malformed JSON recovery, boolean normalization, and error messaging.
585
+ - **S3 Prefix & Name Resolution**: Application namespace prefixing, delimiter handling, and bucket resolution.
534
586
  - **Public API Exports**: Verification of all exported functions, classes, and proxy objects from package root.
535
587
 
536
588
  ---
package/index.js CHANGED
@@ -21,13 +21,16 @@ if (process.env.NODE_ENV === "dev") {
21
21
  await checkVersion();
22
22
  await runHealthCheck();
23
23
  server.listen(port, () => {
24
+ console.log(`[mbkbucket] 🚀 Server running on http://localhost:${port}`);
24
25
  debugServer("Server running on http://localhost:%s", port);
25
26
  });
26
27
  }
27
28
 
28
29
  export * from "./lib/src/core/storage/index.js";
30
+ export * from "./lib/src/core/metrics.js";
31
+ export * from "./lib/src/utils/cleanup-scheduler.js";
29
32
  export * from "./lib/src/services/storage.service.js";
30
33
  export * from "./lib/src/services/s3.service.js";
31
34
  export * from "./lib/src/config/index.js";
32
35
  export { default as bucket, createBucketRouter } from "./lib/src/routes/index.js";
33
- export default server;
36
+ export default server;