@bragduck/cli 2.7.0 → 2.8.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/dist/bin/bragduck.js +513 -138
- package/dist/bin/bragduck.js.map +1 -1
- package/dist/index.js +277 -67
- 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;
|
|
@@ -216,17 +439,10 @@ var init_storage_service = __esm({
|
|
|
216
439
|
}
|
|
217
440
|
}
|
|
218
441
|
/**
|
|
219
|
-
* Check if user is authenticated
|
|
442
|
+
* Check if user is authenticated (checks bragduck service)
|
|
220
443
|
*/
|
|
221
444
|
async isAuthenticated() {
|
|
222
|
-
|
|
223
|
-
if (!credentials || !credentials.accessToken) {
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
if (credentials.expiresAt && credentials.expiresAt < Date.now()) {
|
|
227
|
-
return false;
|
|
228
|
-
}
|
|
229
|
-
return true;
|
|
445
|
+
return this.isServiceAuthenticated("bragduck");
|
|
230
446
|
}
|
|
231
447
|
/**
|
|
232
448
|
* Get credentials for a specific service
|
|
@@ -341,7 +557,27 @@ var init_storage_service = __esm({
|
|
|
341
557
|
this.config.delete("oauthState");
|
|
342
558
|
}
|
|
343
559
|
/**
|
|
344
|
-
* Get configuration value
|
|
560
|
+
* Get configuration value with hierarchy resolution
|
|
561
|
+
* Priority: env vars > project config > user config > defaults
|
|
562
|
+
*/
|
|
563
|
+
async getConfigWithHierarchy(key) {
|
|
564
|
+
const envConfig = loadEnvConfig();
|
|
565
|
+
const envKey = key === "defaultSource" ? "source" : key;
|
|
566
|
+
if (envConfig[envKey] !== void 0) {
|
|
567
|
+
return envConfig[envKey];
|
|
568
|
+
}
|
|
569
|
+
const projectConfig = await findProjectConfig();
|
|
570
|
+
if (projectConfig && projectConfig[key] !== void 0) {
|
|
571
|
+
return projectConfig[key];
|
|
572
|
+
}
|
|
573
|
+
const userValue = this.config.get(key);
|
|
574
|
+
if (userValue !== void 0) {
|
|
575
|
+
return userValue;
|
|
576
|
+
}
|
|
577
|
+
return DEFAULT_CONFIG[key];
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Get configuration value (uses hierarchy resolution)
|
|
345
581
|
*/
|
|
346
582
|
getConfig(key) {
|
|
347
583
|
return this.config.get(key);
|
|
@@ -353,7 +589,32 @@ var init_storage_service = __esm({
|
|
|
353
589
|
this.config.set(key, value);
|
|
354
590
|
}
|
|
355
591
|
/**
|
|
356
|
-
* Get all configuration
|
|
592
|
+
* Get all configuration (merges all layers)
|
|
593
|
+
* Priority: env vars > project config > user config > defaults
|
|
594
|
+
*/
|
|
595
|
+
async getAllConfigWithHierarchy() {
|
|
596
|
+
const envConfig = loadEnvConfig();
|
|
597
|
+
const projectConfig = await findProjectConfig();
|
|
598
|
+
const userConfig = this.config.store;
|
|
599
|
+
return {
|
|
600
|
+
...DEFAULT_CONFIG,
|
|
601
|
+
...userConfig,
|
|
602
|
+
...projectConfig,
|
|
603
|
+
...envConfig.source && { defaultSource: envConfig.source },
|
|
604
|
+
...envConfig.jiraInstance && { jiraInstance: envConfig.jiraInstance },
|
|
605
|
+
...envConfig.confluenceInstance && { confluenceInstance: envConfig.confluenceInstance },
|
|
606
|
+
...envConfig.gitlabInstance && { gitlabInstance: envConfig.gitlabInstance },
|
|
607
|
+
...envConfig.defaultCommitDays !== void 0 && {
|
|
608
|
+
defaultCommitDays: envConfig.defaultCommitDays
|
|
609
|
+
},
|
|
610
|
+
...envConfig.autoVersionCheck !== void 0 && {
|
|
611
|
+
autoVersionCheck: envConfig.autoVersionCheck
|
|
612
|
+
},
|
|
613
|
+
...envConfig.sourcePriority && { sourcePriority: envConfig.sourcePriority }
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Get all configuration (user config only)
|
|
357
618
|
*/
|
|
358
619
|
getAllConfig() {
|
|
359
620
|
return this.config.store;
|
|
@@ -364,7 +625,9 @@ var init_storage_service = __esm({
|
|
|
364
625
|
resetConfig() {
|
|
365
626
|
this.config.clear();
|
|
366
627
|
Object.entries(DEFAULT_CONFIG).forEach(([key, value]) => {
|
|
367
|
-
|
|
628
|
+
if (value !== void 0) {
|
|
629
|
+
this.config.set(key, value);
|
|
630
|
+
}
|
|
368
631
|
});
|
|
369
632
|
}
|
|
370
633
|
/**
|
|
@@ -387,59 +650,6 @@ var init_storage_service = __esm({
|
|
|
387
650
|
}
|
|
388
651
|
});
|
|
389
652
|
|
|
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
653
|
// src/utils/logger.ts
|
|
444
654
|
import chalk from "chalk";
|
|
445
655
|
var logger;
|