@bragduck/cli 2.0.2 → 2.0.3
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 +500 -215
- package/dist/bin/bragduck.js.map +1 -1
- package/dist/index.js +36 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -308,11 +308,13 @@ var init_errors = __esm({
|
|
|
308
308
|
"use strict";
|
|
309
309
|
init_esm_shims();
|
|
310
310
|
BragduckError = class extends Error {
|
|
311
|
+
code;
|
|
312
|
+
details;
|
|
311
313
|
constructor(message, code, details) {
|
|
312
314
|
super(message);
|
|
315
|
+
this.name = "BragduckError";
|
|
313
316
|
this.code = code;
|
|
314
317
|
this.details = details;
|
|
315
|
-
this.name = "BragduckError";
|
|
316
318
|
Error.captureStackTrace(this, this.constructor);
|
|
317
319
|
}
|
|
318
320
|
};
|
|
@@ -323,10 +325,11 @@ var init_errors = __esm({
|
|
|
323
325
|
}
|
|
324
326
|
};
|
|
325
327
|
ApiError = class extends BragduckError {
|
|
328
|
+
statusCode;
|
|
326
329
|
constructor(message, statusCode, details) {
|
|
327
330
|
super(message, "API_ERROR", details);
|
|
328
|
-
this.statusCode = statusCode;
|
|
329
331
|
this.name = "ApiError";
|
|
332
|
+
this.statusCode = statusCode;
|
|
330
333
|
}
|
|
331
334
|
};
|
|
332
335
|
NetworkError = class extends BragduckError {
|
|
@@ -417,7 +420,7 @@ async function findAvailablePort() {
|
|
|
417
420
|
testServer.listen(port, "127.0.0.1");
|
|
418
421
|
});
|
|
419
422
|
return port;
|
|
420
|
-
} catch
|
|
423
|
+
} catch {
|
|
421
424
|
continue;
|
|
422
425
|
}
|
|
423
426
|
}
|
|
@@ -428,10 +431,10 @@ async function startOAuthCallbackServer(expectedState) {
|
|
|
428
431
|
const timeout = OAUTH_CONFIG.TIMEOUT_MS;
|
|
429
432
|
return new Promise((resolve, reject) => {
|
|
430
433
|
let server = null;
|
|
431
|
-
let timeoutId;
|
|
434
|
+
let timeoutId = null;
|
|
432
435
|
const cleanup = () => {
|
|
433
436
|
if (timeoutId) {
|
|
434
|
-
clearTimeout(timeoutId);
|
|
437
|
+
globalThis.clearTimeout(timeoutId);
|
|
435
438
|
}
|
|
436
439
|
if (server) {
|
|
437
440
|
if (typeof server.closeAllConnections === "function") {
|
|
@@ -477,7 +480,7 @@ async function startOAuthCallbackServer(expectedState) {
|
|
|
477
480
|
}
|
|
478
481
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
479
482
|
res.end(SUCCESS_HTML);
|
|
480
|
-
setTimeout(() => {
|
|
483
|
+
globalThis.setTimeout(() => {
|
|
481
484
|
cleanup();
|
|
482
485
|
resolve({
|
|
483
486
|
code: String(code),
|
|
@@ -499,7 +502,7 @@ async function startOAuthCallbackServer(expectedState) {
|
|
|
499
502
|
server.listen(port, "127.0.0.1", () => {
|
|
500
503
|
logger.debug(`OAuth callback server listening on http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`);
|
|
501
504
|
});
|
|
502
|
-
timeoutId = setTimeout(() => {
|
|
505
|
+
timeoutId = globalThis.setTimeout(() => {
|
|
503
506
|
logger.debug("OAuth callback timeout");
|
|
504
507
|
cleanup();
|
|
505
508
|
reject(new OAuthError("Authentication timeout - no callback received within 2 minutes"));
|
|
@@ -677,7 +680,7 @@ var init_browser = __esm({
|
|
|
677
680
|
// src/services/auth.service.ts
|
|
678
681
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
679
682
|
import { readFileSync as readFileSync2 } from "fs";
|
|
680
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
683
|
+
import { fileURLToPath as fileURLToPath3, URLSearchParams } from "url";
|
|
681
684
|
import { dirname as dirname2, join as join3 } from "path";
|
|
682
685
|
import { ofetch } from "ofetch";
|
|
683
686
|
function getUserAgent() {
|
|
@@ -688,7 +691,7 @@ function getUserAgent() {
|
|
|
688
691
|
const platform = process.platform;
|
|
689
692
|
const arch = process.arch;
|
|
690
693
|
return `BragDuck-CLI/${version2} (${platform}-${arch})`;
|
|
691
|
-
} catch
|
|
694
|
+
} catch {
|
|
692
695
|
logger.debug("Failed to read package.json version");
|
|
693
696
|
return "BragDuck-CLI/2.0.0";
|
|
694
697
|
}
|
|
@@ -786,7 +789,7 @@ var init_auth_service = __esm({
|
|
|
786
789
|
const serverPromise = startOAuthCallbackServer(state);
|
|
787
790
|
try {
|
|
788
791
|
await openBrowser(authUrl);
|
|
789
|
-
} catch
|
|
792
|
+
} catch {
|
|
790
793
|
logger.warning("Could not open browser automatically");
|
|
791
794
|
logger.info(`Please open this URL in your browser:`);
|
|
792
795
|
logger.log(authUrl);
|
|
@@ -890,13 +893,14 @@ var init_auth_service = __esm({
|
|
|
890
893
|
import { ofetch as ofetch2 } from "ofetch";
|
|
891
894
|
import { readFileSync as readFileSync3 } from "fs";
|
|
892
895
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
896
|
+
import { URLSearchParams as URLSearchParams2 } from "url";
|
|
893
897
|
import { dirname as dirname3, join as join4 } from "path";
|
|
894
898
|
function getCliVersion() {
|
|
895
899
|
try {
|
|
896
900
|
const packageJsonPath = join4(__dirname4, "../../package.json");
|
|
897
901
|
const packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
|
|
898
902
|
return packageJson.version;
|
|
899
|
-
} catch
|
|
903
|
+
} catch {
|
|
900
904
|
logger.debug("Failed to read package.json version");
|
|
901
905
|
return "2.0.0";
|
|
902
906
|
}
|
|
@@ -926,29 +930,23 @@ var init_api_service = __esm({
|
|
|
926
930
|
baseURL: this.baseURL,
|
|
927
931
|
// Request interceptor
|
|
928
932
|
onRequest: async ({ options }) => {
|
|
929
|
-
|
|
933
|
+
const extendedOptions = options;
|
|
934
|
+
logger.debug(`API Request: ${options.method} ${extendedOptions.baseURL}${extendedOptions.url}`);
|
|
930
935
|
const cliVersion = getCliVersion();
|
|
931
936
|
const platform = getPlatformInfo();
|
|
932
937
|
const userAgent = `BragDuck-CLI/${cliVersion} (${platform})`;
|
|
933
938
|
const token = await authService.getAccessToken();
|
|
939
|
+
const headers = {
|
|
940
|
+
...options.headers,
|
|
941
|
+
"User-Agent": userAgent
|
|
942
|
+
};
|
|
934
943
|
if (token) {
|
|
935
|
-
|
|
936
|
-
...options.headers,
|
|
937
|
-
"User-Agent": userAgent,
|
|
938
|
-
Authorization: `Bearer ${token}`
|
|
939
|
-
};
|
|
940
|
-
} else {
|
|
941
|
-
options.headers = {
|
|
942
|
-
...options.headers,
|
|
943
|
-
"User-Agent": userAgent
|
|
944
|
-
};
|
|
944
|
+
headers.Authorization = `Bearer ${token}`;
|
|
945
945
|
}
|
|
946
946
|
if (options.method && ["POST", "PUT", "PATCH"].includes(options.method)) {
|
|
947
|
-
|
|
948
|
-
...options.headers,
|
|
949
|
-
"Content-Type": "application/json"
|
|
950
|
-
};
|
|
947
|
+
headers["Content-Type"] = "application/json";
|
|
951
948
|
}
|
|
949
|
+
options.headers = headers;
|
|
952
950
|
},
|
|
953
951
|
// Response interceptor for success
|
|
954
952
|
onResponse: ({ response }) => {
|
|
@@ -957,7 +955,8 @@ var init_api_service = __esm({
|
|
|
957
955
|
// Response interceptor for errors
|
|
958
956
|
onResponseError: async ({ response, options }) => {
|
|
959
957
|
const status = response.status;
|
|
960
|
-
const
|
|
958
|
+
const extendedOptions = options;
|
|
959
|
+
const url = `${extendedOptions.baseURL}${extendedOptions.url}`;
|
|
961
960
|
logger.debug(`API Error: ${status} ${response.statusText} - ${url}`);
|
|
962
961
|
if (status === HTTP_STATUS.UNAUTHORIZED) {
|
|
963
962
|
logger.debug("Token expired, attempting refresh");
|
|
@@ -1029,9 +1028,9 @@ var init_api_service = __esm({
|
|
|
1029
1028
|
);
|
|
1030
1029
|
logger.debug(`Successfully refined ${response.refined_commits.length} commits`);
|
|
1031
1030
|
return response;
|
|
1032
|
-
} catch (
|
|
1031
|
+
} catch (_error) {
|
|
1033
1032
|
logger.debug("Failed to refine commits");
|
|
1034
|
-
throw
|
|
1033
|
+
throw _error;
|
|
1035
1034
|
}
|
|
1036
1035
|
}
|
|
1037
1036
|
/**
|
|
@@ -1049,9 +1048,9 @@ var init_api_service = __esm({
|
|
|
1049
1048
|
);
|
|
1050
1049
|
logger.debug(`Successfully created ${response.created} brags`);
|
|
1051
1050
|
return response;
|
|
1052
|
-
} catch (
|
|
1051
|
+
} catch (_error) {
|
|
1053
1052
|
logger.debug("Failed to create brags");
|
|
1054
|
-
throw
|
|
1053
|
+
throw _error;
|
|
1055
1054
|
}
|
|
1056
1055
|
}
|
|
1057
1056
|
/**
|
|
@@ -1061,7 +1060,7 @@ var init_api_service = __esm({
|
|
|
1061
1060
|
const { limit = 50, offset = 0, tags, search } = params;
|
|
1062
1061
|
logger.debug(`Listing brags: limit=${limit}, offset=${offset}`);
|
|
1063
1062
|
try {
|
|
1064
|
-
const queryParams = new
|
|
1063
|
+
const queryParams = new URLSearchParams2({
|
|
1065
1064
|
limit: limit.toString(),
|
|
1066
1065
|
offset: offset.toString()
|
|
1067
1066
|
});
|
|
@@ -1077,9 +1076,9 @@ var init_api_service = __esm({
|
|
|
1077
1076
|
});
|
|
1078
1077
|
logger.debug(`Successfully fetched ${response.brags.length} brags (total: ${response.total})`);
|
|
1079
1078
|
return response;
|
|
1080
|
-
} catch (
|
|
1079
|
+
} catch (_error) {
|
|
1081
1080
|
logger.debug("Failed to list brags");
|
|
1082
|
-
throw
|
|
1081
|
+
throw _error;
|
|
1083
1082
|
}
|
|
1084
1083
|
}
|
|
1085
1084
|
/**
|
|
@@ -1096,7 +1095,7 @@ var init_api_service = __esm({
|
|
|
1096
1095
|
);
|
|
1097
1096
|
logger.debug(`Latest version: ${response.latest_version}`);
|
|
1098
1097
|
return response;
|
|
1099
|
-
} catch
|
|
1098
|
+
} catch {
|
|
1100
1099
|
logger.debug("Failed to check version");
|
|
1101
1100
|
const { version: version2 } = await Promise.resolve().then(() => (init_version(), version_exports));
|
|
1102
1101
|
return {
|
|
@@ -1112,7 +1111,7 @@ var init_api_service = __esm({
|
|
|
1112
1111
|
try {
|
|
1113
1112
|
await this.checkVersion();
|
|
1114
1113
|
return true;
|
|
1115
|
-
} catch
|
|
1114
|
+
} catch {
|
|
1116
1115
|
return false;
|
|
1117
1116
|
}
|
|
1118
1117
|
}
|
|
@@ -1155,7 +1154,7 @@ function getCurrentVersion() {
|
|
|
1155
1154
|
const packageJsonPath = join5(__dirname5, "../../package.json");
|
|
1156
1155
|
const packageJson = JSON.parse(readFileSync4(packageJsonPath, "utf-8"));
|
|
1157
1156
|
return packageJson.version;
|
|
1158
|
-
} catch
|
|
1157
|
+
} catch {
|
|
1159
1158
|
logger.debug("Failed to read package.json version");
|
|
1160
1159
|
return "1.0.0";
|
|
1161
1160
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/constants.ts","../src/services/storage.service.ts","../src/utils/errors.ts","../src/utils/logger.ts","../src/utils/oauth-server.ts","../src/utils/browser.ts","../src/services/auth.service.ts","../src/services/api.service.ts","../src/utils/version.ts","../src/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","// Load environment variables\nimport { config } from 'dotenv';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\n\n// Get the directory of this file\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Load .env from the project root\n// In production, this file is bundled into dist/bin/bragduck.js, so we need to go up 2 levels\n// In development (src/), we'd need to go up 1 level, but the build is what matters\nconfig({ path: join(__dirname, '..', '..', '.env') });\n\n// App-wide constants for Bragduck CLI\n\n/**\n * Application name used for storage and configuration\n */\nexport const APP_NAME = 'bragduck';\n\n/**\n * Storage keys for credentials and configuration\n */\nexport const STORAGE_KEYS = {\n ACCESS_TOKEN: 'access_token',\n REFRESH_TOKEN: 'refresh_token',\n USER_INFO: 'user_info',\n OAUTH_STATE: 'oauth_state',\n} as const;\n\n/**\n * Configuration keys\n */\nexport const CONFIG_KEYS = {\n DEFAULT_COMMIT_DAYS: 'defaultCommitDays',\n AUTO_VERSION_CHECK: 'autoVersionCheck',\n} as const;\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG = {\n defaultCommitDays: 30,\n autoVersionCheck: true,\n} as const;\n\n/**\n * OAuth configuration\n */\nexport const OAUTH_CONFIG = {\n CLIENT_ID: 'bragduck-cli',\n CALLBACK_PATH: '/callback',\n TIMEOUT_MS: 120000, // 2 minutes\n MIN_PORT: 8000,\n MAX_PORT: 9000,\n} as const;\n\n/**\n * API endpoints\n */\nexport const API_ENDPOINTS = {\n AUTH: {\n INITIATE: '/v1/auth/cli/initiate',\n TOKEN: '/v1/auth/cli/token',\n },\n COMMITS: {\n REFINE: '/v1/commits/refine',\n },\n BRAGS: {\n CREATE: '/v1/brags',\n LIST: '/v1/brags',\n },\n VERSION: '/v1/cli/version',\n} as const;\n\n/**\n * Encryption configuration for file-based credential storage\n */\nexport const ENCRYPTION_CONFIG = {\n ALGORITHM: 'aes-256-gcm',\n KEY_LENGTH: 32,\n IV_LENGTH: 16,\n AUTH_TAG_LENGTH: 16,\n SALT_LENGTH: 32,\n} as const;\n\n/**\n * File paths for credential storage fallback\n */\nexport const STORAGE_PATHS = {\n CREDENTIALS_DIR: '.bragduck',\n CREDENTIALS_FILE: 'credentials.enc',\n CONFIG_FILE: 'config.json',\n} as const;\n\n/**\n * Error codes\n */\nexport const ERROR_CODES = {\n AUTH_FAILED: 'AUTH_FAILED',\n TOKEN_EXPIRED: 'TOKEN_EXPIRED',\n NETWORK_ERROR: 'NETWORK_ERROR',\n GIT_ERROR: 'GIT_ERROR',\n API_ERROR: 'API_ERROR',\n STORAGE_ERROR: 'STORAGE_ERROR',\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n} as const;\n\n/**\n * HTTP status codes\n */\nexport const HTTP_STATUS = {\n OK: 200,\n CREATED: 201,\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n INTERNAL_SERVER_ERROR: 500,\n} as const;\n\n/**\n * GitHub configuration\n */\nexport const GITHUB_CONFIG = {\n MIN_GH_VERSION: '2.0.0',\n PR_SEARCH_FIELDS:\n 'number,title,body,author,mergedAt,additions,deletions,changedFiles,url,labels',\n MAX_BODY_LENGTH: 5000,\n} as const;\n","import Conf from 'conf';\nimport { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { APP_NAME, ENCRYPTION_CONFIG, STORAGE_PATHS, DEFAULT_CONFIG } from '../constants.js';\nimport type {\n StoredCredentials,\n UserInfo,\n OAuthState,\n StorageBackend,\n EncryptedData,\n BragduckConfig,\n} from '../types/config.types.js';\n\n/**\n * Storage service for managing credentials and configuration\n * Uses encrypted file storage for credentials\n *\n * NOTE: OS keychain support (via cross-keychain or similar) can be added in the future.\n * For now, we use secure encrypted file storage with machine-specific keys.\n */\nexport class StorageService {\n private config: Conf<BragduckConfig>;\n private storageBackend: StorageBackend;\n private credentialsDir: string;\n private credentialsFilePath: string;\n\n constructor() {\n // Initialize config management\n this.config = new Conf<BragduckConfig>({\n projectName: APP_NAME,\n defaults: DEFAULT_CONFIG,\n });\n\n // Set up credentials directory and file path\n this.credentialsDir = join(homedir(), STORAGE_PATHS.CREDENTIALS_DIR);\n this.credentialsFilePath = join(this.credentialsDir, STORAGE_PATHS.CREDENTIALS_FILE);\n\n // Use file storage for now (keychain support can be added later)\n this.storageBackend = 'file';\n this.ensureCredentialsDir();\n }\n\n /**\n * Ensure credentials directory exists\n */\n private ensureCredentialsDir(): void {\n if (!existsSync(this.credentialsDir)) {\n mkdirSync(this.credentialsDir, { recursive: true, mode: 0o700 });\n }\n }\n\n /**\n * Encrypt data for file storage\n */\n private encrypt(data: string, key: Buffer): EncryptedData {\n const iv = randomBytes(ENCRYPTION_CONFIG.IV_LENGTH);\n const cipher = createCipheriv(ENCRYPTION_CONFIG.ALGORITHM, key, iv, {\n authTagLength: ENCRYPTION_CONFIG.AUTH_TAG_LENGTH,\n });\n\n let encrypted = cipher.update(data, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n\n const authTag = cipher.getAuthTag();\n\n return {\n encrypted,\n iv: iv.toString('hex'),\n authTag: authTag.toString('hex'),\n salt: '', // Salt is stored separately\n };\n }\n\n /**\n * Decrypt data from file storage\n */\n private decrypt(encryptedData: EncryptedData, key: Buffer): string {\n const decipher = createDecipheriv(\n ENCRYPTION_CONFIG.ALGORITHM,\n key,\n Buffer.from(encryptedData.iv, 'hex'),\n {\n authTagLength: ENCRYPTION_CONFIG.AUTH_TAG_LENGTH,\n }\n );\n\n decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));\n\n let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');\n decrypted += decipher.final('utf8');\n\n return decrypted;\n }\n\n /**\n * Derive encryption key from machine-specific data\n */\n private deriveEncryptionKey(salt: Buffer): Buffer {\n // Use machine ID and app name as password\n const password = `${APP_NAME}-${homedir()}-${process.platform}`;\n return scryptSync(password, salt, ENCRYPTION_CONFIG.KEY_LENGTH);\n }\n\n /**\n * Store credentials using encrypted file storage\n */\n async setCredentials(credentials: StoredCredentials): Promise<void> {\n const data = JSON.stringify(credentials);\n\n // Encrypt and store credentials\n const salt = randomBytes(ENCRYPTION_CONFIG.SALT_LENGTH);\n const key = this.deriveEncryptionKey(salt);\n const encrypted = this.encrypt(data, key);\n encrypted.salt = salt.toString('hex');\n\n writeFileSync(this.credentialsFilePath, JSON.stringify(encrypted), {\n mode: 0o600,\n encoding: 'utf8',\n });\n }\n\n /**\n * Retrieve credentials from encrypted file storage\n */\n async getCredentials(): Promise<StoredCredentials | null> {\n if (!existsSync(this.credentialsFilePath)) {\n return null;\n }\n\n try {\n const encryptedData: EncryptedData = JSON.parse(\n readFileSync(this.credentialsFilePath, 'utf8')\n );\n const salt = Buffer.from(encryptedData.salt, 'hex');\n const key = this.deriveEncryptionKey(salt);\n const decrypted = this.decrypt(encryptedData, key);\n return JSON.parse(decrypted);\n } catch (error) {\n console.error('Failed to decrypt credentials:', error);\n return null;\n }\n }\n\n /**\n * Delete credentials from file storage\n */\n async deleteCredentials(): Promise<void> {\n // Delete file if it exists\n if (existsSync(this.credentialsFilePath)) {\n try {\n unlinkSync(this.credentialsFilePath);\n } catch (error) {\n console.error('Failed to delete credentials file:', error);\n }\n }\n }\n\n /**\n * Check if user is authenticated\n */\n async isAuthenticated(): Promise<boolean> {\n const credentials = await this.getCredentials();\n if (!credentials || !credentials.accessToken) {\n return false;\n }\n\n // Check if token is expired\n if (credentials.expiresAt && credentials.expiresAt < Date.now()) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Store user information\n */\n setUserInfo(userInfo: UserInfo): void {\n this.config.set('userInfo' as keyof BragduckConfig, userInfo as any);\n }\n\n /**\n * Get user information\n */\n getUserInfo(): UserInfo | null {\n return (this.config.get('userInfo' as keyof BragduckConfig) as any) || null;\n }\n\n /**\n * Delete user information\n */\n deleteUserInfo(): void {\n this.config.delete('userInfo' as keyof BragduckConfig);\n }\n\n /**\n * Store OAuth state for CSRF protection\n */\n setOAuthState(state: OAuthState): void {\n this.config.set('oauthState' as keyof BragduckConfig, state as any);\n }\n\n /**\n * Get OAuth state\n */\n getOAuthState(): OAuthState | null {\n return (this.config.get('oauthState' as keyof BragduckConfig) as any) || null;\n }\n\n /**\n * Delete OAuth state\n */\n deleteOAuthState(): void {\n this.config.delete('oauthState' as keyof BragduckConfig);\n }\n\n /**\n * Get configuration value\n */\n getConfig<K extends keyof BragduckConfig>(key: K): BragduckConfig[K] {\n return this.config.get(key);\n }\n\n /**\n * Set configuration value\n */\n setConfig<K extends keyof BragduckConfig>(key: K, value: BragduckConfig[K]): void {\n this.config.set(key, value);\n }\n\n /**\n * Get all configuration\n */\n getAllConfig(): BragduckConfig {\n return this.config.store;\n }\n\n /**\n * Reset configuration to defaults\n */\n resetConfig(): void {\n this.config.clear();\n // Re-apply defaults\n Object.entries(DEFAULT_CONFIG).forEach(([key, value]) => {\n this.config.set(key as keyof BragduckConfig, value as any);\n });\n }\n\n /**\n * Get current storage backend\n */\n getStorageBackend(): StorageBackend {\n return this.storageBackend;\n }\n\n /**\n * Clear all stored data (credentials + config)\n */\n async clearAll(): Promise<void> {\n await this.deleteCredentials();\n this.deleteUserInfo();\n this.deleteOAuthState();\n this.resetConfig();\n }\n}\n\n// Export singleton instance\nexport const storageService = new StorageService();\n","// Custom error classes for Bragduck CLI\n\n/**\n * Base error class for all Bragduck errors\n */\nexport class BragduckError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: Record<string, any>\n ) {\n super(message);\n this.name = 'BragduckError';\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Authentication-related errors\n */\nexport class AuthenticationError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'AUTH_ERROR', details);\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Git operation errors\n */\nexport class GitError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'GIT_ERROR', details);\n this.name = 'GitError';\n }\n}\n\n/**\n * API communication errors\n */\nexport class ApiError extends BragduckError {\n constructor(\n message: string,\n public statusCode?: number,\n details?: Record<string, any>\n ) {\n super(message, 'API_ERROR', details);\n this.name = 'ApiError';\n }\n}\n\n/**\n * Network-related errors\n */\nexport class NetworkError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'NETWORK_ERROR', details);\n this.name = 'NetworkError';\n }\n}\n\n/**\n * Storage-related errors\n */\nexport class StorageError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'STORAGE_ERROR', details);\n this.name = 'StorageError';\n }\n}\n\n/**\n * Validation errors\n */\nexport class ValidationError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'VALIDATION_ERROR', details);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * OAuth-specific errors\n */\nexport class OAuthError extends AuthenticationError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, details);\n this.name = 'OAuthError';\n }\n}\n\n/**\n * Token expiration error\n */\nexport class TokenExpiredError extends AuthenticationError {\n constructor(message = 'Authentication token has expired') {\n super(message);\n this.name = 'TokenExpiredError';\n this.code = 'TOKEN_EXPIRED';\n }\n}\n\n/**\n * GitHub-related errors\n */\nexport class GitHubError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'GITHUB_ERROR', details);\n this.name = 'GitHubError';\n }\n}\n","import chalk from 'chalk';\n\n/**\n * Logger utility for consistent console output\n */\nexport const logger = {\n /**\n * Debug message (only shown when DEBUG env var is set)\n */\n debug: (message: string, ...args: any[]): void => {\n if (process.env.DEBUG) {\n console.log(chalk.gray(`[DEBUG] ${message}`), ...args);\n }\n },\n\n /**\n * Info message\n */\n info: (message: string): void => {\n console.log(chalk.blue(`ℹ ${message}`));\n },\n\n /**\n * Success message\n */\n success: (message: string): void => {\n console.log(chalk.green(`✓ ${message}`));\n },\n\n /**\n * Warning message\n */\n warning: (message: string): void => {\n console.warn(chalk.yellow(`⚠ ${message}`));\n },\n\n /**\n * Error message\n */\n error: (message: string): void => {\n console.error(chalk.red(`✗ ${message}`));\n },\n\n /**\n * Plain log without formatting\n */\n log: (message: string): void => {\n console.log(message);\n },\n};\n","import { createServer, type Server, type IncomingMessage, type ServerResponse } from 'http';\nimport { parse } from 'url';\nimport { OAUTH_CONFIG } from '../constants.js';\nimport { OAuthError } from './errors.js';\nimport { logger } from './logger.js';\n\n/**\n * OAuth callback result\n */\nexport interface OAuthCallbackResult {\n code: string;\n state: string;\n port: number;\n}\n\n/**\n * Find an available port in the configured range\n */\nasync function findAvailablePort(): Promise<number> {\n const { MIN_PORT, MAX_PORT } = OAUTH_CONFIG;\n\n for (let port = MIN_PORT; port <= MAX_PORT; port++) {\n try {\n await new Promise<void>((resolve, reject) => {\n const testServer = createServer();\n testServer.once('error', reject);\n testServer.once('listening', () => {\n testServer.close(() => resolve());\n });\n testServer.listen(port, '127.0.0.1');\n });\n return port;\n } catch (error) {\n // Port is in use, try next one\n continue;\n }\n }\n\n throw new OAuthError(`No available ports found in range ${MIN_PORT}-${MAX_PORT}`);\n}\n\n/**\n * Success HTML page to show after authentication\n */\nconst SUCCESS_HTML = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Bragduck - Authentication Successful</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n }\n .container {\n text-align: center;\n padding: 2rem;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 1rem;\n backdrop-filter: blur(10px);\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);\n max-width: 500px;\n }\n h1 {\n font-size: 2.5rem;\n margin: 0 0 1rem 0;\n }\n .checkmark {\n font-size: 4rem;\n animation: scale-in 0.3s ease-out;\n }\n p {\n font-size: 1.2rem;\n margin: 1rem 0;\n opacity: 0.9;\n }\n @keyframes scale-in {\n from { transform: scale(0); }\n to { transform: scale(1); }\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"checkmark\">✓</div>\n <h1>Authentication Successful!</h1>\n <p>You can now close this window and return to your terminal.</p>\n </div>\n</body>\n</html>\n`;\n\n/**\n * Error HTML page to show on authentication failure\n */\nconst ERROR_HTML = (error: string) => `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Bragduck - Authentication Failed</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n color: white;\n }\n .container {\n text-align: center;\n padding: 2rem;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 1rem;\n backdrop-filter: blur(10px);\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);\n max-width: 500px;\n }\n h1 {\n font-size: 2.5rem;\n margin: 0 0 1rem 0;\n }\n .error-icon {\n font-size: 4rem;\n }\n p {\n font-size: 1.2rem;\n margin: 1rem 0;\n opacity: 0.9;\n }\n .error-details {\n background: rgba(0, 0, 0, 0.2);\n padding: 1rem;\n border-radius: 0.5rem;\n font-family: monospace;\n font-size: 0.9rem;\n margin-top: 1rem;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"error-icon\">✗</div>\n <h1>Authentication Failed</h1>\n <p>Please return to your terminal and try again.</p>\n <div class=\"error-details\">${error}</div>\n </div>\n</body>\n</html>\n`;\n\n/**\n * Start OAuth callback server and wait for callback\n */\nexport async function startOAuthCallbackServer(expectedState: string): Promise<OAuthCallbackResult> {\n const port = await findAvailablePort();\n const timeout = OAUTH_CONFIG.TIMEOUT_MS;\n\n return new Promise<OAuthCallbackResult>((resolve, reject) => {\n let server: Server | null = null;\n let timeoutId: NodeJS.Timeout;\n\n const cleanup = () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n if (server) {\n // Close all connections immediately (Node.js 18+)\n if (typeof (server as any).closeAllConnections === 'function') {\n (server as any).closeAllConnections();\n }\n server.close(() => {\n logger.debug('OAuth server closed');\n });\n server.unref(); // Allow process to exit even if server is still running\n }\n };\n\n const handleRequest = (req: IncomingMessage, res: ServerResponse) => {\n const parsedUrl = parse(req.url || '', true);\n\n logger.debug(`OAuth callback received: ${req.url}`);\n\n // Handle callback request\n if (parsedUrl.pathname === OAUTH_CONFIG.CALLBACK_PATH) {\n const { code, state, error, error_description } = parsedUrl.query;\n\n // Check for OAuth errors\n if (error) {\n const errorMsg = error_description || error;\n logger.debug(`OAuth error: ${errorMsg}`);\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(ERROR_HTML(String(errorMsg)));\n\n cleanup();\n reject(new OAuthError(`OAuth error: ${errorMsg}`));\n return;\n }\n\n // Validate required parameters\n if (!code || !state) {\n const errorMsg = 'Missing code or state parameter';\n logger.debug(errorMsg);\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(ERROR_HTML(errorMsg));\n\n cleanup();\n reject(new OAuthError(errorMsg));\n return;\n }\n\n // Verify state matches (CSRF protection)\n if (state !== expectedState) {\n const errorMsg = 'Invalid state parameter (possible CSRF attack)';\n logger.debug(errorMsg);\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(ERROR_HTML(errorMsg));\n\n cleanup();\n reject(new OAuthError(errorMsg));\n return;\n }\n\n // Success!\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(SUCCESS_HTML);\n\n // Give the response time to be sent before closing\n setTimeout(() => {\n cleanup();\n resolve({\n code: String(code),\n state: String(state),\n port,\n });\n }, 100);\n return;\n }\n\n // Handle other requests (404)\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not Found');\n };\n\n // Create server\n server = createServer(handleRequest);\n\n // Handle server errors\n server.on('error', (error) => {\n logger.debug(`OAuth server error: ${error.message}`);\n cleanup();\n reject(new OAuthError(`OAuth server error: ${error.message}`));\n });\n\n // Start server\n server.listen(port, '127.0.0.1', () => {\n logger.debug(`OAuth callback server listening on http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`);\n });\n\n // Set timeout\n timeoutId = setTimeout(() => {\n logger.debug('OAuth callback timeout');\n cleanup();\n reject(new OAuthError('Authentication timeout - no callback received within 2 minutes'));\n }, timeout);\n });\n}\n\n/**\n * Get the callback URL for the OAuth flow\n */\nexport async function getCallbackUrl(): Promise<string> {\n const port = await findAvailablePort();\n return `http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`;\n}\n","import { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { logger } from './logger.js';\n\nconst execAsync = promisify(exec);\n\n/**\n * Open a URL in the default browser\n */\nexport async function openBrowser(url: string): Promise<void> {\n const platform = process.platform;\n let command: string;\n\n // Determine the command based on the platform\n switch (platform) {\n case 'darwin': // macOS\n command = `open \"${url}\"`;\n break;\n case 'win32': // Windows\n command = `start \"\" \"${url}\"`;\n break;\n default: // Linux and others\n command = `xdg-open \"${url}\"`;\n break;\n }\n\n try {\n logger.debug(`Opening browser with command: ${command}`);\n await execAsync(command);\n logger.debug('Browser opened successfully');\n } catch (error) {\n logger.debug(`Failed to open browser: ${error}`);\n throw new Error(\n `Failed to open browser automatically. Please open this URL manually:\\n${url}`\n );\n }\n}\n","import { randomBytes } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { ofetch } from 'ofetch';\nimport { OAUTH_CONFIG, API_ENDPOINTS } from '../constants.js';\nimport { storageService } from './storage.service.js';\nimport { startOAuthCallbackServer, getCallbackUrl } from '../utils/oauth-server.js';\nimport { openBrowser } from '../utils/browser.js';\nimport { AuthenticationError, NetworkError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type { StoredCredentials, UserInfo } from '../types/config.types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Get CLI version and User-Agent string\n */\nfunction getUserAgent(): string {\n try {\n // In production (dist/services/auth.service.js), package.json is 2 levels up\n const packageJsonPath = join(__dirname, '../../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n const version = packageJson.version;\n const platform = process.platform;\n const arch = process.arch;\n return `BragDuck-CLI/${version} (${platform}-${arch})`;\n } catch (error) {\n logger.debug('Failed to read package.json version');\n return 'BragDuck-CLI/2.0.0';\n }\n}\n\n/**\n * Token exchange response from the backend\n */\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type: string;\n user?: UserInfo;\n}\n\n/**\n * Authentication service for managing OAuth flow and tokens\n */\nexport class AuthService {\n private apiBaseUrl: string;\n\n constructor() {\n // Use environment variable or default API URL\n this.apiBaseUrl = process.env.API_BASE_URL || 'https://api.bragduck.com';\n }\n\n /**\n * Generate a random state string for CSRF protection\n */\n private generateState(): string {\n return randomBytes(32).toString('hex');\n }\n\n /**\n * Build the OAuth authorization URL\n */\n private async buildAuthUrl(state: string, callbackUrl: string): Promise<string> {\n const params = new URLSearchParams({\n client_id: OAUTH_CONFIG.CLIENT_ID,\n redirect_uri: callbackUrl,\n state,\n });\n\n return `${this.apiBaseUrl}${API_ENDPOINTS.AUTH.INITIATE}?${params.toString()}`;\n }\n\n /**\n * Exchange authorization code for access token\n */\n private async exchangeCodeForToken(code: string, callbackUrl: string): Promise<TokenResponse> {\n try {\n logger.debug('Exchanging authorization code for token');\n\n const response = await ofetch<TokenResponse>(\n `${this.apiBaseUrl}${API_ENDPOINTS.AUTH.TOKEN}`,\n {\n method: 'POST',\n body: {\n code,\n redirect_uri: callbackUrl,\n client_id: OAUTH_CONFIG.CLIENT_ID,\n grant_type: 'authorization_code',\n },\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': getUserAgent(),\n },\n }\n );\n\n logger.debug('Token exchange successful');\n return response;\n } catch (error: any) {\n logger.debug(`Token exchange failed: ${error.message}`);\n\n if (error.response) {\n throw new AuthenticationError(\n `Token exchange failed: ${error.response.statusText || 'Unknown error'}`,\n {\n statusCode: error.response.status,\n body: error.response._data,\n }\n );\n }\n\n throw new NetworkError('Failed to connect to authentication server', {\n originalError: error.message,\n });\n }\n }\n\n /**\n * Complete OAuth flow: start server, open browser, wait for callback, exchange token\n */\n async login(): Promise<UserInfo> {\n logger.debug('Starting OAuth login flow');\n\n // Generate state for CSRF protection\n const state = this.generateState();\n const callbackUrl = await getCallbackUrl();\n\n // Store state temporarily\n storageService.setOAuthState({\n state,\n createdAt: Date.now(),\n });\n\n logger.debug(`OAuth state: ${state}`);\n logger.debug(`Callback URL: ${callbackUrl}`);\n\n // Build authorization URL\n const authUrl = await this.buildAuthUrl(state, callbackUrl);\n logger.debug(`Authorization URL: ${authUrl}`);\n\n // Start callback server (this will wait for the callback)\n const serverPromise = startOAuthCallbackServer(state);\n\n // Open browser\n try {\n await openBrowser(authUrl);\n } catch (error: any) {\n // If browser opening fails, show the URL for manual opening\n logger.warning('Could not open browser automatically');\n logger.info(`Please open this URL in your browser:`);\n logger.log(authUrl);\n }\n\n // Wait for callback\n let callbackResult;\n try {\n callbackResult = await serverPromise;\n } catch (error: any) {\n storageService.deleteOAuthState();\n throw error;\n }\n\n // Clear OAuth state\n storageService.deleteOAuthState();\n\n // Exchange code for token\n const tokenResponse = await this.exchangeCodeForToken(callbackResult.code, callbackUrl);\n\n // Calculate expiration time\n const expiresAt = tokenResponse.expires_in\n ? Date.now() + tokenResponse.expires_in * 1000\n : undefined;\n\n // Store credentials\n const credentials: StoredCredentials = {\n accessToken: tokenResponse.access_token,\n refreshToken: tokenResponse.refresh_token,\n expiresAt,\n };\n await storageService.setCredentials(credentials);\n\n // Store user info if provided\n if (tokenResponse.user) {\n storageService.setUserInfo(tokenResponse.user);\n }\n\n logger.debug('Login successful');\n\n return tokenResponse.user || { id: 'unknown', email: 'unknown', name: 'Unknown User' };\n }\n\n /**\n * Logout: clear all stored credentials and user info\n */\n async logout(): Promise<void> {\n logger.debug('Logging out');\n\n await storageService.deleteCredentials();\n storageService.deleteUserInfo();\n storageService.deleteOAuthState();\n\n logger.debug('Logout complete');\n }\n\n /**\n * Check if user is authenticated\n */\n async isAuthenticated(): Promise<boolean> {\n return storageService.isAuthenticated();\n }\n\n /**\n * Get current access token\n */\n async getAccessToken(): Promise<string | null> {\n const credentials = await storageService.getCredentials();\n return credentials?.accessToken || null;\n }\n\n /**\n * Get current user info\n */\n getUserInfo(): UserInfo | null {\n return storageService.getUserInfo();\n }\n\n /**\n * Refresh access token using refresh token\n */\n async refreshToken(): Promise<void> {\n logger.debug('Refreshing access token');\n\n const credentials = await storageService.getCredentials();\n if (!credentials?.refreshToken) {\n throw new AuthenticationError('No refresh token available');\n }\n\n try {\n const response = await ofetch<TokenResponse>(\n `${this.apiBaseUrl}${API_ENDPOINTS.AUTH.TOKEN}`,\n {\n method: 'POST',\n body: {\n refresh_token: credentials.refreshToken,\n client_id: OAUTH_CONFIG.CLIENT_ID,\n grant_type: 'refresh_token',\n },\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': getUserAgent(),\n },\n }\n );\n\n // Calculate expiration time\n const expiresAt = response.expires_in ? Date.now() + response.expires_in * 1000 : undefined;\n\n // Update stored credentials\n const newCredentials: StoredCredentials = {\n accessToken: response.access_token,\n refreshToken: response.refresh_token || credentials.refreshToken,\n expiresAt,\n };\n await storageService.setCredentials(newCredentials);\n\n logger.debug('Token refresh successful');\n } catch (error: any) {\n logger.debug(`Token refresh failed: ${error.message}`);\n\n // If refresh fails, user needs to re-authenticate\n await this.logout();\n throw new AuthenticationError('Token refresh failed. Please log in again.');\n }\n }\n}\n\n// Export singleton instance\nexport const authService = new AuthService();\n","import { ofetch, type FetchOptions } from 'ofetch';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { authService } from './auth.service.js';\nimport { API_ENDPOINTS, HTTP_STATUS } from '../constants.js';\nimport { ApiError, NetworkError, TokenExpiredError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type {\n RefineCommitsRequest,\n RefineCommitsResponse,\n CreateBragsRequest,\n CreateBragsResponse,\n ListBragsParams,\n ListBragsResponse,\n VersionCheckResponse,\n ApiErrorResponse,\n} from '../types/api.types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Get CLI version from package.json\n */\nfunction getCliVersion(): string {\n try {\n // In production (dist/services/api.service.js), package.json is 2 levels up\n const packageJsonPath = join(__dirname, '../../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n return packageJson.version;\n } catch (error) {\n logger.debug('Failed to read package.json version');\n return '2.0.0'; // Fallback version\n }\n}\n\n/**\n * Get platform information for User-Agent\n */\nfunction getPlatformInfo(): string {\n const platform = process.platform; // darwin, linux, win32, etc.\n const arch = process.arch; // arm64, x64, etc.\n return `${platform}-${arch}`;\n}\n\n/**\n * API service for communicating with the Bragduck backend\n */\nexport class ApiService {\n private baseURL: string;\n private client: typeof ofetch;\n\n constructor() {\n // Use environment variable or default API URL\n this.baseURL = process.env.API_BASE_URL || 'https://api.bragduck.com';\n\n // Create ofetch client with interceptors\n this.client = ofetch.create({\n baseURL: this.baseURL,\n\n // Request interceptor\n onRequest: async ({ options }) => {\n logger.debug(`API Request: ${options.method} ${(options as any).baseURL}${(options as any).url}`);\n\n // Add User-Agent header for CLI identification\n const cliVersion = getCliVersion();\n const platform = getPlatformInfo();\n const userAgent = `BragDuck-CLI/${cliVersion} (${platform})`;\n\n // Add authentication header\n const token = await authService.getAccessToken();\n if (token) {\n (options.headers as any) = {\n ...options.headers,\n 'User-Agent': userAgent,\n Authorization: `Bearer ${token}`,\n };\n } else {\n (options.headers as any) = {\n ...options.headers,\n 'User-Agent': userAgent,\n };\n }\n\n // Ensure Content-Type is set for POST/PUT requests\n if (options.method && ['POST', 'PUT', 'PATCH'].includes(options.method)) {\n (options.headers as any) = {\n ...options.headers,\n 'Content-Type': 'application/json',\n };\n }\n },\n\n // Response interceptor for success\n onResponse: ({ response }) => {\n logger.debug(`API Response: ${response.status} ${response.statusText}`);\n },\n\n // Response interceptor for errors\n onResponseError: async ({ response, options }) => {\n const status = response.status;\n const url = `${(options as any).baseURL}${(options as any).url}`;\n\n logger.debug(`API Error: ${status} ${response.statusText} - ${url}`);\n\n // Handle 401 Unauthorized - token expired\n if (status === HTTP_STATUS.UNAUTHORIZED) {\n logger.debug('Token expired, attempting refresh');\n\n try {\n // Try to refresh the token\n await authService.refreshToken();\n\n // Retry the request once with the new token\n logger.debug('Token refreshed, retrying request');\n throw new Error('RETRY_WITH_NEW_TOKEN');\n } catch (error: any) {\n if (error.message === 'RETRY_WITH_NEW_TOKEN') {\n throw error;\n }\n // If refresh fails, throw TokenExpiredError\n throw new TokenExpiredError('Your session has expired. Please run \"bragduck init\" to login again.');\n }\n }\n\n // Parse error response\n let errorMessage = 'An unexpected error occurred';\n let errorDetails: Record<string, any> | undefined;\n\n try {\n const errorData = response._data as ApiErrorResponse;\n if (errorData && errorData.message) {\n errorMessage = errorData.message;\n errorDetails = errorData.details;\n }\n } catch {\n // If we can't parse error, use status text\n errorMessage = response.statusText || errorMessage;\n }\n\n throw new ApiError(errorMessage, status, errorDetails);\n },\n\n // Retry configuration\n retry: 2,\n retryDelay: 1000,\n retryStatusCodes: [408, 409, 425, 429, 500, 502, 503, 504],\n\n // Timeout\n timeout: 30000, // 30 seconds\n });\n }\n\n /**\n * Make API request with retry for token refresh\n */\n private async makeRequest<T>(\n url: string,\n options: FetchOptions = {}\n ): Promise<T> {\n try {\n return await this.client<T>(url, options as any);\n } catch (error: any) {\n // If we got the special retry signal, retry the request once\n if (error.message === 'RETRY_WITH_NEW_TOKEN') {\n logger.debug('Retrying request with refreshed token');\n return await this.client<T>(url, options as any);\n }\n\n // Handle network errors\n if (error.name === 'FetchError' || error.code === 'ECONNREFUSED') {\n throw new NetworkError('Failed to connect to Bragduck API', {\n originalError: error.message,\n baseURL: this.baseURL,\n });\n }\n\n throw error;\n }\n }\n\n /**\n * Refine commits using AI\n */\n async refineCommits(request: RefineCommitsRequest): Promise<RefineCommitsResponse> {\n logger.debug(`Refining ${request.commits.length} commits`);\n\n try {\n const response = await this.makeRequest<RefineCommitsResponse>(\n API_ENDPOINTS.COMMITS.REFINE,\n {\n method: 'POST',\n body: request,\n }\n );\n\n logger.debug(`Successfully refined ${response.refined_commits.length} commits`);\n return response;\n } catch (error) {\n logger.debug('Failed to refine commits');\n throw error;\n }\n }\n\n /**\n * Create brags from refined commits\n */\n async createBrags(request: CreateBragsRequest): Promise<CreateBragsResponse> {\n logger.debug(`Creating ${request.brags.length} brags`);\n\n try {\n const response = await this.makeRequest<CreateBragsResponse>(\n API_ENDPOINTS.BRAGS.CREATE,\n {\n method: 'POST',\n body: request,\n }\n );\n\n logger.debug(`Successfully created ${response.created} brags`);\n return response;\n } catch (error) {\n logger.debug('Failed to create brags');\n throw error;\n }\n }\n\n /**\n * List existing brags\n */\n async listBrags(params: ListBragsParams = {}): Promise<ListBragsResponse> {\n const { limit = 50, offset = 0, tags, search } = params;\n\n logger.debug(`Listing brags: limit=${limit}, offset=${offset}`);\n\n try {\n // Build query parameters\n const queryParams = new URLSearchParams({\n limit: limit.toString(),\n offset: offset.toString(),\n });\n\n if (search) {\n queryParams.append('search', search);\n }\n\n if (tags && tags.length > 0) {\n tags.forEach((tag) => queryParams.append('tags[]', tag));\n }\n\n const url = `${API_ENDPOINTS.BRAGS.LIST}?${queryParams.toString()}`;\n\n const response = await this.makeRequest<ListBragsResponse>(url, {\n method: 'GET',\n });\n\n logger.debug(`Successfully fetched ${response.brags.length} brags (total: ${response.total})`);\n return response;\n } catch (error) {\n logger.debug('Failed to list brags');\n throw error;\n }\n }\n\n /**\n * Check for CLI updates\n */\n async checkVersion(): Promise<VersionCheckResponse> {\n logger.debug('Checking for CLI updates');\n\n try {\n const response = await this.makeRequest<VersionCheckResponse>(\n API_ENDPOINTS.VERSION,\n {\n method: 'GET',\n }\n );\n\n logger.debug(`Latest version: ${response.latest_version}`);\n return response;\n } catch (error) {\n logger.debug('Failed to check version');\n // Don't throw error for version check failures\n // Return current version as fallback\n const { version } = await import('../utils/version.js');\n return {\n latest_version: version,\n critical_update: false,\n };\n }\n }\n\n /**\n * Test API connectivity\n */\n async testConnection(): Promise<boolean> {\n try {\n await this.checkVersion();\n return true;\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update base URL\n */\n setBaseURL(url: string): void {\n this.baseURL = url;\n // Recreate client with new base URL\n this.client = ofetch.create({\n baseURL: url,\n });\n }\n\n /**\n * Get current base URL\n */\n getBaseURL(): string {\n return this.baseURL;\n }\n}\n\n// Export singleton instance\nexport const apiService = new ApiService();\n","import { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport chalk from 'chalk';\nimport boxen from 'boxen';\nimport { apiService } from '../services/api.service.js';\nimport { storageService } from '../services/storage.service.js';\nimport { logger } from './logger.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Get current CLI version from package.json\n */\nexport function getCurrentVersion(): string {\n try {\n // In production (dist/utils/version.js), package.json is 2 levels up\n const packageJsonPath = join(__dirname, '../../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n return packageJson.version;\n } catch (error) {\n logger.debug('Failed to read package.json version');\n return '1.0.0'; // Fallback version\n }\n}\n\n/**\n * Export current version\n */\nexport const version = getCurrentVersion();\n\n/**\n * Compare two semantic versions\n * Returns:\n * 1 if v1 > v2\n * 0 if v1 === v2\n * -1 if v1 < v2\n */\nexport function compareVersions(v1: string, v2: string): number {\n const parts1 = v1.split('.').map((p) => parseInt(p, 10));\n const parts2 = v2.split('.').map((p) => parseInt(p, 10));\n\n for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {\n const part1 = parts1[i] || 0;\n const part2 = parts2[i] || 0;\n\n if (part1 > part2) return 1;\n if (part1 < part2) return -1;\n }\n\n return 0;\n}\n\n/**\n * Check if a newer version is available\n */\nexport async function checkForUpdates(options: {\n silent?: boolean;\n force?: boolean;\n} = {}): Promise<{ updateAvailable: boolean; latestVersion: string; currentVersion: string }> {\n const { silent = false, force = false } = options;\n\n try {\n // Skip version check if disabled in config (unless forced)\n if (!force) {\n const autoVersionCheck = storageService.getConfig('autoVersionCheck');\n if (!autoVersionCheck) {\n logger.debug('Version check disabled in config');\n return {\n updateAvailable: false,\n latestVersion: version,\n currentVersion: version,\n };\n }\n }\n\n logger.debug('Checking for CLI updates...');\n\n // Check via API service\n const response = await apiService.checkVersion();\n const latestVersion = response.latest_version;\n const currentVersion = version;\n\n logger.debug(`Current version: ${currentVersion}, Latest version: ${latestVersion}`);\n\n const updateAvailable = compareVersions(latestVersion, currentVersion) > 0;\n\n // Display update notification if not silent and update is available\n if (!silent && updateAvailable) {\n displayUpdateNotification(currentVersion, latestVersion, response.critical_update);\n }\n\n return {\n updateAvailable,\n latestVersion,\n currentVersion,\n };\n } catch (error: any) {\n logger.debug(`Version check failed: ${error.message}`);\n // Don't throw error - version check is non-critical\n return {\n updateAvailable: false,\n latestVersion: version,\n currentVersion: version,\n };\n }\n}\n\n/**\n * Display update notification\n */\nfunction displayUpdateNotification(\n currentVersion: string,\n latestVersion: string,\n critical: boolean = false\n): void {\n const urgency = critical ? chalk.red.bold('CRITICAL UPDATE') : chalk.yellow.bold('Update Available');\n const message =\n `${urgency}\\n\\n` +\n `Current version: ${chalk.dim(currentVersion)}\\n` +\n `Latest version: ${chalk.green(latestVersion)}\\n\\n` +\n `Update with: ${chalk.cyan('npm install -g @bragduck/cli@latest')}`;\n\n console.log('');\n console.log(\n boxen(message, {\n padding: 1,\n margin: { top: 0, right: 1, bottom: 0, left: 1 },\n borderStyle: 'round',\n borderColor: critical ? 'red' : 'yellow',\n })\n );\n console.log('');\n\n if (critical) {\n logger.warning('This is a critical update. Please update as soon as possible.');\n console.log('');\n }\n}\n\n/**\n * Format version for display\n */\nexport function formatVersion(includePrefix: boolean = true): string {\n const prefix = includePrefix ? 'v' : '';\n return `${prefix}${version}`;\n}\n","// Main entry point for the Bragduck CLI package\n// This file exports the public API for programmatic usage\n\nexport { version } from './utils/version.js';\n\n// Future exports will be added here as we implement services and utilities\n// Example:\n// export { AuthService } from './services/auth.service.js';\n// export { GitService } from './services/git.service.js';\n// export { ApiService } from './services/api.service.js';\n"],"mappings":"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","names":["fileURLToPath","join","randomBytes","readFileSync","fileURLToPath","dirname","join","__dirname","version","__filename","ofetch","readFileSync","fileURLToPath","dirname","join","__dirname","__filename","version","readFileSync","fileURLToPath","dirname","join","chalk","__dirname","__filename"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/constants.ts","../src/services/storage.service.ts","../src/utils/errors.ts","../src/utils/logger.ts","../src/utils/oauth-server.ts","../src/utils/browser.ts","../src/services/auth.service.ts","../src/services/api.service.ts","../src/utils/version.ts","../src/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","// Load environment variables\nimport { config } from 'dotenv';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\n\n// Get the directory of this file\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Load .env from the project root\n// In production, this file is bundled into dist/bin/bragduck.js, so we need to go up 2 levels\n// In development (src/), we'd need to go up 1 level, but the build is what matters\nconfig({ path: join(__dirname, '..', '..', '.env') });\n\n// App-wide constants for Bragduck CLI\n\n/**\n * Application name used for storage and configuration\n */\nexport const APP_NAME = 'bragduck';\n\n/**\n * Storage keys for credentials and configuration\n */\nexport const STORAGE_KEYS = {\n ACCESS_TOKEN: 'access_token',\n REFRESH_TOKEN: 'refresh_token',\n USER_INFO: 'user_info',\n OAUTH_STATE: 'oauth_state',\n} as const;\n\n/**\n * Configuration keys\n */\nexport const CONFIG_KEYS = {\n DEFAULT_COMMIT_DAYS: 'defaultCommitDays',\n AUTO_VERSION_CHECK: 'autoVersionCheck',\n} as const;\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG = {\n defaultCommitDays: 30,\n autoVersionCheck: true,\n} as const;\n\n/**\n * OAuth configuration\n */\nexport const OAUTH_CONFIG = {\n CLIENT_ID: 'bragduck-cli',\n CALLBACK_PATH: '/callback',\n TIMEOUT_MS: 120000, // 2 minutes\n MIN_PORT: 8000,\n MAX_PORT: 9000,\n} as const;\n\n/**\n * API endpoints\n */\nexport const API_ENDPOINTS = {\n AUTH: {\n INITIATE: '/v1/auth/cli/initiate',\n TOKEN: '/v1/auth/cli/token',\n },\n COMMITS: {\n REFINE: '/v1/commits/refine',\n },\n BRAGS: {\n CREATE: '/v1/brags',\n LIST: '/v1/brags',\n },\n VERSION: '/v1/cli/version',\n} as const;\n\n/**\n * Encryption configuration for file-based credential storage\n */\nexport const ENCRYPTION_CONFIG = {\n ALGORITHM: 'aes-256-gcm',\n KEY_LENGTH: 32,\n IV_LENGTH: 16,\n AUTH_TAG_LENGTH: 16,\n SALT_LENGTH: 32,\n} as const;\n\n/**\n * File paths for credential storage fallback\n */\nexport const STORAGE_PATHS = {\n CREDENTIALS_DIR: '.bragduck',\n CREDENTIALS_FILE: 'credentials.enc',\n CONFIG_FILE: 'config.json',\n} as const;\n\n/**\n * Error codes\n */\nexport const ERROR_CODES = {\n AUTH_FAILED: 'AUTH_FAILED',\n TOKEN_EXPIRED: 'TOKEN_EXPIRED',\n NETWORK_ERROR: 'NETWORK_ERROR',\n GIT_ERROR: 'GIT_ERROR',\n API_ERROR: 'API_ERROR',\n STORAGE_ERROR: 'STORAGE_ERROR',\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n} as const;\n\n/**\n * HTTP status codes\n */\nexport const HTTP_STATUS = {\n OK: 200,\n CREATED: 201,\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n INTERNAL_SERVER_ERROR: 500,\n} as const;\n\n/**\n * GitHub configuration\n */\nexport const GITHUB_CONFIG = {\n MIN_GH_VERSION: '2.0.0',\n PR_SEARCH_FIELDS:\n 'number,title,body,author,mergedAt,additions,deletions,changedFiles,url,labels',\n MAX_BODY_LENGTH: 5000,\n} as const;\n","import Conf from 'conf';\nimport { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { APP_NAME, ENCRYPTION_CONFIG, STORAGE_PATHS, DEFAULT_CONFIG } from '../constants.js';\nimport type {\n StoredCredentials,\n UserInfo,\n OAuthState,\n StorageBackend,\n EncryptedData,\n BragduckConfig,\n} from '../types/config.types.js';\n\n/**\n * Storage service for managing credentials and configuration\n * Uses encrypted file storage for credentials\n *\n * NOTE: OS keychain support (via cross-keychain or similar) can be added in the future.\n * For now, we use secure encrypted file storage with machine-specific keys.\n */\nexport class StorageService {\n private config: Conf<BragduckConfig>;\n private storageBackend: StorageBackend;\n private credentialsDir: string;\n private credentialsFilePath: string;\n\n constructor() {\n // Initialize config management\n this.config = new Conf<BragduckConfig>({\n projectName: APP_NAME,\n defaults: DEFAULT_CONFIG,\n });\n\n // Set up credentials directory and file path\n this.credentialsDir = join(homedir(), STORAGE_PATHS.CREDENTIALS_DIR);\n this.credentialsFilePath = join(this.credentialsDir, STORAGE_PATHS.CREDENTIALS_FILE);\n\n // Use file storage for now (keychain support can be added later)\n this.storageBackend = 'file';\n this.ensureCredentialsDir();\n }\n\n /**\n * Ensure credentials directory exists\n */\n private ensureCredentialsDir(): void {\n if (!existsSync(this.credentialsDir)) {\n mkdirSync(this.credentialsDir, { recursive: true, mode: 0o700 });\n }\n }\n\n /**\n * Encrypt data for file storage\n */\n private encrypt(data: string, key: Buffer): EncryptedData {\n const iv = randomBytes(ENCRYPTION_CONFIG.IV_LENGTH);\n const cipher = createCipheriv(ENCRYPTION_CONFIG.ALGORITHM, key, iv, {\n authTagLength: ENCRYPTION_CONFIG.AUTH_TAG_LENGTH,\n });\n\n let encrypted = cipher.update(data, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n\n const authTag = cipher.getAuthTag();\n\n return {\n encrypted,\n iv: iv.toString('hex'),\n authTag: authTag.toString('hex'),\n salt: '', // Salt is stored separately\n };\n }\n\n /**\n * Decrypt data from file storage\n */\n private decrypt(encryptedData: EncryptedData, key: Buffer): string {\n const decipher = createDecipheriv(\n ENCRYPTION_CONFIG.ALGORITHM,\n key,\n Buffer.from(encryptedData.iv, 'hex'),\n {\n authTagLength: ENCRYPTION_CONFIG.AUTH_TAG_LENGTH,\n }\n );\n\n decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));\n\n let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');\n decrypted += decipher.final('utf8');\n\n return decrypted;\n }\n\n /**\n * Derive encryption key from machine-specific data\n */\n private deriveEncryptionKey(salt: Buffer): Buffer {\n // Use machine ID and app name as password\n const password = `${APP_NAME}-${homedir()}-${process.platform}`;\n return scryptSync(password, salt, ENCRYPTION_CONFIG.KEY_LENGTH);\n }\n\n /**\n * Store credentials using encrypted file storage\n */\n async setCredentials(credentials: StoredCredentials): Promise<void> {\n const data = JSON.stringify(credentials);\n\n // Encrypt and store credentials\n const salt = randomBytes(ENCRYPTION_CONFIG.SALT_LENGTH);\n const key = this.deriveEncryptionKey(salt);\n const encrypted = this.encrypt(data, key);\n encrypted.salt = salt.toString('hex');\n\n writeFileSync(this.credentialsFilePath, JSON.stringify(encrypted), {\n mode: 0o600,\n encoding: 'utf8',\n });\n }\n\n /**\n * Retrieve credentials from encrypted file storage\n */\n async getCredentials(): Promise<StoredCredentials | null> {\n if (!existsSync(this.credentialsFilePath)) {\n return null;\n }\n\n try {\n const encryptedData: EncryptedData = JSON.parse(\n readFileSync(this.credentialsFilePath, 'utf8')\n );\n const salt = Buffer.from(encryptedData.salt, 'hex');\n const key = this.deriveEncryptionKey(salt);\n const decrypted = this.decrypt(encryptedData, key);\n return JSON.parse(decrypted);\n } catch (error) {\n console.error('Failed to decrypt credentials:', error);\n return null;\n }\n }\n\n /**\n * Delete credentials from file storage\n */\n async deleteCredentials(): Promise<void> {\n // Delete file if it exists\n if (existsSync(this.credentialsFilePath)) {\n try {\n unlinkSync(this.credentialsFilePath);\n } catch (error) {\n console.error('Failed to delete credentials file:', error);\n }\n }\n }\n\n /**\n * Check if user is authenticated\n */\n async isAuthenticated(): Promise<boolean> {\n const credentials = await this.getCredentials();\n if (!credentials || !credentials.accessToken) {\n return false;\n }\n\n // Check if token is expired\n if (credentials.expiresAt && credentials.expiresAt < Date.now()) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Store user information\n */\n setUserInfo(userInfo: UserInfo): void {\n this.config.set('userInfo' as keyof BragduckConfig, userInfo as any);\n }\n\n /**\n * Get user information\n */\n getUserInfo(): UserInfo | null {\n return (this.config.get('userInfo' as keyof BragduckConfig) as any) || null;\n }\n\n /**\n * Delete user information\n */\n deleteUserInfo(): void {\n this.config.delete('userInfo' as keyof BragduckConfig);\n }\n\n /**\n * Store OAuth state for CSRF protection\n */\n setOAuthState(state: OAuthState): void {\n this.config.set('oauthState' as keyof BragduckConfig, state as any);\n }\n\n /**\n * Get OAuth state\n */\n getOAuthState(): OAuthState | null {\n return (this.config.get('oauthState' as keyof BragduckConfig) as any) || null;\n }\n\n /**\n * Delete OAuth state\n */\n deleteOAuthState(): void {\n this.config.delete('oauthState' as keyof BragduckConfig);\n }\n\n /**\n * Get configuration value\n */\n getConfig<K extends keyof BragduckConfig>(key: K): BragduckConfig[K] {\n return this.config.get(key);\n }\n\n /**\n * Set configuration value\n */\n setConfig<K extends keyof BragduckConfig>(key: K, value: BragduckConfig[K]): void {\n this.config.set(key, value);\n }\n\n /**\n * Get all configuration\n */\n getAllConfig(): BragduckConfig {\n return this.config.store;\n }\n\n /**\n * Reset configuration to defaults\n */\n resetConfig(): void {\n this.config.clear();\n // Re-apply defaults\n Object.entries(DEFAULT_CONFIG).forEach(([key, value]) => {\n this.config.set(key as keyof BragduckConfig, value as any);\n });\n }\n\n /**\n * Get current storage backend\n */\n getStorageBackend(): StorageBackend {\n return this.storageBackend;\n }\n\n /**\n * Clear all stored data (credentials + config)\n */\n async clearAll(): Promise<void> {\n await this.deleteCredentials();\n this.deleteUserInfo();\n this.deleteOAuthState();\n this.resetConfig();\n }\n}\n\n// Export singleton instance\nexport const storageService = new StorageService();\n","// Custom error classes for Bragduck CLI\n\n/**\n * Base error class for all Bragduck errors\n */\nexport class BragduckError extends Error {\n public code: string;\n public details?: Record<string, any>;\n\n constructor(\n message: string,\n code: string,\n details?: Record<string, any>\n ) {\n super(message);\n this.name = 'BragduckError';\n this.code = code;\n this.details = details;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Authentication-related errors\n */\nexport class AuthenticationError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'AUTH_ERROR', details);\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Git operation errors\n */\nexport class GitError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'GIT_ERROR', details);\n this.name = 'GitError';\n }\n}\n\n/**\n * API communication errors\n */\nexport class ApiError extends BragduckError {\n public statusCode?: number;\n\n constructor(\n message: string,\n statusCode?: number,\n details?: Record<string, any>\n ) {\n super(message, 'API_ERROR', details);\n this.name = 'ApiError';\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Network-related errors\n */\nexport class NetworkError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'NETWORK_ERROR', details);\n this.name = 'NetworkError';\n }\n}\n\n/**\n * Storage-related errors\n */\nexport class StorageError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'STORAGE_ERROR', details);\n this.name = 'StorageError';\n }\n}\n\n/**\n * Validation errors\n */\nexport class ValidationError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'VALIDATION_ERROR', details);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * OAuth-specific errors\n */\nexport class OAuthError extends AuthenticationError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, details);\n this.name = 'OAuthError';\n }\n}\n\n/**\n * Token expiration error\n */\nexport class TokenExpiredError extends AuthenticationError {\n constructor(message = 'Authentication token has expired') {\n super(message);\n this.name = 'TokenExpiredError';\n this.code = 'TOKEN_EXPIRED';\n }\n}\n\n/**\n * GitHub-related errors\n */\nexport class GitHubError extends BragduckError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'GITHUB_ERROR', details);\n this.name = 'GitHubError';\n }\n}\n","import chalk from 'chalk';\n\n/**\n * Logger utility for consistent console output\n */\nexport const logger = {\n /**\n * Debug message (only shown when DEBUG env var is set)\n */\n debug: (message: string, ...args: any[]): void => {\n if (process.env.DEBUG) {\n console.log(chalk.gray(`[DEBUG] ${message}`), ...args);\n }\n },\n\n /**\n * Info message\n */\n info: (message: string): void => {\n console.log(chalk.blue(`ℹ ${message}`));\n },\n\n /**\n * Success message\n */\n success: (message: string): void => {\n console.log(chalk.green(`✓ ${message}`));\n },\n\n /**\n * Warning message\n */\n warning: (message: string): void => {\n console.warn(chalk.yellow(`⚠ ${message}`));\n },\n\n /**\n * Error message\n */\n error: (message: string): void => {\n console.error(chalk.red(`✗ ${message}`));\n },\n\n /**\n * Plain log without formatting\n */\n log: (message: string): void => {\n console.log(message);\n },\n};\n","import { createServer, type Server, type IncomingMessage, type ServerResponse } from 'http';\nimport { parse } from 'url';\nimport { OAUTH_CONFIG } from '../constants.js';\nimport { OAuthError } from './errors.js';\nimport { logger } from './logger.js';\n\n/**\n * OAuth callback result\n */\nexport interface OAuthCallbackResult {\n code: string;\n state: string;\n port: number;\n}\n\n/**\n * Find an available port in the configured range\n */\nasync function findAvailablePort(): Promise<number> {\n const { MIN_PORT, MAX_PORT } = OAUTH_CONFIG;\n\n for (let port = MIN_PORT; port <= MAX_PORT; port++) {\n try {\n await new Promise<void>((resolve, reject) => {\n const testServer = createServer();\n testServer.once('error', reject);\n testServer.once('listening', () => {\n testServer.close(() => resolve());\n });\n testServer.listen(port, '127.0.0.1');\n });\n return port;\n } catch {\n // Port is in use, try next one\n continue;\n }\n }\n\n throw new OAuthError(`No available ports found in range ${MIN_PORT}-${MAX_PORT}`);\n}\n\n/**\n * Success HTML page to show after authentication\n */\nconst SUCCESS_HTML = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Bragduck - Authentication Successful</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n }\n .container {\n text-align: center;\n padding: 2rem;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 1rem;\n backdrop-filter: blur(10px);\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);\n max-width: 500px;\n }\n h1 {\n font-size: 2.5rem;\n margin: 0 0 1rem 0;\n }\n .checkmark {\n font-size: 4rem;\n animation: scale-in 0.3s ease-out;\n }\n p {\n font-size: 1.2rem;\n margin: 1rem 0;\n opacity: 0.9;\n }\n @keyframes scale-in {\n from { transform: scale(0); }\n to { transform: scale(1); }\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"checkmark\">✓</div>\n <h1>Authentication Successful!</h1>\n <p>You can now close this window and return to your terminal.</p>\n </div>\n</body>\n</html>\n`;\n\n/**\n * Error HTML page to show on authentication failure\n */\nconst ERROR_HTML = (error: string) => `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Bragduck - Authentication Failed</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n color: white;\n }\n .container {\n text-align: center;\n padding: 2rem;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 1rem;\n backdrop-filter: blur(10px);\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);\n max-width: 500px;\n }\n h1 {\n font-size: 2.5rem;\n margin: 0 0 1rem 0;\n }\n .error-icon {\n font-size: 4rem;\n }\n p {\n font-size: 1.2rem;\n margin: 1rem 0;\n opacity: 0.9;\n }\n .error-details {\n background: rgba(0, 0, 0, 0.2);\n padding: 1rem;\n border-radius: 0.5rem;\n font-family: monospace;\n font-size: 0.9rem;\n margin-top: 1rem;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"error-icon\">✗</div>\n <h1>Authentication Failed</h1>\n <p>Please return to your terminal and try again.</p>\n <div class=\"error-details\">${error}</div>\n </div>\n</body>\n</html>\n`;\n\n/**\n * Start OAuth callback server and wait for callback\n */\nexport async function startOAuthCallbackServer(expectedState: string): Promise<OAuthCallbackResult> {\n const port = await findAvailablePort();\n const timeout = OAUTH_CONFIG.TIMEOUT_MS;\n\n return new Promise<OAuthCallbackResult>((resolve, reject) => {\n let server: Server | null = null;\n let timeoutId: ReturnType<typeof globalThis.setTimeout> | null = null;\n\n const cleanup = () => {\n if (timeoutId) {\n globalThis.clearTimeout(timeoutId);\n }\n if (server) {\n // Close all connections immediately (Node.js 18+)\n if (typeof (server as any).closeAllConnections === 'function') {\n (server as any).closeAllConnections();\n }\n server.close(() => {\n logger.debug('OAuth server closed');\n });\n server.unref(); // Allow process to exit even if server is still running\n }\n };\n\n const handleRequest = (req: IncomingMessage, res: ServerResponse) => {\n const parsedUrl = parse(req.url || '', true);\n\n logger.debug(`OAuth callback received: ${req.url}`);\n\n // Handle callback request\n if (parsedUrl.pathname === OAUTH_CONFIG.CALLBACK_PATH) {\n const { code, state, error, error_description } = parsedUrl.query;\n\n // Check for OAuth errors\n if (error) {\n const errorMsg = error_description || error;\n logger.debug(`OAuth error: ${errorMsg}`);\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(ERROR_HTML(String(errorMsg)));\n\n cleanup();\n reject(new OAuthError(`OAuth error: ${errorMsg}`));\n return;\n }\n\n // Validate required parameters\n if (!code || !state) {\n const errorMsg = 'Missing code or state parameter';\n logger.debug(errorMsg);\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(ERROR_HTML(errorMsg));\n\n cleanup();\n reject(new OAuthError(errorMsg));\n return;\n }\n\n // Verify state matches (CSRF protection)\n if (state !== expectedState) {\n const errorMsg = 'Invalid state parameter (possible CSRF attack)';\n logger.debug(errorMsg);\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(ERROR_HTML(errorMsg));\n\n cleanup();\n reject(new OAuthError(errorMsg));\n return;\n }\n\n // Success!\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(SUCCESS_HTML);\n\n // Give the response time to be sent before closing\n globalThis.setTimeout(() => {\n cleanup();\n resolve({\n code: String(code),\n state: String(state),\n port,\n });\n }, 100);\n return;\n }\n\n // Handle other requests (404)\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not Found');\n };\n\n // Create server\n server = createServer(handleRequest);\n\n // Handle server errors\n server.on('error', (error) => {\n logger.debug(`OAuth server error: ${error.message}`);\n cleanup();\n reject(new OAuthError(`OAuth server error: ${error.message}`));\n });\n\n // Start server\n server.listen(port, '127.0.0.1', () => {\n logger.debug(`OAuth callback server listening on http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`);\n });\n\n // Set timeout\n timeoutId = globalThis.setTimeout(() => {\n logger.debug('OAuth callback timeout');\n cleanup();\n reject(new OAuthError('Authentication timeout - no callback received within 2 minutes'));\n }, timeout);\n });\n}\n\n/**\n * Get the callback URL for the OAuth flow\n */\nexport async function getCallbackUrl(): Promise<string> {\n const port = await findAvailablePort();\n return `http://127.0.0.1:${port}${OAUTH_CONFIG.CALLBACK_PATH}`;\n}\n","import { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { logger } from './logger.js';\n\nconst execAsync = promisify(exec);\n\n/**\n * Open a URL in the default browser\n */\nexport async function openBrowser(url: string): Promise<void> {\n const platform = process.platform;\n let command: string;\n\n // Determine the command based on the platform\n switch (platform) {\n case 'darwin': // macOS\n command = `open \"${url}\"`;\n break;\n case 'win32': // Windows\n command = `start \"\" \"${url}\"`;\n break;\n default: // Linux and others\n command = `xdg-open \"${url}\"`;\n break;\n }\n\n try {\n logger.debug(`Opening browser with command: ${command}`);\n await execAsync(command);\n logger.debug('Browser opened successfully');\n } catch (error) {\n logger.debug(`Failed to open browser: ${error}`);\n throw new Error(\n `Failed to open browser automatically. Please open this URL manually:\\n${url}`\n );\n }\n}\n","import { randomBytes } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath, URLSearchParams } from 'url';\nimport { dirname, join } from 'path';\nimport { ofetch } from 'ofetch';\nimport { OAUTH_CONFIG, API_ENDPOINTS } from '../constants.js';\nimport { storageService } from './storage.service.js';\nimport { startOAuthCallbackServer, getCallbackUrl } from '../utils/oauth-server.js';\nimport { openBrowser } from '../utils/browser.js';\nimport { AuthenticationError, NetworkError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type { StoredCredentials, UserInfo } from '../types/config.types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Get CLI version and User-Agent string\n */\nfunction getUserAgent(): string {\n try {\n // In production (dist/services/auth.service.js), package.json is 2 levels up\n const packageJsonPath = join(__dirname, '../../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n const version = packageJson.version;\n const platform = process.platform;\n const arch = process.arch;\n return `BragDuck-CLI/${version} (${platform}-${arch})`;\n } catch {\n logger.debug('Failed to read package.json version');\n return 'BragDuck-CLI/2.0.0';\n }\n}\n\n/**\n * Token exchange response from the backend\n */\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type: string;\n user?: UserInfo;\n}\n\n/**\n * Authentication service for managing OAuth flow and tokens\n */\nexport class AuthService {\n private apiBaseUrl: string;\n\n constructor() {\n // Use environment variable or default API URL\n this.apiBaseUrl = process.env.API_BASE_URL || 'https://api.bragduck.com';\n }\n\n /**\n * Generate a random state string for CSRF protection\n */\n private generateState(): string {\n return randomBytes(32).toString('hex');\n }\n\n /**\n * Build the OAuth authorization URL\n */\n private async buildAuthUrl(state: string, callbackUrl: string): Promise<string> {\n const params = new URLSearchParams({\n client_id: OAUTH_CONFIG.CLIENT_ID,\n redirect_uri: callbackUrl,\n state,\n });\n\n return `${this.apiBaseUrl}${API_ENDPOINTS.AUTH.INITIATE}?${params.toString()}`;\n }\n\n /**\n * Exchange authorization code for access token\n */\n private async exchangeCodeForToken(code: string, callbackUrl: string): Promise<TokenResponse> {\n try {\n logger.debug('Exchanging authorization code for token');\n\n const response = await ofetch<TokenResponse>(\n `${this.apiBaseUrl}${API_ENDPOINTS.AUTH.TOKEN}`,\n {\n method: 'POST',\n body: {\n code,\n redirect_uri: callbackUrl,\n client_id: OAUTH_CONFIG.CLIENT_ID,\n grant_type: 'authorization_code',\n },\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': getUserAgent(),\n },\n }\n );\n\n logger.debug('Token exchange successful');\n return response;\n } catch (error: any) {\n logger.debug(`Token exchange failed: ${error.message}`);\n\n if (error.response) {\n throw new AuthenticationError(\n `Token exchange failed: ${error.response.statusText || 'Unknown error'}`,\n {\n statusCode: error.response.status,\n body: error.response._data,\n }\n );\n }\n\n throw new NetworkError('Failed to connect to authentication server', {\n originalError: error.message,\n });\n }\n }\n\n /**\n * Complete OAuth flow: start server, open browser, wait for callback, exchange token\n */\n async login(): Promise<UserInfo> {\n logger.debug('Starting OAuth login flow');\n\n // Generate state for CSRF protection\n const state = this.generateState();\n const callbackUrl = await getCallbackUrl();\n\n // Store state temporarily\n storageService.setOAuthState({\n state,\n createdAt: Date.now(),\n });\n\n logger.debug(`OAuth state: ${state}`);\n logger.debug(`Callback URL: ${callbackUrl}`);\n\n // Build authorization URL\n const authUrl = await this.buildAuthUrl(state, callbackUrl);\n logger.debug(`Authorization URL: ${authUrl}`);\n\n // Start callback server (this will wait for the callback)\n const serverPromise = startOAuthCallbackServer(state);\n\n // Open browser\n try {\n await openBrowser(authUrl);\n } catch {\n // If browser opening fails, show the URL for manual opening\n logger.warning('Could not open browser automatically');\n logger.info(`Please open this URL in your browser:`);\n logger.log(authUrl);\n }\n\n // Wait for callback\n let callbackResult;\n try {\n callbackResult = await serverPromise;\n } catch (error: any) {\n storageService.deleteOAuthState();\n throw error;\n }\n\n // Clear OAuth state\n storageService.deleteOAuthState();\n\n // Exchange code for token\n const tokenResponse = await this.exchangeCodeForToken(callbackResult.code, callbackUrl);\n\n // Calculate expiration time\n const expiresAt = tokenResponse.expires_in\n ? Date.now() + tokenResponse.expires_in * 1000\n : undefined;\n\n // Store credentials\n const credentials: StoredCredentials = {\n accessToken: tokenResponse.access_token,\n refreshToken: tokenResponse.refresh_token,\n expiresAt,\n };\n await storageService.setCredentials(credentials);\n\n // Store user info if provided\n if (tokenResponse.user) {\n storageService.setUserInfo(tokenResponse.user);\n }\n\n logger.debug('Login successful');\n\n return tokenResponse.user || { id: 'unknown', email: 'unknown', name: 'Unknown User' };\n }\n\n /**\n * Logout: clear all stored credentials and user info\n */\n async logout(): Promise<void> {\n logger.debug('Logging out');\n\n await storageService.deleteCredentials();\n storageService.deleteUserInfo();\n storageService.deleteOAuthState();\n\n logger.debug('Logout complete');\n }\n\n /**\n * Check if user is authenticated\n */\n async isAuthenticated(): Promise<boolean> {\n return storageService.isAuthenticated();\n }\n\n /**\n * Get current access token\n */\n async getAccessToken(): Promise<string | null> {\n const credentials = await storageService.getCredentials();\n return credentials?.accessToken || null;\n }\n\n /**\n * Get current user info\n */\n getUserInfo(): UserInfo | null {\n return storageService.getUserInfo();\n }\n\n /**\n * Refresh access token using refresh token\n */\n async refreshToken(): Promise<void> {\n logger.debug('Refreshing access token');\n\n const credentials = await storageService.getCredentials();\n if (!credentials?.refreshToken) {\n throw new AuthenticationError('No refresh token available');\n }\n\n try {\n const response = await ofetch<TokenResponse>(\n `${this.apiBaseUrl}${API_ENDPOINTS.AUTH.TOKEN}`,\n {\n method: 'POST',\n body: {\n refresh_token: credentials.refreshToken,\n client_id: OAUTH_CONFIG.CLIENT_ID,\n grant_type: 'refresh_token',\n },\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': getUserAgent(),\n },\n }\n );\n\n // Calculate expiration time\n const expiresAt = response.expires_in ? Date.now() + response.expires_in * 1000 : undefined;\n\n // Update stored credentials\n const newCredentials: StoredCredentials = {\n accessToken: response.access_token,\n refreshToken: response.refresh_token || credentials.refreshToken,\n expiresAt,\n };\n await storageService.setCredentials(newCredentials);\n\n logger.debug('Token refresh successful');\n } catch (error: any) {\n logger.debug(`Token refresh failed: ${error.message}`);\n\n // If refresh fails, user needs to re-authenticate\n await this.logout();\n throw new AuthenticationError('Token refresh failed. Please log in again.');\n }\n }\n}\n\n// Export singleton instance\nexport const authService = new AuthService();\n","import { ofetch, type FetchOptions } from 'ofetch';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { URLSearchParams } from 'url';\nimport { dirname, join } from 'path';\nimport { authService } from './auth.service.js';\nimport { API_ENDPOINTS, HTTP_STATUS } from '../constants.js';\nimport { ApiError, NetworkError, TokenExpiredError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type {\n RefineCommitsRequest,\n RefineCommitsResponse,\n CreateBragsRequest,\n CreateBragsResponse,\n ListBragsParams,\n ListBragsResponse,\n VersionCheckResponse,\n ApiErrorResponse,\n} from '../types/api.types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Extended fetch options with internal ofetch properties\n */\ninterface ExtendedFetchOptions extends FetchOptions {\n baseURL?: string;\n url?: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Get CLI version from package.json\n */\nfunction getCliVersion(): string {\n try {\n // In production (dist/services/api.service.js), package.json is 2 levels up\n const packageJsonPath = join(__dirname, '../../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n return packageJson.version;\n } catch {\n logger.debug('Failed to read package.json version');\n return '2.0.0'; // Fallback version\n }\n}\n\n/**\n * Get platform information for User-Agent\n */\nfunction getPlatformInfo(): string {\n const platform = process.platform; // darwin, linux, win32, etc.\n const arch = process.arch; // arm64, x64, etc.\n return `${platform}-${arch}`;\n}\n\n/**\n * API service for communicating with the Bragduck backend\n */\nexport class ApiService {\n private baseURL: string;\n private client: typeof ofetch;\n\n constructor() {\n // Use environment variable or default API URL\n this.baseURL = process.env.API_BASE_URL || 'https://api.bragduck.com';\n\n // Create ofetch client with interceptors\n this.client = ofetch.create({\n baseURL: this.baseURL,\n\n // Request interceptor\n onRequest: async ({ options }) => {\n const extendedOptions = options as ExtendedFetchOptions;\n logger.debug(`API Request: ${options.method} ${extendedOptions.baseURL}${extendedOptions.url}`);\n\n // Add User-Agent header for CLI identification\n const cliVersion = getCliVersion();\n const platform = getPlatformInfo();\n const userAgent = `BragDuck-CLI/${cliVersion} (${platform})`;\n\n // Add authentication header\n const token = await authService.getAccessToken();\n const headers: Record<string, string> = {\n ...(options.headers as Record<string, string>),\n 'User-Agent': userAgent,\n };\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n // Ensure Content-Type is set for POST/PUT requests\n if (options.method && ['POST', 'PUT', 'PATCH'].includes(options.method)) {\n headers['Content-Type'] = 'application/json';\n }\n\n options.headers = headers;\n },\n\n // Response interceptor for success\n onResponse: ({ response }) => {\n logger.debug(`API Response: ${response.status} ${response.statusText}`);\n },\n\n // Response interceptor for errors\n onResponseError: async ({ response, options }) => {\n const status = response.status;\n const extendedOptions = options as ExtendedFetchOptions;\n const url = `${extendedOptions.baseURL}${extendedOptions.url}`;\n\n logger.debug(`API Error: ${status} ${response.statusText} - ${url}`);\n\n // Handle 401 Unauthorized - token expired\n if (status === HTTP_STATUS.UNAUTHORIZED) {\n logger.debug('Token expired, attempting refresh');\n\n try {\n // Try to refresh the token\n await authService.refreshToken();\n\n // Retry the request once with the new token\n logger.debug('Token refreshed, retrying request');\n throw new Error('RETRY_WITH_NEW_TOKEN');\n } catch (error: any) {\n if (error.message === 'RETRY_WITH_NEW_TOKEN') {\n throw error;\n }\n // If refresh fails, throw TokenExpiredError\n throw new TokenExpiredError('Your session has expired. Please run \"bragduck init\" to login again.');\n }\n }\n\n // Parse error response\n let errorMessage = 'An unexpected error occurred';\n let errorDetails: Record<string, any> | undefined;\n\n try {\n const errorData = response._data as ApiErrorResponse;\n if (errorData && errorData.message) {\n errorMessage = errorData.message;\n errorDetails = errorData.details;\n }\n } catch {\n // If we can't parse error, use status text\n errorMessage = response.statusText || errorMessage;\n }\n\n throw new ApiError(errorMessage, status, errorDetails);\n },\n\n // Retry configuration\n retry: 2,\n retryDelay: 1000,\n retryStatusCodes: [408, 409, 425, 429, 500, 502, 503, 504],\n\n // Timeout\n timeout: 30000, // 30 seconds\n });\n }\n\n /**\n * Make API request with retry for token refresh\n */\n private async makeRequest<T>(\n url: string,\n options: FetchOptions = {}\n ): Promise<T> {\n try {\n return await this.client<T>(url, options);\n } catch (error: any) {\n // If we got the special retry signal, retry the request once\n if (error.message === 'RETRY_WITH_NEW_TOKEN') {\n logger.debug('Retrying request with refreshed token');\n return await this.client<T>(url, options);\n }\n\n // Handle network errors\n if (error.name === 'FetchError' || error.code === 'ECONNREFUSED') {\n throw new NetworkError('Failed to connect to Bragduck API', {\n originalError: error.message,\n baseURL: this.baseURL,\n });\n }\n\n throw error;\n }\n }\n\n /**\n * Refine commits using AI\n */\n async refineCommits(request: RefineCommitsRequest): Promise<RefineCommitsResponse> {\n logger.debug(`Refining ${request.commits.length} commits`);\n\n try {\n const response = await this.makeRequest<RefineCommitsResponse>(\n API_ENDPOINTS.COMMITS.REFINE,\n {\n method: 'POST',\n body: request,\n }\n );\n\n logger.debug(`Successfully refined ${response.refined_commits.length} commits`);\n return response;\n } catch (_error) {\n logger.debug('Failed to refine commits');\n throw _error;\n }\n }\n\n /**\n * Create brags from refined commits\n */\n async createBrags(request: CreateBragsRequest): Promise<CreateBragsResponse> {\n logger.debug(`Creating ${request.brags.length} brags`);\n\n try {\n const response = await this.makeRequest<CreateBragsResponse>(\n API_ENDPOINTS.BRAGS.CREATE,\n {\n method: 'POST',\n body: request,\n }\n );\n\n logger.debug(`Successfully created ${response.created} brags`);\n return response;\n } catch (_error) {\n logger.debug('Failed to create brags');\n throw _error;\n }\n }\n\n /**\n * List existing brags\n */\n async listBrags(params: ListBragsParams = {}): Promise<ListBragsResponse> {\n const { limit = 50, offset = 0, tags, search } = params;\n\n logger.debug(`Listing brags: limit=${limit}, offset=${offset}`);\n\n try {\n // Build query parameters\n const queryParams = new URLSearchParams({\n limit: limit.toString(),\n offset: offset.toString(),\n });\n\n if (search) {\n queryParams.append('search', search);\n }\n\n if (tags && tags.length > 0) {\n tags.forEach((tag) => queryParams.append('tags[]', tag));\n }\n\n const url = `${API_ENDPOINTS.BRAGS.LIST}?${queryParams.toString()}`;\n\n const response = await this.makeRequest<ListBragsResponse>(url, {\n method: 'GET',\n });\n\n logger.debug(`Successfully fetched ${response.brags.length} brags (total: ${response.total})`);\n return response;\n } catch (_error) {\n logger.debug('Failed to list brags');\n throw _error;\n }\n }\n\n /**\n * Check for CLI updates\n */\n async checkVersion(): Promise<VersionCheckResponse> {\n logger.debug('Checking for CLI updates');\n\n try {\n const response = await this.makeRequest<VersionCheckResponse>(\n API_ENDPOINTS.VERSION,\n {\n method: 'GET',\n }\n );\n\n logger.debug(`Latest version: ${response.latest_version}`);\n return response;\n } catch {\n logger.debug('Failed to check version');\n // Don't throw error for version check failures\n // Return current version as fallback\n const { version } = await import('../utils/version.js');\n return {\n latest_version: version,\n critical_update: false,\n };\n }\n }\n\n /**\n * Test API connectivity\n */\n async testConnection(): Promise<boolean> {\n try {\n await this.checkVersion();\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Update base URL\n */\n setBaseURL(url: string): void {\n this.baseURL = url;\n // Recreate client with new base URL\n this.client = ofetch.create({\n baseURL: url,\n });\n }\n\n /**\n * Get current base URL\n */\n getBaseURL(): string {\n return this.baseURL;\n }\n}\n\n// Export singleton instance\nexport const apiService = new ApiService();\n","import { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport chalk from 'chalk';\nimport boxen from 'boxen';\nimport { apiService } from '../services/api.service.js';\nimport { storageService } from '../services/storage.service.js';\nimport { logger } from './logger.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Get current CLI version from package.json\n */\nexport function getCurrentVersion(): string {\n try {\n // In production (dist/utils/version.js), package.json is 2 levels up\n const packageJsonPath = join(__dirname, '../../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n return packageJson.version;\n } catch {\n logger.debug('Failed to read package.json version');\n return '1.0.0'; // Fallback version\n }\n}\n\n/**\n * Export current version\n */\nexport const version = getCurrentVersion();\n\n/**\n * Compare two semantic versions\n * Returns:\n * 1 if v1 > v2\n * 0 if v1 === v2\n * -1 if v1 < v2\n */\nexport function compareVersions(v1: string, v2: string): number {\n const parts1 = v1.split('.').map((p) => parseInt(p, 10));\n const parts2 = v2.split('.').map((p) => parseInt(p, 10));\n\n for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {\n const part1 = parts1[i] || 0;\n const part2 = parts2[i] || 0;\n\n if (part1 > part2) return 1;\n if (part1 < part2) return -1;\n }\n\n return 0;\n}\n\n/**\n * Check if a newer version is available\n */\nexport async function checkForUpdates(options: {\n silent?: boolean;\n force?: boolean;\n} = {}): Promise<{ updateAvailable: boolean; latestVersion: string; currentVersion: string }> {\n const { silent = false, force = false } = options;\n\n try {\n // Skip version check if disabled in config (unless forced)\n if (!force) {\n const autoVersionCheck = storageService.getConfig('autoVersionCheck');\n if (!autoVersionCheck) {\n logger.debug('Version check disabled in config');\n return {\n updateAvailable: false,\n latestVersion: version,\n currentVersion: version,\n };\n }\n }\n\n logger.debug('Checking for CLI updates...');\n\n // Check via API service\n const response = await apiService.checkVersion();\n const latestVersion = response.latest_version;\n const currentVersion = version;\n\n logger.debug(`Current version: ${currentVersion}, Latest version: ${latestVersion}`);\n\n const updateAvailable = compareVersions(latestVersion, currentVersion) > 0;\n\n // Display update notification if not silent and update is available\n if (!silent && updateAvailable) {\n displayUpdateNotification(currentVersion, latestVersion, response.critical_update);\n }\n\n return {\n updateAvailable,\n latestVersion,\n currentVersion,\n };\n } catch (error: any) {\n logger.debug(`Version check failed: ${error.message}`);\n // Don't throw error - version check is non-critical\n return {\n updateAvailable: false,\n latestVersion: version,\n currentVersion: version,\n };\n }\n}\n\n/**\n * Display update notification\n */\nfunction displayUpdateNotification(\n currentVersion: string,\n latestVersion: string,\n critical: boolean = false\n): void {\n const urgency = critical ? chalk.red.bold('CRITICAL UPDATE') : chalk.yellow.bold('Update Available');\n const message =\n `${urgency}\\n\\n` +\n `Current version: ${chalk.dim(currentVersion)}\\n` +\n `Latest version: ${chalk.green(latestVersion)}\\n\\n` +\n `Update with: ${chalk.cyan('npm install -g @bragduck/cli@latest')}`;\n\n console.log('');\n console.log(\n boxen(message, {\n padding: 1,\n margin: { top: 0, right: 1, bottom: 0, left: 1 },\n borderStyle: 'round',\n borderColor: critical ? 'red' : 'yellow',\n })\n );\n console.log('');\n\n if (critical) {\n logger.warning('This is a critical update. Please update as soon as possible.');\n console.log('');\n }\n}\n\n/**\n * Format version for display\n */\nexport function formatVersion(includePrefix: boolean = true): string {\n const prefix = includePrefix ? 'v' : '';\n return `${prefix}${version}`;\n}\n","// Main entry point for the Bragduck CLI package\n// This file exports the public API for programmatic usage\n\nexport { version } from './utils/version.js';\n\n// Future exports will be added here as we implement services and utilities\n// Example:\n// export { AuthService } from './services/auth.service.js';\n// export { GitService } from './services/git.service.js';\n// export { ApiService } from './services/api.service.js';\n"],"mappings":"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","names":["fileURLToPath","join","randomBytes","readFileSync","fileURLToPath","dirname","join","__dirname","version","__filename","ofetch","readFileSync","fileURLToPath","URLSearchParams","dirname","join","__dirname","__filename","version","readFileSync","fileURLToPath","dirname","join","chalk","__dirname","__filename"]}
|