mbkbucket 3.3.1 → 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 (34) hide show
  1. package/index.js +2 -12
  2. package/lib/cli.js +178 -512
  3. package/lib/public/bucketadmin.js +1 -1
  4. package/lib/src/app.js +37 -50
  5. package/lib/src/cli/auth-helper.js +24 -103
  6. package/lib/src/config/index.js +69 -94
  7. package/lib/src/config/validation.js +14 -30
  8. package/lib/src/controllers/api.controller.js +85 -176
  9. package/lib/src/controllers/dashboard.controller.js +12 -23
  10. package/lib/src/controllers/info.controller.js +17 -20
  11. package/lib/src/controllers/view.controller.js +23 -70
  12. package/lib/src/middleware/async-handler.js +1 -16
  13. package/lib/src/middleware/bucket-resolver.js +7 -13
  14. package/lib/src/middleware/error-handler.js +6 -14
  15. package/lib/src/middleware/rate-limiter.js +2 -10
  16. package/lib/src/middleware/security.js +1 -17
  17. package/lib/src/routes/api.routes.js +21 -47
  18. package/lib/src/routes/index.js +1 -9
  19. package/lib/src/routes/info.routes.js +2 -3
  20. package/lib/src/routes/view.routes.js +3 -8
  21. package/lib/src/services/s3.service.js +157 -349
  22. package/lib/src/utils/errors.js +28 -59
  23. package/lib/src/utils/helpers.js +124 -70
  24. package/package.json +6 -1
  25. /package/{lib/views → views}/bucket.handlebars +0 -0
  26. /package/{lib/views → views}/bucketadmin_alerts.handlebars +0 -0
  27. /package/{lib/views → views}/bucketadmin_delete_modal.handlebars +0 -0
  28. /package/{lib/views → views}/bucketadmin_filelist_skeleton.handlebars +0 -0
  29. /package/{lib/views → views}/bucketadmin_newfolder_modal.handlebars +0 -0
  30. /package/{lib/views → views}/bucketadmin_preview_modal.handlebars +0 -0
  31. /package/{lib/views → views}/bucketadmin_upload_modal.handlebars +0 -0
  32. /package/{lib/views → views}/bucketadmincontent.handlebars +0 -0
  33. /package/{lib/views → views}/bucketportal.handlebars +0 -0
  34. /package/{lib/views → views}/mbkbucket_info.handlebars +0 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * MBKBucket File Manager - Gentelella v4 UI & Client Logic
2
+ * MBKBucket File Manager - UI & Client Logic
3
3
  */
4
4
 
5
5
  (function () {
package/lib/src/app.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import express from "express";
2
2
  import path from "path";
3
+ import fs from "fs";
3
4
  import { fileURLToPath } from "url";
4
5
  import { engine } from "express-handlebars";
5
6
  import compression from "compression";
@@ -8,34 +9,25 @@ import { generalLimiter } from "./middleware/rate-limiter.js";
8
9
  import { notFoundHandler, globalErrorHandler } from "./middleware/error-handler.js";
9
10
  import bucketRoutes from "./routes/index.js";
10
11
  import { packageJson } from "./config/index.js";
11
- import { createLogger } from "./utils/logger.js";
12
+ import { createLogger } from "#logger";
12
13
  import { commonHandlebarsHelpers } from "./utils/helpers.js";
13
14
 
14
15
  const debugServer = createLogger('server');
15
-
16
16
  const __filename = fileURLToPath(import.meta.url);
17
17
  const __dirname = path.dirname(__filename);
18
18
  const isDevMode = process.env.NODE_ENV === "dev";
19
19
 
20
- /**
21
- * Creates and configures the Express application.
22
- * @returns {express.Application}
23
- */
24
20
  export function createApp() {
25
21
  const server = express();
26
22
  server.set('trust proxy', 1);
27
23
 
28
- // Compression
29
24
  server.use(compression());
30
-
31
- // Body parsing
32
25
  server.use(express.json({ limit: '10mb' }));
33
26
  server.use(express.urlencoded({ extended: true, limit: '10mb' }));
34
27
 
35
- // Static assets (CSS/JS for dashboard)
36
- const dashboardAssetCacheControl = 'public, max-age=300, must-revalidate';
37
- const serveAsset = (filename) => (req, res) => {
38
- res.set('Cache-Control', dashboardAssetCacheControl);
28
+ // Static dashboard & helper assets
29
+ const serveAsset = (filename) => (_req, res) => {
30
+ res.set('Cache-Control', 'public, max-age=300, must-revalidate');
39
31
  res.sendFile(path.join(__dirname, '..', 'public', filename), (err) => {
40
32
  if (err) res.status(err.status || 404).end();
41
33
  });
@@ -43,71 +35,66 @@ export function createApp() {
43
35
 
44
36
  server.get('/mbkbucket/bucketadmin.css', serveAsset('bucketadmin.css'));
45
37
  server.get('/mbkbucket/bucketadmin.js', serveAsset('bucketadmin.js'));
46
-
47
- // Frontend helper utilities (drop-in for any HTML page)
48
38
  server.get('/mbkbucket/mbkbucket-helper.css', serveAsset('mbkbucket-helper.css'));
49
39
  server.get('/mbkbucket/mbkbucket-helper.js', serveAsset('mbkbucket-helper.js'));
50
-
51
- // Helper component demo page (no auth — purely static HTML)
52
40
  server.get('/mbkbucket/helper-demo', serveAsset('mbkbucket-helper-demo.html'));
53
41
 
54
- // Handlebars configuration
42
+ const rootDir = path.resolve(__dirname, "..", "..");
43
+ const libDir = path.resolve(__dirname, "..");
44
+ const cwd = process.cwd();
45
+
46
+ const viewDirs = [
47
+ path.join(rootDir, "views"),
48
+ path.join(libDir, "views"),
49
+ path.join(rootDir, "node_modules", "mbkauthe", "views"),
50
+ path.resolve(cwd, "views"),
51
+ path.resolve(cwd, "node_modules", "mbkauthe", "views"),
52
+ ].filter(dir => fs.existsSync(dir));
53
+
54
+ const partialsDir = [
55
+ path.join(rootDir, "views", "templates"),
56
+ path.join(rootDir, "views", "templates", "notice"),
57
+ path.join(rootDir, "views"),
58
+ path.join(rootDir, "views", "partial"),
59
+ path.join(libDir, "views", "templates"),
60
+ path.join(libDir, "views", "templates", "notice"),
61
+ path.join(libDir, "views"),
62
+ path.join(libDir, "views", "partial"),
63
+ path.join(rootDir, "node_modules", "mbkauthe", "views"),
64
+ path.resolve(cwd, "node_modules", "mbkauthe", "views"),
65
+ ].filter(dir => fs.existsSync(dir));
66
+
67
+ // Handlebars template engine
55
68
  server.engine("handlebars", engine({
56
69
  extname: ".handlebars",
57
70
  defaultLayout: false,
58
- partialsDir: [
59
- path.join(__dirname, "..", "views", "templates"),
60
- path.join(__dirname, "..", "views", "templates", "notice"),
61
- path.join(__dirname, "..", "views"),
62
- path.join(__dirname, "..", "views", "partial"),
63
- path.join(__dirname, "..", "node_modules", "mbkauthe", "views"),
64
- path.join(__dirname, "..", "..", "mbkauthe", "views")
65
- ],
71
+ partialsDir: [...new Set(partialsDir)],
66
72
  cache: process.env.NODE_ENV === "production",
67
73
  helpers: {
68
74
  ...commonHandlebarsHelpers,
69
- mbkbucket_cachebuster: function () {
70
- return "?v=" + packageJson.version;
71
- }
75
+ mbkbucket_cachebuster: () => `?v=${packageJson.version}`
72
76
  }
73
77
  }));
74
78
 
75
79
  server.set("view engine", "handlebars");
76
- server.set("views", [
77
- path.join(__dirname, "..", "views"),
78
- path.join(__dirname, "..", "node_modules", "mbkauthe", "views"),
79
- path.join(__dirname, "..", "..", "mbkauthe", "views")
80
- ]);
80
+ server.set("views", [...new Set(viewDirs)]);
81
81
 
82
- // Auth routes
83
82
  server.use(mbkautheRoutes);
84
-
85
- // Rate limiting
86
83
  server.use(generalLimiter);
87
-
88
- // Bucket routes
89
84
  server.use(bucketRoutes);
90
85
 
91
- // Dev-mode request timing
92
86
  if (isDevMode) {
93
- debugServer("Dev mode is enabled. Starting server in dev mode.");
94
-
95
87
  server.use((req, res, next) => {
96
- const start = process.hrtime();
88
+ const start = Date.now();
97
89
  res.on('finish', () => {
98
- const diff = process.hrtime(start);
99
- const ms = diff[0] * 1000 + diff[1] / 1e6;
100
- debugServer("[%s] %s %s %s - %s ms", new Date().toISOString(), req.method, req.originalUrl, res.statusCode, ms.toFixed(3));
90
+ debugServer('%s %s %s (%sms)', req.method, req.originalUrl, res.statusCode, Date.now() - start);
101
91
  });
102
92
  next();
103
93
  });
104
94
 
105
- server.get("/", async (req, res) => {
106
- res.redirect("/mbkbucket");
107
- });
95
+ server.get("/", (_req, res) => res.redirect("/mbkbucket"));
108
96
  }
109
97
 
110
- // Error handlers
111
98
  server.use(notFoundHandler);
112
99
  server.use(globalErrorHandler);
113
100
 
@@ -1,6 +1,5 @@
1
1
  /**
2
2
  * CLI Authentication Helper
3
- *
4
3
  * Handles mbkauthe device-flow login for the mbkbucket CLI.
5
4
  * Stores credentials in ~/.mbkbucket/config.json
6
5
  */
@@ -8,39 +7,27 @@
8
7
  import fs from 'node:fs';
9
8
  import path from 'node:path';
10
9
  import os from 'node:os';
11
- import { createLogger } from '../utils/logger.js';
10
+ import { createLogger } from '#logger';
12
11
 
13
12
  const debugCli = createLogger('cli:auth');
14
13
 
15
14
  export const CONFIG_DIR = path.join(os.homedir(), '.mbkbucket');
16
15
  export const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
17
- const POLL_INTERVAL_MS = 5000;
18
16
  const MAX_POLL_TIME_MS = 15 * 60 * 1000; // 15 minutes
17
+ const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
19
18
 
20
- /**
21
- * Read the stored CLI config.
22
- * @returns {{ token?: string, tokenPrefix?: string, username?: string, serverUrl?: string, profile?: object }}
23
- */
24
19
  export function readConfig() {
25
20
  try {
26
- if (!fs.existsSync(CONFIG_FILE)) return {};
27
- const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
28
- return JSON.parse(raw);
21
+ return fs.existsSync(CONFIG_FILE) ? JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8')) : {};
29
22
  } catch (err) {
30
23
  debugCli('Failed to read config: %s', err.message);
31
24
  return {};
32
25
  }
33
26
  }
34
27
 
35
- /**
36
- * Write config to disk.
37
- * @param {object} config
38
- */
39
28
  export function writeConfig(config) {
40
29
  try {
41
- if (!fs.existsSync(CONFIG_DIR)) {
42
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
43
- }
30
+ if (!fs.existsSync(CONFIG_DIR)) fs.mkdirSync(CONFIG_DIR, { recursive: true });
44
31
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
45
32
  } catch (err) {
46
33
  console.error(`❌ Failed to write config: ${err.message}`);
@@ -48,14 +35,9 @@ export function writeConfig(config) {
48
35
  }
49
36
  }
50
37
 
51
- /**
52
- * Clear stored credentials (logout).
53
- */
54
38
  export function clearConfig() {
55
39
  try {
56
- if (fs.existsSync(CONFIG_FILE)) {
57
- fs.unlinkSync(CONFIG_FILE);
58
- }
40
+ if (fs.existsSync(CONFIG_FILE)) fs.unlinkSync(CONFIG_FILE);
59
41
  return true;
60
42
  } catch (err) {
61
43
  debugCli('Failed to clear config: %s', err.message);
@@ -63,49 +45,27 @@ export function clearConfig() {
63
45
  }
64
46
  }
65
47
 
66
- /**
67
- * Merge partial config into stored config.
68
- * @param {object} partial
69
- */
70
48
  export function updateConfig(partial) {
71
- const current = readConfig();
72
- const updated = { ...current, ...partial };
49
+ const updated = { ...readConfig(), ...partial };
73
50
  writeConfig(updated);
74
51
  return updated;
75
52
  }
76
53
 
77
- /**
78
- * Check if the user is logged in (has a stored token).
79
- */
80
54
  export function isLoggedIn() {
81
- const cfg = readConfig();
82
- return !!(cfg.token && cfg.serverUrl);
55
+ const { token, serverUrl } = readConfig();
56
+ return Boolean(token && serverUrl);
83
57
  }
84
58
 
85
- /**
86
- * Get the stored API token.
87
- */
88
59
  export function getStoredToken() {
89
60
  return readConfig().token || null;
90
61
  }
91
62
 
92
- /**
93
- * Get the stored server URL.
94
- */
95
63
  export function getStoredServerUrl() {
96
64
  return readConfig().serverUrl || null;
97
65
  }
98
66
 
99
- /**
100
- * Perform a device-flow login against an mbkauthe-powered server.
101
- *
102
- * @param {{ serverUrl: string, profileKey?: string }} options
103
- * @returns {Promise<{ token: string, tokenPrefix: string, username: string, profile: object }>}
104
- */
105
67
  export async function deviceFlowLogin({ serverUrl, profileKey }) {
106
68
  const baseUrl = String(serverUrl).replace(/\/+$/, '');
107
-
108
- // --- Step 1: Request a device code ---
109
69
  console.log(`🔑 Requesting device login from ${baseUrl} ...`);
110
70
 
111
71
  let deviceResp;
@@ -115,53 +75,32 @@ export async function deviceFlowLogin({ serverUrl, profileKey }) {
115
75
  headers: { 'Content-Type': 'application/json' },
116
76
  body: JSON.stringify({
117
77
  clientName: `mbkbucket-cli-${os.hostname()}`,
118
- ...(profileKey ? { profileKey } : {}),
78
+ ...(profileKey && { profileKey }),
119
79
  }),
120
80
  });
121
-
122
81
  deviceResp = await res.json();
123
-
124
- if (!deviceResp.success) {
125
- throw new Error(deviceResp.message || 'Failed to initiate device login');
126
- }
82
+ if (!deviceResp.success) throw new Error(deviceResp.message || 'Failed to initiate device login');
127
83
  } catch (err) {
128
84
  if (err.message.includes('Failed to initiate') || err.message.includes('fetch')) {
129
- throw new Error(
130
- `Could not reach mbkauthe server at ${baseUrl}/api/cli/device.\n` +
131
- `Verify the server URL and that CLI_AUTH_ENABLED=true on the server.`
132
- );
85
+ throw new Error(`Could not reach mbkauthe server at ${baseUrl}/api/cli/device.\nVerify the server URL and that CLI_AUTH_ENABLED=true on the server.`);
133
86
  }
134
87
  throw err;
135
88
  }
136
89
 
137
- const {
138
- verificationUrl,
139
- userCode,
140
- deviceCode,
141
- expiresIn,
142
- interval,
143
- profile,
144
- } = deviceResp;
145
-
146
- // --- Step 2: Prompt user to approve ---
147
- console.log('');
148
- console.log('┌─────────────────────────────────────────────────────────┐');
90
+ const { verificationUrl, userCode, deviceCode, expiresIn, interval, profile } = deviceResp;
91
+
92
+ console.log('\n┌─────────────────────────────────────────────────────────┐');
149
93
  console.log('│ │');
150
- console.log(`│ 🌐 Open this URL in your browser to approve: │`);
94
+ console.log('│ 🌐 Open this URL in your browser to approve: │');
151
95
  console.log(`│ ${verificationUrl.padEnd(53)}│`);
152
- console.log(`│ │`);
96
+ console.log('│ │');
153
97
  console.log(`│ 🔢 Or enter this code: ${userCode.padEnd(30)}│`);
154
98
  console.log('│ │');
155
- console.log('└─────────────────────────────────────────────────────────┘');
156
- console.log('');
99
+ console.log('└─────────────────────────────────────────────────────────┘\n');
157
100
 
158
- if (profile) {
159
- console.log(` Profile: ${profile.name} (scope: ${profile.scope || 'full'})`);
160
- }
161
- console.log(` Waiting for approval (expires in ${Math.floor(expiresIn / 60)} minutes)...`);
162
- console.log('');
101
+ if (profile) console.log(` Profile: ${profile.name} (scope: ${profile.scope || 'full'})`);
102
+ console.log(` Waiting for approval (expires in ${Math.floor(expiresIn / 60)} minutes)...\n`);
163
103
 
164
- // --- Step 3: Poll for token ---
165
104
  const pollInterval = (interval || 5) * 1000;
166
105
  const deadline = Date.now() + MAX_POLL_TIME_MS;
167
106
  let attempts = 0;
@@ -190,34 +129,16 @@ export async function deviceFlowLogin({ serverUrl, profileKey }) {
190
129
  };
191
130
  }
192
131
 
193
- if (pollBody.status === 'denied') {
194
- throw new Error('Login request was denied.');
195
- }
132
+ if (pollBody.status === 'denied') throw new Error('Login request was denied.');
133
+ if (pollBody.status === 'expired') throw new Error('Login request expired. Please try again.');
134
+ if (pollBody.status === 'completed') throw new Error('This login session has already been completed.');
196
135
 
197
- if (pollBody.status === 'expired') {
198
- throw new Error('Login request expired. Please try again.');
199
- }
200
-
201
- if (pollBody.status === 'completed') {
202
- throw new Error('This login session has already been completed.');
203
- }
204
-
205
- // Still pending — show a dot every 5 polls
206
- if (attempts % 5 === 0) {
207
- process.stdout.write('.');
208
- }
136
+ if (attempts % 5 === 0) process.stdout.write('.');
209
137
  } catch (err) {
210
- if (err.message.includes('denied') || err.message.includes('expired') || err.message.includes('completed')) {
211
- throw err;
212
- }
213
- // Network errors during poll — retry
138
+ if (['denied', 'expired', 'completed'].some(k => err.message.includes(k))) throw err;
214
139
  debugCli('Poll error (will retry): %s', err.message);
215
140
  }
216
141
  }
217
142
 
218
143
  throw new Error('Login timed out. Please try again.');
219
144
  }
220
-
221
- function sleep(ms) {
222
- return new Promise((resolve) => setTimeout(resolve, ms));
223
- }
@@ -1,133 +1,108 @@
1
1
  import { createRequire } from "module";
2
2
  import dotenv from "dotenv";
3
3
  import { parseAndValidateMbkbucketVar, parseAndValidateBucketConnection } from "./validation.js";
4
- import { createLogger } from "../utils/logger.js";
4
+ import { createLogger } from "#logger";
5
5
 
6
6
  dotenv.config();
7
7
  const debugConfig = createLogger('config');
8
-
9
- // Load package.json from mbkbucket package (not parent project)
10
8
  const require = createRequire(import.meta.url);
9
+
10
+ // Load mbkbucket package.json
11
11
  let packageJson;
12
12
  try {
13
- // Try to load from mbkbucket package directory
14
- packageJson = require("mbkbucket/package.json");
13
+ packageJson = require("mbkbucket/package.json");
15
14
  } catch {
16
- // Fallback to relative path (for development/testing)
17
- packageJson = require("../../../package.json");
15
+ packageJson = require("../../../package.json");
18
16
  }
19
17
 
20
18
  // Parent project version
21
- let appVersion;
19
+ let appVersion = "unknown";
22
20
  try {
23
- appVersion = require("../../../../package.json")?.version || "unknown";
21
+ appVersion = require("../../../../package.json")?.version ?? require(`${process.cwd()}/package.json`)?.version ?? "unknown";
24
22
  } 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
- }
23
+ try {
24
+ appVersion = require(`${process.cwd()}/package.json`)?.version ?? "unknown";
25
+ } catch {}
31
26
  }
32
27
 
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);
28
+ export function compareVersions(a = '', b = '') {
29
+ const left = String(a).split(/[.-]/).map(p => parseInt(p, 10) || 0);
30
+ const right = String(b).split(/[.-]/).map(p => parseInt(p, 10) || 0);
31
+ const len = Math.max(left.length, right.length);
37
32
 
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;
33
+ for (let i = 0; i < len; i++) {
34
+ const diff = (left[i] || 0) - (right[i] || 0);
35
+ if (diff !== 0) return diff;
36
+ }
37
+ return 0;
43
38
  }
44
39
 
45
- // Fetch latest version from GitHub
46
- async function getLatestVersion() {
40
+ export async function getLatestVersion() {
47
41
  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);
42
+ const res = await fetch('https://raw.githubusercontent.com/MIbnEKhalid/mbkbucket/master/package.json');
43
+ if (!res.ok) {
44
+ debugConfig('GitHub API responded with status %s', res.status);
51
45
  return "0.0.0";
52
46
  }
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);
47
+ const data = await res.json();
48
+ return data.version;
49
+ } catch (err) {
50
+ debugConfig('Error fetching latest version from GitHub: %s', err.message);
58
51
  return null;
59
52
  }
60
53
  }
61
54
 
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);
55
+ export async function checkVersion() {
56
+ try {
57
+ const latest = await getLatestVersion();
58
+ if (!latest) return;
59
+ const diff = compareVersions(latest, packageJson.version);
60
+ if (diff > 0) {
61
+ console.log(`[mbkbucket] ⚠️ Update available: v${latest} (current: v${packageJson.version})`);
62
+ } else {
63
+ debugConfig('Running latest version (%s).', packageJson.version);
75
64
  }
65
+ } catch (err) {
66
+ debugConfig('Failed to check for updates: %s', err.message);
67
+ }
76
68
  }
77
69
 
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
- }
70
+ export function validateConfiguration() {
71
+ try {
72
+ return parseAndValidateMbkbucketVar(process.env.mbkbucketVar);
73
+ } catch (err) {
74
+ throw new Error(`[mbkbucket] Configuration Validation Failed:\n - ${err.message}`);
75
+ }
90
76
  }
91
77
 
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
- }
78
+ export function validateBucketConnection() {
79
+ if (!process.env.BucketConnection) {
80
+ console.warn(`[mbkbucket] ⚠️ BucketConnection not configured. You need to set this environment variable.`);
81
+ console.warn(`[mbkbucket] Example format:\n[mbkbucket] BucketConnection={"r2":{"BUCKET_NAME":"my-bucket","ACCESS_KEY_ID":"key","SECRET_ACCESS_KEY":"secret","ENDPOINT":"https://..."}}`);
82
+ return;
83
+ }
84
+ try {
85
+ parseAndValidateBucketConnection(process.env.BucketConnection);
86
+ debugConfig('BucketConnection validated');
87
+ } catch (err) {
88
+ throw new Error(`[mbkbucket] BucketConnection validation failed:\n - ${err.message}`);
89
+ }
107
90
  }
108
91
 
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
- }
92
+ export function validateAllConfiguration() {
93
+ try {
94
+ validateConfiguration();
95
+ validateBucketConnection();
96
+ return true;
97
+ } catch (err) {
98
+ console.error(err.message);
99
+ return false;
100
+ }
120
101
  }
121
102
 
122
- const mbkbucketVar = validateConfiguration();
103
+ export const mbkbucketVar = validateConfiguration();
123
104
 
124
105
  export {
125
- packageJson,
126
- appVersion,
127
- mbkbucketVar,
128
- checkVersion,
129
- getLatestVersion,
130
- validateConfiguration,
131
- validateBucketConnection,
132
- validateAllConfiguration
106
+ packageJson,
107
+ appVersion
133
108
  };