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.
package/index.js CHANGED
@@ -1,33 +1,33 @@
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 dotenv from "dotenv";
9
- import { createApp } from "./lib/src/app.js";
10
- import { checkVersion } from "./lib/src/config/index.js";
11
- import { runHealthCheck } from "./lib/src/services/storage.service.js";
12
- import { createLogger } from "#logger";
13
-
14
- dotenv.config();
15
-
16
- const debugServer = createLogger('server');
17
- const port = process.env.PORT || 3004;
18
- const server = createApp();
19
-
20
- if (process.env.NODE_ENV === "dev") {
21
- await checkVersion();
22
- await runHealthCheck();
23
- server.listen(port, () => {
24
- debugServer("Server running on http://localhost:%s", port);
25
- });
26
- }
27
-
28
- export * from "./lib/src/core/storage/index.js";
29
- export * from "./lib/src/services/storage.service.js";
30
- export * from "./lib/src/services/s3.service.js";
31
- export * from "./lib/src/config/index.js";
32
- export { default as bucket, createBucketRouter } from "./lib/src/routes/index.js";
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 dotenv from "dotenv";
9
+ import { createApp } from "./lib/src/app.js";
10
+ import { checkVersion } from "./lib/src/config/index.js";
11
+ import { runHealthCheck } from "./lib/src/services/storage.service.js";
12
+ import { createLogger } from "#logger";
13
+
14
+ dotenv.config();
15
+
16
+ const debugServer = createLogger('server');
17
+ const port = process.env.PORT || 3004;
18
+ const server = createApp();
19
+
20
+ if (process.env.NODE_ENV === "dev") {
21
+ await checkVersion();
22
+ await runHealthCheck();
23
+ server.listen(port, () => {
24
+ debugServer("Server running on http://localhost:%s", port);
25
+ });
26
+ }
27
+
28
+ export * from "./lib/src/core/storage/index.js";
29
+ export * from "./lib/src/services/storage.service.js";
30
+ export * from "./lib/src/services/s3.service.js";
31
+ export * from "./lib/src/config/index.js";
32
+ export { default as bucket, createBucketRouter } from "./lib/src/routes/index.js";
33
33
  export default server;
package/lib/cli.js CHANGED
@@ -1,239 +1,239 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * MBKBucket
5
- * Copyright (c) 2026 Muhammad Bin Khalid, MBKTech.org and contributors
6
- * Licensed under the MIT License.
7
- * Source: https://github.com/MIbnEKhalid/mbkbucket
8
- */
9
-
10
- /**
11
- * mbkbucket CLI — Standalone server runner for MBKBucket web application.
12
- */
13
-
14
- import dotenv from 'dotenv';
15
- import path from 'node:path';
16
- import os from 'node:os';
17
- import { createApp } from './src/app.js';
18
- import { packageJson, checkVersion } from './src/config/index.js';
19
- import { checkHealth, getAvailableBucketNames } from './src/services/s3.service.js';
20
-
21
- // ---------------------------------------------------------------------------
22
- // ANSI Color helpers
23
- // ---------------------------------------------------------------------------
24
- const c = {
25
- cyan: (s) => `\x1b[36m${s}\x1b[0m`,
26
- green: (s) => `\x1b[32m${s}\x1b[0m`,
27
- yellow: (s) => `\x1b[33m${s}\x1b[0m`,
28
- red: (s) => `\x1b[31m${s}\x1b[0m`,
29
- bold: (s) => `\x1b[1m${s}\x1b[0m`,
30
- dim: (s) => `\x1b[2m${s}\x1b[0m`,
31
- };
32
-
33
- // ---------------------------------------------------------------------------
34
- // Parse CLI arguments
35
- // ---------------------------------------------------------------------------
36
- const args = process.argv.slice(2);
37
-
38
- function findFlag(name, shortChar) {
39
- const long = `--${name}`;
40
- const short = shortChar ? `-${shortChar}` : `-${name[0]}`;
41
- for (let i = 0; i < args.length; i++) {
42
- if (args[i] === long || args[i] === short) {
43
- if (args[i + 1] !== undefined && !args[i + 1].startsWith('-')) {
44
- return args[i + 1];
45
- }
46
- return true;
47
- }
48
- }
49
- return undefined;
50
- }
51
-
52
- const hasFlag = (name, shortChar) => {
53
- const long = `--${name}`;
54
- const short = shortChar ? `-${shortChar}` : `-${name[0]}`;
55
- return args.includes(long) || args.includes(short);
56
- };
57
-
58
- // ---------------------------------------------------------------------------
59
- // Help & Version
60
- // ---------------------------------------------------------------------------
61
- function showHelp() {
62
- console.log(`
63
- ${c.cyan(c.bold('⚡ mbkbucket'))} ${c.dim(`v${packageJson.version}`)}
64
- Standalone S3/R2 Bucket Management Server
65
-
66
- ${c.bold('USAGE:')}
67
- mbkbucket [options]
68
- npx mbkbucket [options]
69
-
70
- ${c.bold('OPTIONS:')}
71
- -p, --port <number> Port to listen on (default: 3004 or $PORT)
72
- -H, --host <host> Host address to bind (default: 0.0.0.0 or $HOST)
73
- -a, --app <name> Override APP_NAME for bucket key prefix isolation
74
- -b, --bucket <name> Override default bucket name (MBKAUTHE_BUCKET)
75
- -e, --env <path> Load environment variables from a custom .env file
76
- -d, --dev Run in development mode (NODE_ENV=dev)
77
- -o, --open Automatically open the dashboard in default browser
78
- -v, --version Show version number
79
- -h, --help Show this help message
80
-
81
- ${c.bold('ENVIRONMENT VARIABLES:')}
82
- PORT Server port (default: 3004)
83
- HOST Server host (default: 0.0.0.0)
84
- NODE_ENV Environment mode ('production' | 'dev')
85
- BucketConnection JSON mapping of bucket name -> S3 credentials
86
- mbkautheVar mbkauthe configuration JSON
87
- mbkbucketVar mbkbucket configuration JSON
88
-
89
- ${c.bold('EXAMPLES:')}
90
- $ mbkbucket
91
- $ mbkbucket -p 8080 --open
92
- $ mbkbucket --env ./configs/.env.prod -a myapp
93
- `);
94
- }
95
-
96
- function showVersion() {
97
- console.log(`mbkbucket v${packageJson.version}`);
98
- }
99
-
100
- function getNetworkIp() {
101
- try {
102
- const nets = os.networkInterfaces();
103
- for (const name of Object.keys(nets)) {
104
- for (const net of nets[name] ?? []) {
105
- if (net.family === 'IPv4' && !net.internal) return net.address;
106
- }
107
- }
108
- } catch {}
109
- return undefined;
110
- }
111
-
112
- function openBrowser(url) {
113
- const platform = process.platform;
114
- let cmd = '';
115
- if (platform === 'darwin') cmd = `open "${url}"`;
116
- else if (platform === 'win32') cmd = `start "" "${url}"`;
117
- else cmd = `xdg-open "${url}"`;
118
- import('node:child_process').then(({ exec }) => {
119
- exec(cmd, () => {});
120
- }).catch(() => {});
121
- }
122
-
123
- // ---------------------------------------------------------------------------
124
- // Main Runner
125
- // ---------------------------------------------------------------------------
126
- async function main() {
127
- if (hasFlag('help', 'h')) {
128
- showHelp();
129
- process.exit(0);
130
- }
131
-
132
- if (hasFlag('version', 'v')) {
133
- showVersion();
134
- process.exit(0);
135
- }
136
-
137
- // Load custom or default .env
138
- const envPath = findFlag('env', 'e');
139
- if (typeof envPath === 'string') {
140
- dotenv.config({ path: path.resolve(process.cwd(), envPath) });
141
- } else {
142
- dotenv.config();
143
- }
144
-
145
- // Handle environment overrides from flags
146
- const appFlag = findFlag('app', 'a');
147
- if (typeof appFlag === 'string') {
148
- process.env.APP_NAME = appFlag;
149
- }
150
-
151
- const bucketFlag = findFlag('bucket', 'b');
152
- if (typeof bucketFlag === 'string') {
153
- process.env.MBKAUTHE_BUCKET = bucketFlag;
154
- }
155
-
156
- if (hasFlag('dev', 'd')) {
157
- process.env.NODE_ENV = 'dev';
158
- }
159
-
160
- const port = parseInt(findFlag('port', 'p') || process.env.PORT || '3004', 10);
161
- const host = findFlag('host', 'H') || process.env.HOST || '0.0.0.0';
162
- const shouldOpen = hasFlag('open', 'o');
163
-
164
- // Check version in background
165
- await checkVersion();
166
-
167
- // Test S3 connectivity
168
- let healthResult = null;
169
- try {
170
- healthResult = await checkHealth();
171
- } catch (err) {
172
- healthResult = { status: 'unhealthy', error: err.message };
173
- }
174
-
175
- // Create express application
176
- const app = createApp();
177
-
178
- const server = app.listen(port, host, () => {
179
- const isAnyHost = host === '0.0.0.0' || host === '::' || host === '';
180
- const displayHost = isAnyHost ? 'localhost' : host;
181
- const localUrl = `http://${displayHost}:${port}/mbkbucket`;
182
-
183
- console.log();
184
- console.log(` ${c.cyan(c.bold('⚡ MBKBucket'))} ${c.dim(`v${packageJson.version}`)}`);
185
- console.log();
186
- console.log(` ${c.green('➜')} ${c.bold('Local:')} ${c.cyan(localUrl)}`);
187
-
188
- if (isAnyHost) {
189
- const netIp = getNetworkIp();
190
- if (netIp) {
191
- console.log(` ${c.green('➜')} ${c.bold('Network:')} ${c.cyan(`http://${netIp}:${port}/mbkbucket`)}`);
192
- }
193
- }
194
-
195
- const appName = process.env.APP_NAME || 'root';
196
- console.log(` ${c.green('➜')} ${c.bold('App Name:')} ${appName}`);
197
-
198
- let bucketNames = [];
199
- try {
200
- bucketNames = getAvailableBucketNames();
201
- } catch {}
202
-
203
- if (bucketNames.length > 0) {
204
- console.log(` ${c.green('➜')} ${c.bold('Buckets:')} ${bucketNames.join(', ')}`);
205
- }
206
-
207
- if (healthResult?.status === 'healthy') {
208
- console.log(` ${c.green('➜')} ${c.bold('Storage:')} ${c.green('✓ Connected')} (${healthResult.bucket} in ${healthResult.responseTime}ms)`);
209
- } else if (healthResult?.error) {
210
- console.log(` ${c.yellow('➜')} ${c.bold('Storage:')} ${c.yellow('⚠ Connection warning')} (${healthResult.error})`);
211
- }
212
-
213
- console.log();
214
- console.log(` ${c.dim('Press Ctrl+C to stop the server')}`);
215
- console.log();
216
-
217
- if (shouldOpen) {
218
- openBrowser(localUrl);
219
- }
220
- });
221
-
222
- const shutdown = (signal) => {
223
- console.log(`\n ${c.dim(`Received ${signal}, shutting down...`)}`);
224
- server.close(() => {
225
- console.log(` ${c.green('✓')} ${c.dim('MBKBucket server stopped.')}\n`);
226
- process.exit(0);
227
- });
228
- setTimeout(() => process.exit(0), 2000).unref();
229
- };
230
-
231
- process.on('SIGINT', () => shutdown('SIGINT'));
232
- process.on('SIGTERM', () => shutdown('SIGTERM'));
233
- }
234
-
235
- main().catch((err) => {
236
- console.error(`\n${c.red(c.bold('Error starting mbkbucket:'))} ${err.message}`);
237
- if (process.env.DEBUG) console.error(err);
238
- process.exit(1);
239
- });
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MBKBucket
5
+ * Copyright (c) 2026 Muhammad Bin Khalid, MBKTech.org and contributors
6
+ * Licensed under the MIT License.
7
+ * Source: https://github.com/MIbnEKhalid/mbkbucket
8
+ */
9
+
10
+ /**
11
+ * mbkbucket CLI — Standalone server runner for MBKBucket web application.
12
+ */
13
+
14
+ import dotenv from 'dotenv';
15
+ import path from 'node:path';
16
+ import os from 'node:os';
17
+ import { createApp } from './src/app.js';
18
+ import { packageJson, checkVersion } from './src/config/index.js';
19
+ import { checkHealth, getAvailableBucketNames } from './src/services/s3.service.js';
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // ANSI Color helpers
23
+ // ---------------------------------------------------------------------------
24
+ const c = {
25
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
26
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
27
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
28
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
29
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
30
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
31
+ };
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Parse CLI arguments
35
+ // ---------------------------------------------------------------------------
36
+ const args = process.argv.slice(2);
37
+
38
+ function findFlag(name, shortChar) {
39
+ const long = `--${name}`;
40
+ const short = shortChar ? `-${shortChar}` : `-${name[0]}`;
41
+ for (let i = 0; i < args.length; i++) {
42
+ if (args[i] === long || args[i] === short) {
43
+ if (args[i + 1] !== undefined && !args[i + 1].startsWith('-')) {
44
+ return args[i + 1];
45
+ }
46
+ return true;
47
+ }
48
+ }
49
+ return undefined;
50
+ }
51
+
52
+ const hasFlag = (name, shortChar) => {
53
+ const long = `--${name}`;
54
+ const short = shortChar ? `-${shortChar}` : `-${name[0]}`;
55
+ return args.includes(long) || args.includes(short);
56
+ };
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // Help & Version
60
+ // ---------------------------------------------------------------------------
61
+ function showHelp() {
62
+ console.log(`
63
+ ${c.cyan(c.bold('⚡ mbkbucket'))} ${c.dim(`v${packageJson.version}`)}
64
+ Standalone S3/R2 Bucket Management Server
65
+
66
+ ${c.bold('USAGE:')}
67
+ mbkbucket [options]
68
+ npx mbkbucket [options]
69
+
70
+ ${c.bold('OPTIONS:')}
71
+ -p, --port <number> Port to listen on (default: 3004 or $PORT)
72
+ -H, --host <host> Host address to bind (default: 0.0.0.0 or $HOST)
73
+ -a, --app <name> Override APP_NAME for bucket key prefix isolation
74
+ -b, --bucket <name> Override default bucket name (MBKAUTHE_BUCKET)
75
+ -e, --env <path> Load environment variables from a custom .env file
76
+ -d, --dev Run in development mode (NODE_ENV=dev)
77
+ -o, --open Automatically open the dashboard in default browser
78
+ -v, --version Show version number
79
+ -h, --help Show this help message
80
+
81
+ ${c.bold('ENVIRONMENT VARIABLES:')}
82
+ PORT Server port (default: 3004)
83
+ HOST Server host (default: 0.0.0.0)
84
+ NODE_ENV Environment mode ('production' | 'dev')
85
+ BucketConnection JSON mapping of bucket name -> S3 credentials
86
+ mbkautheVar mbkauthe configuration JSON
87
+ mbkbucketVar mbkbucket configuration JSON
88
+
89
+ ${c.bold('EXAMPLES:')}
90
+ $ mbkbucket
91
+ $ mbkbucket -p 8080 --open
92
+ $ mbkbucket --env ./configs/.env.prod -a myapp
93
+ `);
94
+ }
95
+
96
+ function showVersion() {
97
+ console.log(`mbkbucket v${packageJson.version}`);
98
+ }
99
+
100
+ function getNetworkIp() {
101
+ try {
102
+ const nets = os.networkInterfaces();
103
+ for (const name of Object.keys(nets)) {
104
+ for (const net of nets[name] ?? []) {
105
+ if (net.family === 'IPv4' && !net.internal) return net.address;
106
+ }
107
+ }
108
+ } catch {}
109
+ return undefined;
110
+ }
111
+
112
+ function openBrowser(url) {
113
+ const platform = process.platform;
114
+ let cmd = '';
115
+ if (platform === 'darwin') cmd = `open "${url}"`;
116
+ else if (platform === 'win32') cmd = `start "" "${url}"`;
117
+ else cmd = `xdg-open "${url}"`;
118
+ import('node:child_process').then(({ exec }) => {
119
+ exec(cmd, () => {});
120
+ }).catch(() => {});
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // Main Runner
125
+ // ---------------------------------------------------------------------------
126
+ async function main() {
127
+ if (hasFlag('help', 'h')) {
128
+ showHelp();
129
+ process.exit(0);
130
+ }
131
+
132
+ if (hasFlag('version', 'v')) {
133
+ showVersion();
134
+ process.exit(0);
135
+ }
136
+
137
+ // Load custom or default .env
138
+ const envPath = findFlag('env', 'e');
139
+ if (typeof envPath === 'string') {
140
+ dotenv.config({ path: path.resolve(process.cwd(), envPath) });
141
+ } else {
142
+ dotenv.config();
143
+ }
144
+
145
+ // Handle environment overrides from flags
146
+ const appFlag = findFlag('app', 'a');
147
+ if (typeof appFlag === 'string') {
148
+ process.env.APP_NAME = appFlag;
149
+ }
150
+
151
+ const bucketFlag = findFlag('bucket', 'b');
152
+ if (typeof bucketFlag === 'string') {
153
+ process.env.MBKAUTHE_BUCKET = bucketFlag;
154
+ }
155
+
156
+ if (hasFlag('dev', 'd')) {
157
+ process.env.NODE_ENV = 'dev';
158
+ }
159
+
160
+ const port = parseInt(findFlag('port', 'p') || process.env.PORT || '3004', 10);
161
+ const host = findFlag('host', 'H') || process.env.HOST || '0.0.0.0';
162
+ const shouldOpen = hasFlag('open', 'o');
163
+
164
+ // Check version in background
165
+ await checkVersion();
166
+
167
+ // Test S3 connectivity
168
+ let healthResult = null;
169
+ try {
170
+ healthResult = await checkHealth();
171
+ } catch (err) {
172
+ healthResult = { status: 'unhealthy', error: err.message };
173
+ }
174
+
175
+ // Create express application
176
+ const app = createApp();
177
+
178
+ const server = app.listen(port, host, () => {
179
+ const isAnyHost = host === '0.0.0.0' || host === '::' || host === '';
180
+ const displayHost = isAnyHost ? 'localhost' : host;
181
+ const localUrl = `http://${displayHost}:${port}/mbkbucket`;
182
+
183
+ console.log();
184
+ console.log(` ${c.cyan(c.bold('⚡ MBKBucket'))} ${c.dim(`v${packageJson.version}`)}`);
185
+ console.log();
186
+ console.log(` ${c.green('➜')} ${c.bold('Local:')} ${c.cyan(localUrl)}`);
187
+
188
+ if (isAnyHost) {
189
+ const netIp = getNetworkIp();
190
+ if (netIp) {
191
+ console.log(` ${c.green('➜')} ${c.bold('Network:')} ${c.cyan(`http://${netIp}:${port}/mbkbucket`)}`);
192
+ }
193
+ }
194
+
195
+ const appName = process.env.APP_NAME || 'root';
196
+ console.log(` ${c.green('➜')} ${c.bold('App Name:')} ${appName}`);
197
+
198
+ let bucketNames = [];
199
+ try {
200
+ bucketNames = getAvailableBucketNames();
201
+ } catch {}
202
+
203
+ if (bucketNames.length > 0) {
204
+ console.log(` ${c.green('➜')} ${c.bold('Buckets:')} ${bucketNames.join(', ')}`);
205
+ }
206
+
207
+ if (healthResult?.status === 'healthy') {
208
+ console.log(` ${c.green('➜')} ${c.bold('Storage:')} ${c.green('✓ Connected')} (${healthResult.bucket} in ${healthResult.responseTime}ms)`);
209
+ } else if (healthResult?.error) {
210
+ console.log(` ${c.yellow('➜')} ${c.bold('Storage:')} ${c.yellow('⚠ Connection warning')} (${healthResult.error})`);
211
+ }
212
+
213
+ console.log();
214
+ console.log(` ${c.dim('Press Ctrl+C to stop the server')}`);
215
+ console.log();
216
+
217
+ if (shouldOpen) {
218
+ openBrowser(localUrl);
219
+ }
220
+ });
221
+
222
+ const shutdown = (signal) => {
223
+ console.log(`\n ${c.dim(`Received ${signal}, shutting down...`)}`);
224
+ server.close(() => {
225
+ console.log(` ${c.green('✓')} ${c.dim('MBKBucket server stopped.')}\n`);
226
+ process.exit(0);
227
+ });
228
+ setTimeout(() => process.exit(0), 2000).unref();
229
+ };
230
+
231
+ process.on('SIGINT', () => shutdown('SIGINT'));
232
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
233
+ }
234
+
235
+ main().catch((err) => {
236
+ console.error(`\n${c.red(c.bold('Error starting mbkbucket:'))} ${err.message}`);
237
+ if (process.env.DEBUG) console.error(err);
238
+ process.exit(1);
239
+ });