mbkbucket 1.3.0 → 1.5.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
@@ -1,10 +1,13 @@
1
- mbkbucketVar={"APP_NAME":"mbkbucket","loginRedirectURL":"/dashboard","bucket":""}
1
+ mbkautheVar={"APP_NAME":"mbkbucket","loginRedirectURL":"/dashboard","bucket":""}
2
2
  mbkauthShared={"Main_SECRET_TOKEN": 123,"DOMAIN":"mbktech.org","IS_DEPLOYED":"false","EncPass":"false","DEVICE_TRUST_DURATION_DAYS":7,"SESSION_SECRET_KEY":"123","LOGIN_DB":"postgres://","MBKAUTH_TWO_FA_ENABLE":"true","COOKIE_EXPIRE_TIME":2,"GITHUB_LOGIN_ENABLED":"f","GITHUB_CLIENT_ID":"123","GITHUB_CLIENT_SECRET":"123","GOOGLE_LOGIN_ENABLED":"f","GOOGLE_CLIENT_ID":"123","GOOGLE_CLIENT_SECRET":"123"}
3
3
  # See @node_modules/mbkauthe/docs/env.md for more details
4
4
  NODE_ENV=development
5
5
 
6
- R2_Bucket={"BUCKET_NAME":"","ACCESS_KEY_ID":"","SECRET_ACCESS_KEY":"","ENDPOINT":""}
7
- E2_Bucket={"BUCKET_NAME":"","ACCESS_KEY_ID":"","SECRET_ACCESS_KEY":"","ENDPOINT":"","Region":"ap-southeast-1"}
6
+ BucketConnection={"r2":{"BUCKET_NAME":"","ACCESS_KEY_ID":"","SECRET_ACCESS_KEY":"","ENDPOINT":""},"e2":{"BUCKET_NAME":"","ACCESS_KEY_ID":"","SECRET_ACCESS_KEY":"","ENDPOINT":"","Region":"ap-southeast-1"},"custom":{"BUCKET_NAME":"","ACCESS_KEY_ID":"","SECRET_ACCESS_KEY":"","ENDPOINT":"","Region":""}}
8
7
  # Region is optional
9
8
 
9
+ mbkbucketVar={"publiView_enabled":"true","p_view_inline":"true"}
10
+ # 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.
11
+ # p_view_inline means if the file should be displayed inline in the browser (proxy) or redirect to s3 signed url if false.
12
+
10
13
  PORT=3005
@@ -8,10 +8,6 @@ This package is published on npm: [mbkbucket](https://www.npmjs.com/package/mbkb
8
8
  npm install mbkbucket
9
9
  ```
10
10
 
11
- ## Version
12
-
13
- Current Version: 1.0.0
14
-
15
11
  ## Registry
16
12
 
17
13
  Published to: npm Registry (https://registry.npmjs.org/)
package/README.md CHANGED
@@ -1,34 +1,44 @@
1
1
  # mbkbucket
2
2
 
3
+ S3 Bucket manager for Node.js applications with Express integration.
4
+
3
5
  [![Version](https://img.shields.io/npm/v/mbkbucket.svg)](https://www.npmjs.com/package/mbkbucket)
6
+ [![Downloads](https://img.shields.io/npm/dm/mbkbucket.svg)](https://www.npmjs.com/package/mbkbucket)
4
7
  [![License](https://img.shields.io/badge/License-GPL--2.0-blue.svg)](LICENSE)
5
8
  [![Node.js](https://img.shields.io/badge/node-%3E%3D14.0.0-brightgreen.svg)](https://nodejs.org/)
6
- [![Publish to npm and GitHub Packages](https://github.com/MIbnEKhalid/mbkbucket/actions/workflows/publish.yml/badge.svg)](https://github.com/MIbnEKhalid/mbkbucket/actions/workflows/publish.yml)
9
+ [![Publish Status](https://github.com/MIbnEKhalid/mbkbucket/actions/workflows/publish.yml/badge.svg)](https://github.com/MIbnEKhalid/mbkbucket/actions/workflows/publish.yml)
10
+
11
+
12
+ ## Usage 📖
7
13
 
8
- ## Usage ✅
14
+ ### Installation
9
15
 
10
- Install:
16
+ Install the package via npm:
11
17
 
12
18
  ```bash
13
19
  npm install mbkbucket
14
20
  ```
15
21
 
16
- ### Quick examples
22
+ ### Getting Started
17
23
 
18
- - Named imports from package root:
24
+ #### Named imports from package root
19
25
 
20
26
  ```js
21
27
  import { uploadFile, downloadFile, listfiles, getBucketConfig, packageJson, bucket } from 'mbkbucket';
22
28
  ```
23
29
 
24
- - Default aggregate import:
30
+ #### Default aggregate import
31
+
32
+ This imports the configured Express server instance:
25
33
 
26
34
  ```js
27
35
  import mbkbucket from 'mbkbucket';
28
- // mbkbucket.uploadFile(...)
36
+ // Access bucket router via: mbkbucket.bucket
29
37
  ```
30
38
 
31
- - Direct subpath imports (optional):
39
+ #### Direct subpath imports (optional)
40
+
41
+ For more granular control, import directly from submodules:
32
42
 
33
43
  ```js
34
44
  import { uploadFile } from 'mbkbucket/lib/s3';
@@ -36,17 +46,52 @@ import { packageJson } from 'mbkbucket/lib/config/index';
36
46
  import bucketRouter from 'mbkbucket/lib/bucket';
37
47
  ```
38
48
 
39
- ### Notes
49
+ ### Additional Information
40
50
 
41
51
  - All functions, objects, and variables exported from `lib/` are re-exported at the package root for convenience.
42
- - The package includes TypeScript declarations (`index.d.ts`) so IDEs and TypeScript projects get proper typings.
43
- - The default export of the package is the configured Express `server` instance; the `bucket` router is available as `bucket` (named export).
52
+ - TypeScript support with full type declarations (`index.d.ts`) for IDE intellisense and type safety.
53
+ - The default export is the configured Express `server` instance; access the `bucket` router as a named export.
54
+ - Supports Node.js 14.0.0 and higher with ES Modules.
44
55
 
45
56
  ---
46
57
 
58
+ ## API Overview
59
+
60
+ - **uploadFile()** - Upload files to S3 bucket
61
+ - **downloadFile()** - Retrieve files from S3 bucket
62
+ - **listfiles()** - List contents of S3 bucket
63
+ - **getBucketConfig()** - Get current bucket configuration
64
+ - **bucket** - Express router with bucket management endpoints
65
+
66
+ For complete API documentation, refer to the TypeScript declarations in [index.d.ts](index.d.ts).
67
+
68
+ ---
69
+
70
+ ## Requirements
71
+
72
+ - Node.js >= 14.0.0
73
+ - AWS S3 credentials configured
74
+ - AWS SDK v3 compatible environment
47
75
 
48
- ## Contact
76
+ ---
77
+
78
+ ## Contact & Support
79
+
80
+ For questions, issues, or contributions, please reach out:
81
+
82
+ - **Website**: [mbktech.org/Support](https://mbktech.org/Support/?Project=MIbnEKhalidWeb)
83
+ - **Email**: [support@mbktech.org](mailto:support@mbktech.org) or [chmuhammadbinkhalid28@gmail.com](mailto:chmuhammadbinkhalid28@gmail.com)
84
+ - **GitHub**: [MIbnEKhalid](https://github.com/MIbnEKhalid)
85
+
86
+ ---
87
+
88
+ ## About
89
+
90
+ Developed by [Muhammad Bin Khalid](https://github.com/MIbnEKhalid)
91
+ Part of [MBK Tech Studio](https://mbktech.org/)
92
+
93
+ ---
49
94
 
50
- For questions or contributions, please contact Muhammad Bin Khalid at [mbktechstudio.com/Support](https://mbktechstudio.com/Support/?Project=MIbnEKhalidWeb), [support@mbktechstudio.com](mailto:support@mbktechstudio.com) or [chmuhammadbinkhalid28@gmail.com](mailto:chmuhammadbinkhalid28@gmail.com).
95
+ ## License
51
96
 
52
- Developed by [Muhammad Bin Khalid](https://github.com/MIbnEKhalid) at [MBK Tech Studio](https://mbktech.org/).
97
+ Licensed under the GPL-2.0 License. See [LICENSE](LICENSE) file for details.
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Type definitions for mbkbucket 1.2.1
1
+ // Type definitions for mbkbucket 1.5.0
2
2
  // Project: https://github.com/MIbnEKhalid/mbkbucket
3
3
  // Definitions by: Muhammad Bin Khalid <https://github.com/MIbnEKhalid">
4
4
 
@@ -26,6 +26,53 @@ export interface S3ObjectResult {
26
26
  [key: string]: any;
27
27
  }
28
28
 
29
+ // Options passed to uploadFile
30
+ export interface UploadOptions {
31
+ metadata?: Record<string, string>;
32
+ cacheControl?: string;
33
+ storageClass?: string;
34
+ serverSideEncryption?: string;
35
+ bucketName?: string;
36
+ preventOverwrite?: boolean; // added in 1.4.1
37
+ [key: string]: any;
38
+ }
39
+
40
+ // Options for listing files
41
+ export interface ListFilesOptions {
42
+ maxKeys?: number;
43
+ continuationToken?: string | null;
44
+ delimiter?: string | null;
45
+ fetchOwner?: boolean;
46
+ startAfter?: string | null;
47
+ bucketName?: string;
48
+ [key: string]: any;
49
+ }
50
+
51
+ // Result returned from listfiles calls
52
+ export interface ListFilesResult extends Record<string, any> {
53
+ requestedAt: string;
54
+ totalFiles: number;
55
+ hasMore: boolean;
56
+ nextToken: string | null;
57
+ }
58
+
59
+ // Incomplete multipart upload descriptor returned by AWS
60
+ export interface IncompleteMultipartUpload {
61
+ Key?: string;
62
+ UploadId?: string;
63
+ Initiated?: string;
64
+ Initiator?: { DisplayName?: string; [key: string]: any };
65
+ [key: string]: any;
66
+ }
67
+
68
+ // Result returned by cleanupIncompleteMultipartUploads
69
+ export interface CleanupResult {
70
+ abortedCount: number;
71
+ uploads: Array<{ key: string; uploadId: string; initiated?: string }>;
72
+ cleanedAt?: string;
73
+ [key: string]: any;
74
+ }
75
+
29
76
  /**
30
77
  * S3-related functions (available from `mbkbucket/lib/s3` and re-exported at package root)
31
78
  */
@@ -35,20 +82,13 @@ export function getAppName(): string;
35
82
  export function ensureKeyHasAppPrefix(key?: string): string;
36
83
  export function ensurePrefix(prefix?: string): string;
37
84
  export function getBucketClient(bucketName?: string): any;
38
- export function checkR2Health(): Promise<{ status: string; responseTime?: number; bucket?: string; error?: string; checkedAt: string; region?: string }>;
85
+ export function checkHealth(): Promise<{ status: string; responseTime?: number; bucket?: string; error?: string; checkedAt: string; region?: string }>;
39
86
 
40
87
  export function uploadFile(
41
88
  key: string,
42
89
  fileBuffer: Buffer | Uint8Array,
43
90
  contentType: string,
44
- options?: {
45
- metadata?: Record<string, string>;
46
- cacheControl?: string;
47
- storageClass?: string;
48
- serverSideEncryption?: string;
49
- bucketName?: string;
50
- [key: string]: any;
51
- }
91
+ options?: UploadOptions
52
92
  ): Promise<{ fileSize?: number; key: string; contentType?: string; uploadedAt?: string } & Record<string, any>>;
53
93
 
54
94
  export function downloadFile(
@@ -83,16 +123,8 @@ export function deleteFolder(prefix: string, bucketName?: string): Promise<{
83
123
 
84
124
  export function listfiles(
85
125
  prefix?: string,
86
- options?: {
87
- maxKeys?: number;
88
- continuationToken?: string | null;
89
- delimiter?: string | null;
90
- fetchOwner?: boolean;
91
- startAfter?: string | null;
92
- bucketName?: string;
93
- [key: string]: any;
94
- }
95
- ): Promise<Record<string, any>>;
126
+ options?: ListFilesOptions
127
+ ): Promise<ListFilesResult>;
96
128
 
97
129
  export function getFileMetadata(key: string, bucketName?: string): Promise<{
98
130
  key: string;
@@ -120,6 +152,55 @@ export function generateSignedUrl(
120
152
  generatedAt: string;
121
153
  }>;
122
154
 
155
+ /**
156
+ * S3 Multipart Upload Functions
157
+ */
158
+ export function createMultipartUpload(
159
+ key: string,
160
+ contentType?: string,
161
+ metadata?: Record<string, 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
+ ): Promise<{ ETag: string; partNumber: number }>;
170
+
171
+ export function completeMultipartUpload(
172
+ key: string,
173
+ uploadId: string,
174
+ parts: Array<{ partNumber: number; ETag: string }>
175
+ ): Promise<{ key: string }>;
176
+
177
+ export function abortMultipartUpload(
178
+ key: string,
179
+ uploadId: string
180
+ ): Promise<{ key: string; abortedAt: string }>;
181
+
182
+ export function listIncompleteMultipartUploads(
183
+ prefix?: string,
184
+ bucketName?: string
185
+ ): Promise<IncompleteMultipartUpload[]>;
186
+
187
+ export function cleanupIncompleteMultipartUploads(
188
+ olderThanDays?: number,
189
+ prefix?: string,
190
+ bucketName?: string
191
+ ): Promise<CleanupResult>;
192
+
193
+ /**
194
+ * Configuration variables from mbkbucket
195
+ */
196
+ export interface ConfigVars {
197
+ publiView_enabled: boolean;
198
+ p_view_inline: boolean;
199
+ [key: string]: any;
200
+ }
201
+
202
+ export const mbkbucketVar: ConfigVars;
203
+
123
204
  /**
124
205
  * Exported router from `lib/bucket` (re-exported at package root as `bucket`)
125
206
  */
@@ -155,26 +236,61 @@ declare module "mbkbucket/lib/s3" {
155
236
  Key?: string;
156
237
  [key: string]: any;
157
238
  }
239
+
240
+ // re-use shared interfaces defined at top of index.d.ts
241
+ export interface UploadOptions {
242
+ metadata?: Record<string, string>;
243
+ cacheControl?: string;
244
+ storageClass?: string;
245
+ serverSideEncryption?: string;
246
+ bucketName?: string;
247
+ preventOverwrite?: boolean;
248
+ [key: string]: any;
249
+ }
250
+ export interface ListFilesOptions {
251
+ maxKeys?: number;
252
+ continuationToken?: string | null;
253
+ delimiter?: string | null;
254
+ fetchOwner?: boolean;
255
+ startAfter?: string | null;
256
+ bucketName?: string;
257
+ [key: string]: any;
258
+ }
259
+ export interface ListFilesResult extends Record<string, any> {
260
+ requestedAt: string;
261
+ totalFiles: number;
262
+ hasMore: boolean;
263
+ nextToken: string | null;
264
+ }
265
+ export interface IncompleteMultipartUpload {
266
+ Key?: string;
267
+ UploadId?: string;
268
+ Initiated?: string;
269
+ Initiator?: { DisplayName?: string; [key: string]: any };
270
+ [key: string]: any;
271
+ }
272
+ export interface CleanupResult {
273
+ abortedCount: number;
274
+ uploads: Array<{ key: string; uploadId: string; initiated?: string }>;
275
+ cleanedAt?: string;
276
+ [key: string]: any;
277
+ }
278
+
158
279
  export function getBucketConfig(bucketName?: string): BucketConfig;
159
280
  export const bucketClient: any;
160
281
  export function getAppName(): string;
161
282
  export function ensureKeyHasAppPrefix(key?: string): string;
162
283
  export function ensurePrefix(prefix?: string): string;
163
284
  export function getBucketClient(bucketName?: string): any;
164
- export function checkR2Health(): Promise<{ status: string; responseTime?: number; bucket?: string; error?: string; checkedAt: string; region?: string }>;
285
+ export function checkHealth(): Promise<{ status: string; responseTime?: number; bucket?: string; error?: string; checkedAt: string; region?: string }>;
286
+
165
287
  export function uploadFile(
166
288
  key: string,
167
289
  fileBuffer: Buffer | Uint8Array,
168
290
  contentType: string,
169
- options?: {
170
- metadata?: Record<string, string>;
171
- cacheControl?: string;
172
- storageClass?: string;
173
- serverSideEncryption?: string;
174
- bucketName?: string;
175
- [key: string]: any;
176
- }
291
+ options?: UploadOptions
177
292
  ): Promise<{ fileSize?: number; key: string; contentType?: string; uploadedAt?: string } & Record<string, any>>;
293
+
178
294
  export function downloadFile(
179
295
  key: string,
180
296
  options?: {
@@ -187,6 +303,7 @@ declare module "mbkbucket/lib/s3" {
187
303
  [key: string]: any;
188
304
  }
189
305
  ): Promise<S3ObjectResult>;
306
+
190
307
  export function deleteFile(key: string, bucketName?: string): Promise<{ key: string; deletedAt?: string } & Record<string, any>>;
191
308
  export function deleteFiles(keys: string[], bucketName?: string): Promise<{
192
309
  results: any[];
@@ -202,18 +319,12 @@ declare module "mbkbucket/lib/s3" {
202
319
  deletedAt: string;
203
320
  prefix?: string;
204
321
  }>;
322
+
205
323
  export function listfiles(
206
324
  prefix?: string,
207
- options?: {
208
- maxKeys?: number;
209
- continuationToken?: string | null;
210
- delimiter?: string | null;
211
- fetchOwner?: boolean;
212
- startAfter?: string | null;
213
- bucketName?: string;
214
- [key: string]: any;
215
- }
216
- ): Promise<Record<string, any>>;
325
+ options?: ListFilesOptions
326
+ ): Promise<ListFilesResult>;
327
+
217
328
  export function getFileMetadata(key: string, bucketName?: string): Promise<{
218
329
  key: string;
219
330
  exists: boolean;
@@ -223,6 +334,7 @@ declare module "mbkbucket/lib/s3" {
223
334
  LastModified?: Date;
224
335
  [key: string]: any;
225
336
  }>;
337
+
226
338
  export function fileExists(key: string, bucketName?: string): Promise<boolean>;
227
339
  export function getFileSize(key: string, bucketName?: string): Promise<number | null>;
228
340
  export function generateSignedUrl(
@@ -237,11 +349,52 @@ declare module "mbkbucket/lib/s3" {
237
349
  expiresAt: string;
238
350
  generatedAt: string;
239
351
  }>;
352
+
353
+ export function createMultipartUpload(
354
+ key: string,
355
+ contentType?: string,
356
+ metadata?: Record<string, string>
357
+ ): Promise<{ uploadId: string; key: string }>;
358
+
359
+ export function uploadPart(
360
+ key: string,
361
+ uploadId: string,
362
+ partNumber: number,
363
+ buffer: Buffer | Uint8Array
364
+ ): Promise<{ ETag: string; partNumber: number }>;
365
+
366
+ export function completeMultipartUpload(
367
+ key: string,
368
+ uploadId: string,
369
+ parts: Array<{ partNumber: number; ETag: string }>
370
+ ): Promise<{ key: string }>;
371
+
372
+ export function abortMultipartUpload(
373
+ key: string,
374
+ uploadId: string
375
+ ): Promise<{ key: string; abortedAt: string }>;
376
+
377
+ export function listIncompleteMultipartUploads(
378
+ prefix?: string,
379
+ bucketName?: string
380
+ ): Promise<IncompleteMultipartUpload[]>;
381
+
382
+ export function cleanupIncompleteMultipartUploads(
383
+ olderThanDays?: number,
384
+ prefix?: string,
385
+ bucketName?: string
386
+ ): Promise<CleanupResult>;
240
387
  }
241
388
 
242
389
  declare module "mbkbucket/lib/config/index" {
390
+ export interface ConfigVars {
391
+ publiView_enabled: boolean;
392
+ p_view_inline: boolean;
393
+ [key: string]: any;
394
+ }
243
395
  export const packageJson: Record<string, any>;
244
396
  export const appVersion: string;
397
+ export const mbkbucketVar: ConfigVars;
245
398
  export function getLatestVersion(): Promise<string | null>;
246
399
  export function checkVersion(): Promise<void>;
247
400
  }
package/index.js CHANGED
@@ -2,11 +2,11 @@ import express from "express";
2
2
  import path from "path";
3
3
  import dotenv from "dotenv";
4
4
  import { fileURLToPath } from "url";
5
- import mbkauthe from "mbkauthe";
5
+ import mbkautheRoutes from "mbkauthe";
6
6
  import { engine } from "express-handlebars";
7
7
  import compression from "compression";
8
8
  import rateLimit from 'express-rate-limit';
9
- import bucket from "./lib/bucket.js";
9
+ import bucketRoutes from "./lib/routes/index.js";
10
10
  import { checkVersion } from "./lib/config/index.js";
11
11
  import { appVersion } from "./lib/config/index.js";
12
12
 
@@ -71,83 +71,8 @@ server.engine("handlebars", engine({
71
71
  ],
72
72
  cache: process.env.NODE_ENV === "production",
73
73
  helpers: {
74
- formatDate: (date) => {
75
- return new Date(date).toLocaleString('en-US', {
76
- year: 'numeric',
77
- month: 'long',
78
- day: 'numeric',
79
- hour: '2-digit',
80
- minute: '2-digit',
81
- second: '2-digit',
82
- hour12: true
83
- });
84
- },
85
- in: function (value, list) {
86
- if (!list || !Array.isArray(list)) return false;
87
- return list.includes(parseInt(value) || value);
88
- },
89
- trim: function (str) {
90
- return str ? str.trim() : '';
91
- },
92
74
  eq: function (a, b) {
93
75
  return a === b;
94
- },
95
- encodeURIComponent: function (str) {
96
- return encodeURIComponent(str);
97
- },
98
- formatTimestamp: function (timestamp) {
99
- return new Date(timestamp).toLocaleString();
100
- },
101
- jsonStringify: function (context) {
102
- return JSON.stringify(context);
103
- },
104
- truncate: (str, len) => {
105
- if (!str) return '';
106
- if (str.length > len) {
107
- return str.substring(0, len) + '...';
108
- }
109
- return str;
110
- },
111
- section: function (name, options) {
112
- if (!this._sections) this._sections = {};
113
- this._sections[name] = options.fn(this);
114
- return null;
115
- },
116
- getCanonicalUrl: function (req, path) {
117
- const protocol = req.protocol || 'https';
118
- const host = req.get('host') || 'blog.mbktechstudio.com';
119
- return `${protocol}://${host}${path}`;
120
- },
121
- index: function (array, idx) {
122
- return array ? array[idx] : null;
123
- },
124
- add: function (a, b) {
125
- return Number(a) + Number(b);
126
- },
127
- subtract: function (a, b) {
128
- return Number(a) - Number(b);
129
- },
130
- gt: function (a, b) {
131
- return Number(a) > Number(b);
132
- },
133
- gte: function (a, b) {
134
- return Number(a) >= Number(b);
135
- },
136
- lte: function (a, b) {
137
- return Number(a) <= Number(b);
138
- },
139
- and: function () {
140
- return Array.prototype.slice.call(arguments, 0, -1).every(Boolean);
141
- },
142
- or: function () {
143
- return Array.prototype.slice.call(arguments, 0, -1).some(Boolean);
144
- },
145
- range: function (start, end) {
146
- const result = [];
147
- for (let i = start; i < end; i++) {
148
- result.push(i);
149
- }
150
- return result;
151
76
  }
152
77
  }
153
78
  }));
@@ -159,9 +84,9 @@ server.set("views", [
159
84
  path.join(__dirname, "../mbkauthe/views")
160
85
  ]);
161
86
 
162
- server.use(mbkauthe);
87
+ server.use(mbkautheRoutes);
163
88
  server.use(generalLimiter);
164
- server.use(bucket);
89
+ server.use(bucketRoutes);
165
90
 
166
91
  if (process.env.mbkbucket_test === "dev") {
167
92