@bragduck/cli 2.7.0 → 2.8.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/dist/bin/bragduck.js +511 -129
- package/dist/bin/bragduck.js.map +1 -1
- package/dist/index.js +275 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ var init_esm_shims = __esm({
|
|
|
22
22
|
import { config } from "dotenv";
|
|
23
23
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
24
24
|
import { dirname, join } from "path";
|
|
25
|
-
var __filename, __dirname, APP_NAME, DEFAULT_CONFIG, OAUTH_CONFIG, API_ENDPOINTS, ENCRYPTION_CONFIG, STORAGE_PATHS, HTTP_STATUS;
|
|
25
|
+
var __filename, __dirname, APP_NAME, DEFAULT_CONFIG, OAUTH_CONFIG, API_ENDPOINTS, ENCRYPTION_CONFIG, STORAGE_PATHS, HTTP_STATUS, CONFIG_FILES;
|
|
26
26
|
var init_constants = __esm({
|
|
27
27
|
"src/constants.ts"() {
|
|
28
28
|
"use strict";
|
|
@@ -33,7 +33,12 @@ var init_constants = __esm({
|
|
|
33
33
|
APP_NAME = "bragduck";
|
|
34
34
|
DEFAULT_CONFIG = {
|
|
35
35
|
defaultCommitDays: 30,
|
|
36
|
-
autoVersionCheck: true
|
|
36
|
+
autoVersionCheck: true,
|
|
37
|
+
defaultSource: void 0,
|
|
38
|
+
sourcePriority: void 0,
|
|
39
|
+
jiraInstance: void 0,
|
|
40
|
+
confluenceInstance: void 0,
|
|
41
|
+
gitlabInstance: void 0
|
|
37
42
|
};
|
|
38
43
|
OAUTH_CONFIG = {
|
|
39
44
|
CLIENT_ID: "bragduck-cli",
|
|
@@ -88,6 +93,222 @@ var init_constants = __esm({
|
|
|
88
93
|
NOT_FOUND: 404,
|
|
89
94
|
INTERNAL_SERVER_ERROR: 500
|
|
90
95
|
};
|
|
96
|
+
CONFIG_FILES = [".bragduckrc", ".bragduck/config.json", ".bragduckrc.json"];
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// src/utils/env-loader.ts
|
|
101
|
+
function parseEnvNumber(key) {
|
|
102
|
+
const value = process.env[key];
|
|
103
|
+
if (!value) return void 0;
|
|
104
|
+
const parsed = parseInt(value, 10);
|
|
105
|
+
return isNaN(parsed) ? void 0 : parsed;
|
|
106
|
+
}
|
|
107
|
+
function parseEnvBoolean(key) {
|
|
108
|
+
const value = process.env[key]?.toLowerCase();
|
|
109
|
+
if (!value) return void 0;
|
|
110
|
+
if (["true", "yes", "1"].includes(value)) return true;
|
|
111
|
+
if (["false", "no", "0"].includes(value)) return false;
|
|
112
|
+
return void 0;
|
|
113
|
+
}
|
|
114
|
+
function parseEnvArray(key) {
|
|
115
|
+
const value = process.env[key];
|
|
116
|
+
if (!value) return void 0;
|
|
117
|
+
const items = value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
118
|
+
return items.length > 0 ? items : void 0;
|
|
119
|
+
}
|
|
120
|
+
function parseEnvSource(key) {
|
|
121
|
+
const value = process.env[key];
|
|
122
|
+
if (!value) return void 0;
|
|
123
|
+
const validSources = ["github", "gitlab", "bitbucket", "jira", "confluence"];
|
|
124
|
+
return validSources.includes(value) ? value : void 0;
|
|
125
|
+
}
|
|
126
|
+
function loadEnvConfig() {
|
|
127
|
+
return {
|
|
128
|
+
// Source configuration
|
|
129
|
+
source: parseEnvSource("BRAGDUCK_SOURCE"),
|
|
130
|
+
jiraInstance: process.env.BRAGDUCK_JIRA_INSTANCE,
|
|
131
|
+
confluenceInstance: process.env.BRAGDUCK_CONFLUENCE_INSTANCE,
|
|
132
|
+
gitlabInstance: process.env.BRAGDUCK_GITLAB_INSTANCE,
|
|
133
|
+
// Behavior configuration
|
|
134
|
+
defaultCommitDays: parseEnvNumber("BRAGDUCK_DEFAULT_COMMIT_DAYS"),
|
|
135
|
+
autoVersionCheck: parseEnvBoolean("BRAGDUCK_AUTO_VERSION_CHECK"),
|
|
136
|
+
sourcePriority: parseEnvArray("BRAGDUCK_SOURCE_PRIORITY"),
|
|
137
|
+
// Credential overrides (for CI/CD)
|
|
138
|
+
jiraToken: process.env.BRAGDUCK_JIRA_TOKEN,
|
|
139
|
+
confluenceToken: process.env.BRAGDUCK_CONFLUENCE_TOKEN,
|
|
140
|
+
gitlabToken: process.env.BRAGDUCK_GITLAB_TOKEN
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
var init_env_loader = __esm({
|
|
144
|
+
"src/utils/env-loader.ts"() {
|
|
145
|
+
"use strict";
|
|
146
|
+
init_esm_shims();
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// src/utils/errors.ts
|
|
151
|
+
var BragduckError, AuthenticationError, ApiError, NetworkError, ValidationError, OAuthError, TokenExpiredError;
|
|
152
|
+
var init_errors = __esm({
|
|
153
|
+
"src/utils/errors.ts"() {
|
|
154
|
+
"use strict";
|
|
155
|
+
init_esm_shims();
|
|
156
|
+
BragduckError = class extends Error {
|
|
157
|
+
code;
|
|
158
|
+
details;
|
|
159
|
+
constructor(message, code, details) {
|
|
160
|
+
super(message);
|
|
161
|
+
this.name = "BragduckError";
|
|
162
|
+
this.code = code;
|
|
163
|
+
this.details = details;
|
|
164
|
+
Error.captureStackTrace(this, this.constructor);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
AuthenticationError = class extends BragduckError {
|
|
168
|
+
constructor(message, details) {
|
|
169
|
+
super(message, "AUTH_ERROR", details);
|
|
170
|
+
this.name = "AuthenticationError";
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
ApiError = class extends BragduckError {
|
|
174
|
+
statusCode;
|
|
175
|
+
constructor(message, statusCode, details) {
|
|
176
|
+
super(message, "API_ERROR", details);
|
|
177
|
+
this.name = "ApiError";
|
|
178
|
+
this.statusCode = statusCode;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
NetworkError = class extends BragduckError {
|
|
182
|
+
constructor(message, details) {
|
|
183
|
+
super(message, "NETWORK_ERROR", details);
|
|
184
|
+
this.name = "NetworkError";
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
ValidationError = class extends BragduckError {
|
|
188
|
+
constructor(message, details) {
|
|
189
|
+
super(message, "VALIDATION_ERROR", details);
|
|
190
|
+
this.name = "ValidationError";
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
OAuthError = class extends AuthenticationError {
|
|
194
|
+
constructor(message, details) {
|
|
195
|
+
super(message, details);
|
|
196
|
+
this.name = "OAuthError";
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
TokenExpiredError = class extends AuthenticationError {
|
|
200
|
+
constructor(message = "Authentication token has expired") {
|
|
201
|
+
super(message);
|
|
202
|
+
this.name = "TokenExpiredError";
|
|
203
|
+
this.code = "TOKEN_EXPIRED";
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// src/utils/config-loader.ts
|
|
210
|
+
import { promises as fs } from "fs";
|
|
211
|
+
import path2 from "path";
|
|
212
|
+
async function findProjectConfig() {
|
|
213
|
+
const cwd = process.cwd();
|
|
214
|
+
if (configCache.has(cwd)) {
|
|
215
|
+
return configCache.get(cwd) || null;
|
|
216
|
+
}
|
|
217
|
+
for (const filename of CONFIG_FILES) {
|
|
218
|
+
const configPath = path2.join(cwd, filename);
|
|
219
|
+
try {
|
|
220
|
+
await fs.access(configPath);
|
|
221
|
+
const config2 = await loadAndValidateConfig(configPath);
|
|
222
|
+
configCache.set(cwd, config2);
|
|
223
|
+
return config2;
|
|
224
|
+
} catch {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
configCache.set(cwd, null);
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
async function loadAndValidateConfig(configPath) {
|
|
232
|
+
try {
|
|
233
|
+
const content = await fs.readFile(configPath, "utf-8");
|
|
234
|
+
const config2 = JSON.parse(content);
|
|
235
|
+
validateProjectConfig(config2);
|
|
236
|
+
return config2;
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (error instanceof SyntaxError) {
|
|
239
|
+
throw new ValidationError(`Invalid JSON in config file: ${configPath}`, {
|
|
240
|
+
originalError: error.message
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function validateProjectConfig(config2) {
|
|
247
|
+
if (typeof config2 !== "object" || config2 === null) {
|
|
248
|
+
throw new ValidationError("Config must be a JSON object");
|
|
249
|
+
}
|
|
250
|
+
const cfg = config2;
|
|
251
|
+
if (cfg.defaultCommitDays !== void 0) {
|
|
252
|
+
if (typeof cfg.defaultCommitDays !== "number") {
|
|
253
|
+
throw new ValidationError("defaultCommitDays must be a number");
|
|
254
|
+
}
|
|
255
|
+
if (cfg.defaultCommitDays < 1 || cfg.defaultCommitDays > 365) {
|
|
256
|
+
throw new ValidationError("defaultCommitDays must be between 1 and 365");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (cfg.autoVersionCheck !== void 0) {
|
|
260
|
+
if (typeof cfg.autoVersionCheck !== "boolean") {
|
|
261
|
+
throw new ValidationError("autoVersionCheck must be a boolean");
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (cfg.defaultSource !== void 0) {
|
|
265
|
+
const validSources = ["github", "gitlab", "bitbucket", "jira", "confluence"];
|
|
266
|
+
if (!validSources.includes(cfg.defaultSource)) {
|
|
267
|
+
throw new ValidationError(
|
|
268
|
+
`Invalid defaultSource: ${cfg.defaultSource}. Must be one of: ${validSources.join(", ")}`
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (cfg.sourcePriority !== void 0) {
|
|
273
|
+
if (!Array.isArray(cfg.sourcePriority)) {
|
|
274
|
+
throw new ValidationError("sourcePriority must be an array");
|
|
275
|
+
}
|
|
276
|
+
const validSources = ["github", "gitlab", "bitbucket", "jira", "confluence"];
|
|
277
|
+
for (const source of cfg.sourcePriority) {
|
|
278
|
+
if (!validSources.includes(source)) {
|
|
279
|
+
throw new ValidationError(
|
|
280
|
+
`Invalid source in sourcePriority: ${source}. Must be one of: ${validSources.join(", ")}`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const instanceFields = ["jiraInstance", "confluenceInstance", "gitlabInstance"];
|
|
286
|
+
for (const field of instanceFields) {
|
|
287
|
+
if (cfg[field] !== void 0) {
|
|
288
|
+
if (typeof cfg[field] !== "string") {
|
|
289
|
+
throw new ValidationError(`${field} must be a string`);
|
|
290
|
+
}
|
|
291
|
+
const value = cfg[field];
|
|
292
|
+
if (!value.match(/^[a-zA-Z0-9.-]+(:[0-9]+)?(\/.*)?$/)) {
|
|
293
|
+
throw new ValidationError(`Invalid ${field}: ${value}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const booleanFields = ["requireAuthentication", "skipSourceDetection"];
|
|
298
|
+
for (const field of booleanFields) {
|
|
299
|
+
if (cfg[field] !== void 0 && typeof cfg[field] !== "boolean") {
|
|
300
|
+
throw new ValidationError(`${field} must be a boolean`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
var configCache;
|
|
305
|
+
var init_config_loader = __esm({
|
|
306
|
+
"src/utils/config-loader.ts"() {
|
|
307
|
+
"use strict";
|
|
308
|
+
init_esm_shims();
|
|
309
|
+
init_constants();
|
|
310
|
+
init_errors();
|
|
311
|
+
configCache = /* @__PURE__ */ new Map();
|
|
91
312
|
}
|
|
92
313
|
});
|
|
93
314
|
|
|
@@ -103,6 +324,8 @@ var init_storage_service = __esm({
|
|
|
103
324
|
"use strict";
|
|
104
325
|
init_esm_shims();
|
|
105
326
|
init_constants();
|
|
327
|
+
init_env_loader();
|
|
328
|
+
init_config_loader();
|
|
106
329
|
StorageService = class {
|
|
107
330
|
config;
|
|
108
331
|
storageBackend;
|
|
@@ -341,7 +564,27 @@ var init_storage_service = __esm({
|
|
|
341
564
|
this.config.delete("oauthState");
|
|
342
565
|
}
|
|
343
566
|
/**
|
|
344
|
-
* Get configuration value
|
|
567
|
+
* Get configuration value with hierarchy resolution
|
|
568
|
+
* Priority: env vars > project config > user config > defaults
|
|
569
|
+
*/
|
|
570
|
+
async getConfigWithHierarchy(key) {
|
|
571
|
+
const envConfig = loadEnvConfig();
|
|
572
|
+
const envKey = key === "defaultSource" ? "source" : key;
|
|
573
|
+
if (envConfig[envKey] !== void 0) {
|
|
574
|
+
return envConfig[envKey];
|
|
575
|
+
}
|
|
576
|
+
const projectConfig = await findProjectConfig();
|
|
577
|
+
if (projectConfig && projectConfig[key] !== void 0) {
|
|
578
|
+
return projectConfig[key];
|
|
579
|
+
}
|
|
580
|
+
const userValue = this.config.get(key);
|
|
581
|
+
if (userValue !== void 0) {
|
|
582
|
+
return userValue;
|
|
583
|
+
}
|
|
584
|
+
return DEFAULT_CONFIG[key];
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Get configuration value (uses hierarchy resolution)
|
|
345
588
|
*/
|
|
346
589
|
getConfig(key) {
|
|
347
590
|
return this.config.get(key);
|
|
@@ -353,7 +596,32 @@ var init_storage_service = __esm({
|
|
|
353
596
|
this.config.set(key, value);
|
|
354
597
|
}
|
|
355
598
|
/**
|
|
356
|
-
* Get all configuration
|
|
599
|
+
* Get all configuration (merges all layers)
|
|
600
|
+
* Priority: env vars > project config > user config > defaults
|
|
601
|
+
*/
|
|
602
|
+
async getAllConfigWithHierarchy() {
|
|
603
|
+
const envConfig = loadEnvConfig();
|
|
604
|
+
const projectConfig = await findProjectConfig();
|
|
605
|
+
const userConfig = this.config.store;
|
|
606
|
+
return {
|
|
607
|
+
...DEFAULT_CONFIG,
|
|
608
|
+
...userConfig,
|
|
609
|
+
...projectConfig,
|
|
610
|
+
...envConfig.source && { defaultSource: envConfig.source },
|
|
611
|
+
...envConfig.jiraInstance && { jiraInstance: envConfig.jiraInstance },
|
|
612
|
+
...envConfig.confluenceInstance && { confluenceInstance: envConfig.confluenceInstance },
|
|
613
|
+
...envConfig.gitlabInstance && { gitlabInstance: envConfig.gitlabInstance },
|
|
614
|
+
...envConfig.defaultCommitDays !== void 0 && {
|
|
615
|
+
defaultCommitDays: envConfig.defaultCommitDays
|
|
616
|
+
},
|
|
617
|
+
...envConfig.autoVersionCheck !== void 0 && {
|
|
618
|
+
autoVersionCheck: envConfig.autoVersionCheck
|
|
619
|
+
},
|
|
620
|
+
...envConfig.sourcePriority && { sourcePriority: envConfig.sourcePriority }
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Get all configuration (user config only)
|
|
357
625
|
*/
|
|
358
626
|
getAllConfig() {
|
|
359
627
|
return this.config.store;
|
|
@@ -364,7 +632,9 @@ var init_storage_service = __esm({
|
|
|
364
632
|
resetConfig() {
|
|
365
633
|
this.config.clear();
|
|
366
634
|
Object.entries(DEFAULT_CONFIG).forEach(([key, value]) => {
|
|
367
|
-
|
|
635
|
+
if (value !== void 0) {
|
|
636
|
+
this.config.set(key, value);
|
|
637
|
+
}
|
|
368
638
|
});
|
|
369
639
|
}
|
|
370
640
|
/**
|
|
@@ -387,59 +657,6 @@ var init_storage_service = __esm({
|
|
|
387
657
|
}
|
|
388
658
|
});
|
|
389
659
|
|
|
390
|
-
// src/utils/errors.ts
|
|
391
|
-
var BragduckError, AuthenticationError, ApiError, NetworkError, OAuthError, TokenExpiredError;
|
|
392
|
-
var init_errors = __esm({
|
|
393
|
-
"src/utils/errors.ts"() {
|
|
394
|
-
"use strict";
|
|
395
|
-
init_esm_shims();
|
|
396
|
-
BragduckError = class extends Error {
|
|
397
|
-
code;
|
|
398
|
-
details;
|
|
399
|
-
constructor(message, code, details) {
|
|
400
|
-
super(message);
|
|
401
|
-
this.name = "BragduckError";
|
|
402
|
-
this.code = code;
|
|
403
|
-
this.details = details;
|
|
404
|
-
Error.captureStackTrace(this, this.constructor);
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
AuthenticationError = class extends BragduckError {
|
|
408
|
-
constructor(message, details) {
|
|
409
|
-
super(message, "AUTH_ERROR", details);
|
|
410
|
-
this.name = "AuthenticationError";
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
ApiError = class extends BragduckError {
|
|
414
|
-
statusCode;
|
|
415
|
-
constructor(message, statusCode, details) {
|
|
416
|
-
super(message, "API_ERROR", details);
|
|
417
|
-
this.name = "ApiError";
|
|
418
|
-
this.statusCode = statusCode;
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
NetworkError = class extends BragduckError {
|
|
422
|
-
constructor(message, details) {
|
|
423
|
-
super(message, "NETWORK_ERROR", details);
|
|
424
|
-
this.name = "NetworkError";
|
|
425
|
-
}
|
|
426
|
-
};
|
|
427
|
-
OAuthError = class extends AuthenticationError {
|
|
428
|
-
constructor(message, details) {
|
|
429
|
-
super(message, details);
|
|
430
|
-
this.name = "OAuthError";
|
|
431
|
-
}
|
|
432
|
-
};
|
|
433
|
-
TokenExpiredError = class extends AuthenticationError {
|
|
434
|
-
constructor(message = "Authentication token has expired") {
|
|
435
|
-
super(message);
|
|
436
|
-
this.name = "TokenExpiredError";
|
|
437
|
-
this.code = "TOKEN_EXPIRED";
|
|
438
|
-
}
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
|
|
443
660
|
// src/utils/logger.ts
|
|
444
661
|
import chalk from "chalk";
|
|
445
662
|
var logger;
|