@bragduck/cli 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/bragduck.js +1 -1
- package/dist/bin/bragduck.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/bragduck.js
CHANGED
|
@@ -1861,7 +1861,7 @@ Please run ${chalk7.cyan("bragduck init")} to login first.`,
|
|
|
1861
1861
|
author: c.author,
|
|
1862
1862
|
date: c.date,
|
|
1863
1863
|
diff_stats: c.diffStats ? {
|
|
1864
|
-
|
|
1864
|
+
files_changed: c.diffStats.filesChanged,
|
|
1865
1865
|
insertions: c.diffStats.insertions,
|
|
1866
1866
|
deletions: c.diffStats.deletions
|
|
1867
1867
|
} : void 0
|
package/dist/bin/bragduck.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/utils/version.ts","../../src/services/api.service.ts","../../src/cli.ts","../../src/commands/init.ts","../../src/commands/logout.ts","../../src/commands/scan.ts","../../src/services/git.service.ts","../../src/utils/validators.ts","../../src/ui/prompts.ts","../../src/ui/formatters.ts","../../src/ui/spinners.ts","../../src/commands/list.ts","../../src/commands/config.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 API_BASE_URL: 'apiBaseUrl',\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 apiBaseUrl: process.env.API_BASE_URL || 'https://api.bragduck.com',\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","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","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 { 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, OAuthError, NetworkError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type { StoredCredentials, UserInfo } from '../types/config.types.js';\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 // Prioritize environment variable, fallback to default API URL\n this.apiBaseUrl =\n process.env.API_BASE_URL ||\n storageService.getConfig('apiBaseUrl') ||\n '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 },\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 },\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 { 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","import { ofetch, type FetchOptions } from 'ofetch';\nimport { storageService } from './storage.service.js';\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\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 // Prioritize environment variable over stored config\n this.baseURL = process.env.API_BASE_URL || storageService.getConfig('apiBaseUrl');\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.baseURL}${options.url}`);\n\n // Add authentication header\n const token = await authService.getAccessToken();\n if (token) {\n options.headers = {\n ...options.headers,\n Authorization: `Bearer ${token}`,\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 = {\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.baseURL}${options.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 (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 storageService.setConfig('apiBaseUrl', 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 { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { initCommand } from './commands/init.js';\nimport { logoutCommand } from './commands/logout.js';\nimport { scanCommand } from './commands/scan.js';\nimport { listCommand } from './commands/list.js';\nimport { configCommand } from './commands/config.js';\nimport { checkForUpdates } from './utils/version.js';\nimport { logger } from './utils/logger.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Read package.json for version (go up two levels from dist/bin/)\nconst packageJsonPath = join(__dirname, '../../package.json');\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n\nconst program = new Command();\n\nprogram\n .name('bragduck')\n .description('CLI tool for managing developer achievements and brags')\n .version(packageJson.version, '-v, --version', 'Display version number')\n .helpOption('-h, --help', 'Display help information')\n .option('--skip-version-check', 'Skip automatic version check on startup')\n .option('--debug', 'Enable debug mode (shows detailed logs)');\n\n// Init command - OAuth authentication\nprogram\n .command('init')\n .description('Authenticate with Bragduck')\n .action(async () => {\n try {\n await initCommand();\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// Scan command - Interactive commit selection and brag creation\nprogram\n .command('scan')\n .description('Scan git commits and create brags')\n .option('-d, --days <number>', 'Number of days to scan', (val) => parseInt(val, 10))\n .option('-a, --all', 'Include all commits (not just current user)')\n .action(async (options) => {\n try {\n await scanCommand(options);\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// List command - Display existing brags\nprogram\n .command('list')\n .description('List your existing brags')\n .option('-l, --limit <number>', 'Number of brags to display', (val) => parseInt(val, 10), 50)\n .option('-o, --offset <number>', 'Number of brags to skip', (val) => parseInt(val, 10), 0)\n .option('-t, --tags <tags>', 'Filter by tags (comma-separated)')\n .option('-s, --search <query>', 'Search brags by keyword')\n .action(async (options) => {\n try {\n await listCommand(options);\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// Logout command - Clear credentials\nprogram\n .command('logout')\n .description('Clear stored credentials')\n .action(async () => {\n try {\n await logoutCommand();\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// Config command - Manage CLI configuration\nprogram\n .command('config [subcommand] [key] [value]')\n .description('Manage CLI configuration (subcommands: list, get, set)')\n .action(async (subcommand, key, value) => {\n try {\n await configCommand(subcommand, key, value);\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// Hook to run before any command execution\nprogram.hook('preAction', async (_thisCommand) => {\n const options = program.opts();\n\n // Enable debug mode if --debug flag is set\n if (options.debug) {\n process.env.DEBUG = 'true';\n logger.debug('Debug mode enabled');\n }\n\n // Check for updates (unless --skip-version-check is set or --version/--help is used)\n const isVersionOrHelp = process.argv.includes('--version') ||\n process.argv.includes('-v') ||\n process.argv.includes('--help') ||\n process.argv.includes('-h');\n\n if (!options.skipVersionCheck && !isVersionOrHelp) {\n try {\n await checkForUpdates({ silent: false });\n } catch (error) {\n // Non-critical, continue execution\n logger.debug('Version check failed, continuing...');\n }\n }\n});\n\n// Parse command line arguments\nprogram.parse(process.argv);\n\n// Show help if no command is provided\nif (!process.argv.slice(2).length) {\n program.outputHelp();\n}\n","import ora from 'ora';\nimport boxen from 'boxen';\nimport chalk from 'chalk';\nimport { authService } from '../services/auth.service.js';\nimport { logger } from '../utils/logger.js';\nimport type { BragduckError } from '../utils/errors.js';\n\n/**\n * Init command: Authenticate with Bragduck\n */\nexport async function initCommand(): Promise<void> {\n logger.log('');\n logger.info('Starting authentication flow...');\n logger.log('');\n\n // Check if already authenticated\n const isAuthenticated = await authService.isAuthenticated();\n if (isAuthenticated) {\n const userInfo = authService.getUserInfo();\n if (userInfo) {\n logger.log(\n boxen(\n `${chalk.yellow('Already authenticated!')}\\n\\n` +\n `${chalk.gray('User:')} ${userInfo.name}\\n` +\n `${chalk.gray('Email:')} ${userInfo.email}\\n\\n` +\n `${chalk.dim('Run')} ${chalk.cyan('bragduck logout')} ${chalk.dim('to sign out')}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'yellow',\n }\n )\n );\n logger.log('');\n setTimeout(() => {\n process.exit(0);\n }, 100);\n return;\n }\n }\n\n const spinner = ora('Opening browser for authentication...').start();\n\n try {\n // Start OAuth flow\n spinner.text = 'Waiting for authentication...';\n const userInfo = await authService.login();\n\n spinner.succeed('Authentication successful!');\n logger.log('');\n\n // Show success message\n logger.log(\n boxen(\n `${chalk.green.bold('✓ Successfully authenticated!')}\\n\\n` +\n `${chalk.gray('Welcome,')} ${chalk.cyan(userInfo.name)}\\n` +\n `${chalk.gray('Email:')} ${userInfo.email}\\n\\n` +\n `${chalk.dim('You can now use')} ${chalk.cyan('bragduck scan')} ${chalk.dim('to create brags!')}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'green',\n }\n )\n );\n logger.log('');\n\n // Exit successfully - force immediate exit\n // Use setTimeout to ensure all logs are flushed\n setTimeout(() => {\n process.exit(0);\n }, 100);\n\n // Return to prevent further execution\n return;\n } catch (error) {\n spinner.fail('Authentication failed');\n logger.log('');\n\n const err = error as BragduckError;\n\n // Show error message\n logger.log(\n boxen(\n `${chalk.red.bold('✗ Authentication Failed')}\\n\\n` +\n `${err.message}\\n\\n` +\n `${chalk.dim('Hint:')} ${getErrorHint(err)}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'red',\n }\n )\n );\n\n process.exit(1);\n }\n}\n\n/**\n * Get helpful hint based on error type\n */\nfunction getErrorHint(error: BragduckError): string {\n if (error.name === 'OAuthError') {\n if (error.message.includes('timeout')) {\n return 'Try again and complete the authentication within 2 minutes';\n }\n if (error.message.includes('CSRF')) {\n return 'This might be a security issue. Try running the command again';\n }\n return 'Check your internet connection and try again';\n }\n\n if (error.name === 'NetworkError') {\n return 'Check your internet connection and firewall settings';\n }\n\n if (error.name === 'AuthenticationError') {\n return 'Verify your credentials and try again';\n }\n\n return 'Try running the command again or check the logs with DEBUG=* bragduck init';\n}\n","import { confirm } from '@inquirer/prompts';\nimport boxen from 'boxen';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { authService } from '../services/auth.service.js';\nimport { logger } from '../utils/logger.js';\n\n/**\n * Logout command: Clear stored credentials\n */\nexport async function logoutCommand(): Promise<void> {\n // Check if user is authenticated\n const isAuthenticated = await authService.isAuthenticated();\n\n if (!isAuthenticated) {\n logger.log(\n boxen(`${chalk.yellow('Not currently authenticated')}\\n\\n${chalk.dim('Nothing to logout from')}`, {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'yellow',\n })\n );\n return;\n }\n\n // Get user info to show in confirmation\n const userInfo = authService.getUserInfo();\n const userName = userInfo?.name || 'Unknown User';\n\n logger.log('');\n\n // Confirm logout\n const shouldLogout = await confirm({\n message: `Are you sure you want to logout? (${chalk.cyan(userName)})`,\n default: false,\n });\n\n if (!shouldLogout) {\n logger.info('Logout cancelled');\n return;\n }\n\n const spinner = ora('Logging out...').start();\n\n try {\n await authService.logout();\n spinner.succeed('Logged out successfully');\n logger.log('');\n\n logger.log(\n boxen(\n `${chalk.green.bold('✓ Logged out successfully')}\\n\\n` +\n `${chalk.dim('Your credentials have been cleared')}\\n\\n` +\n `${chalk.dim('Run')} ${chalk.cyan('bragduck init')} ${chalk.dim('to login again')}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'green',\n }\n )\n );\n } catch (error) {\n spinner.fail('Logout failed');\n logger.error('Failed to logout. Please try again.');\n process.exit(1);\n }\n}\n","import boxen from 'boxen';\nimport chalk from 'chalk';\nimport { gitService } from '../services/git.service.js';\nimport { apiService } from '../services/api.service.js';\nimport { authService } from '../services/auth.service.js';\nimport { storageService } from '../services/storage.service.js';\nimport { logger } from '../utils/logger.js';\nimport type { BragduckError } from '../utils/errors.js';\nimport {\n promptSelectCommits,\n promptConfirm,\n promptDaysToScan,\n} from '../ui/prompts.js';\nimport {\n fetchingCommitsSpinner,\n refiningCommitsSpinner,\n creatingBragsSpinner,\n succeedSpinner,\n failSpinner,\n} from '../ui/spinners.js';\nimport {\n formatRefinedCommitsTable,\n formatSuccessMessage,\n formatErrorMessage,\n formatCommitStats,\n} from '../ui/formatters.js';\nimport type { GitCommit } from '../types/git.types.js';\nimport type { RefinedCommit, CreateBragItem } from '../types/api.types.js';\n\n/**\n * Scan command options\n */\nexport interface ScanCommandOptions {\n days?: number;\n all?: boolean; // Include all commits, not just current user's\n}\n\n/**\n * Scan command: Scan git commits and create brags\n */\nexport async function scanCommand(options: ScanCommandOptions = {}): Promise<void> {\n logger.log('');\n\n try {\n // 1. Check authentication\n const isAuthenticated = await authService.isAuthenticated();\n if (!isAuthenticated) {\n logger.log(\n boxen(\n `${chalk.yellow.bold('⚠ Not authenticated')}\\n\\n` +\n `Please run ${chalk.cyan('bragduck init')} to login first.`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'yellow',\n }\n )\n );\n process.exit(1);\n }\n\n // 2. Validate git repository\n await gitService.validateRepository();\n const repoInfo = await gitService.getRepositoryInfo();\n\n logger.info(`Repository: ${chalk.cyan(repoInfo.currentBranch)} branch`);\n logger.log('');\n\n // 3. Prompt for days to scan (if not provided)\n let days = options.days;\n if (!days) {\n const defaultDays = storageService.getConfig('defaultCommitDays');\n days = await promptDaysToScan(defaultDays);\n logger.log('');\n }\n\n // 4. Fetch commits\n const spinner = fetchingCommitsSpinner(days);\n spinner.start();\n\n let commits: GitCommit[];\n if (options.all) {\n commits = await gitService.getCommitsWithStats({ days });\n } else {\n commits = await gitService.getCommitsByCurrentUser({ days });\n }\n\n if (commits.length === 0) {\n failSpinner(spinner, `No commits found in the last ${days} days`);\n logger.log('');\n logger.info('Try increasing the number of days or check your git configuration');\n return;\n }\n\n succeedSpinner(spinner, `Found ${commits.length} commit${commits.length > 1 ? 's' : ''}`);\n logger.log('');\n\n // Show commit statistics\n logger.log(formatCommitStats(commits));\n logger.log('');\n\n // 5. Interactive commit selection\n const selectedShas = await promptSelectCommits(commits);\n\n if (selectedShas.length === 0) {\n logger.warning('No commits selected');\n return;\n }\n\n const selectedCommits = commits.filter((c) => selectedShas.includes(c.sha));\n logger.log('');\n logger.success(`Selected ${selectedCommits.length} commit${selectedCommits.length > 1 ? 's' : ''}`);\n logger.log('');\n\n // 6. Refine commits with AI\n const refineSpinner = refiningCommitsSpinner(selectedCommits.length);\n refineSpinner.start();\n\n const refineRequest = {\n commits: selectedCommits.map((c) => ({\n sha: c.sha,\n message: c.message,\n author: c.author,\n date: c.date,\n diff_stats: c.diffStats\n ? {\n filesChanged: c.diffStats.filesChanged,\n insertions: c.diffStats.insertions,\n deletions: c.diffStats.deletions,\n }\n : undefined,\n })),\n };\n\n const refineResponse = await apiService.refineCommits(refineRequest);\n const refinedCommits = refineResponse.refined_commits;\n\n succeedSpinner(refineSpinner, 'Commits refined successfully');\n logger.log('');\n\n // 7. Show preview\n logger.info('Preview of refined brags:');\n logger.log('');\n logger.log(formatRefinedCommitsTable(refinedCommits));\n logger.log('');\n\n // 8. Confirm creation\n const shouldCreate = await promptConfirm('Create these brags?', true);\n\n if (!shouldCreate) {\n logger.warning('Cancelled');\n return;\n }\n\n logger.log('');\n\n // 9. Create brags\n const createSpinner = creatingBragsSpinner(refinedCommits.length);\n createSpinner.start();\n\n const createRequest = {\n brags: refinedCommits.map((refined): CreateBragItem => {\n const originalCommit = selectedCommits.find((c) => c.sha === refined.sha);\n return {\n commit_sha: refined.sha,\n title: refined.refined_title,\n description: refined.refined_description,\n tags: refined.suggested_tags,\n repository: repoInfo.remoteUrl,\n date: originalCommit?.date || new Date().toISOString(),\n };\n }),\n };\n\n const createResponse = await apiService.createBrags(createRequest);\n\n succeedSpinner(createSpinner, `Created ${createResponse.created} brags`);\n logger.log('');\n\n // 10. Show success message\n logger.log(\n boxen(formatSuccessMessage(createResponse.created), {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'green',\n })\n );\n } catch (error) {\n const err = error as BragduckError;\n\n logger.log('');\n logger.log(\n boxen(formatErrorMessage(err.message, getErrorHint(err)), {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'red',\n })\n );\n\n process.exit(1);\n }\n}\n\n/**\n * Get helpful hint based on error type\n */\nfunction getErrorHint(error: BragduckError): string {\n if (error.name === 'GitError') {\n return 'Make sure you are in a git repository with commits';\n }\n\n if (error.name === 'TokenExpiredError' || error.name === 'AuthenticationError') {\n return 'Run \"bragduck init\" to login again';\n }\n\n if (error.name === 'NetworkError') {\n return 'Check your internet connection and try again';\n }\n\n if (error.name === 'ApiError') {\n return 'The server might be experiencing issues. Try again later';\n }\n\n return 'Try running with DEBUG=* for more information';\n}\n","import simpleGit, { SimpleGit, LogResult, DefaultLogFields } from 'simple-git';\nimport { validateGitRepository } from '../utils/validators.js';\nimport { GitError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type {\n GitCommit,\n DiffStats,\n FetchCommitsOptions,\n GitRepositoryInfo,\n} from '../types/git.types.js';\n\n/**\n * Git service for interacting with git repositories\n */\nexport class GitService {\n private git: SimpleGit;\n private repoPath: string;\n\n constructor(repoPath: string = process.cwd()) {\n this.repoPath = repoPath;\n this.git = simpleGit(repoPath);\n }\n\n /**\n * Validate that the current directory is a git repository\n */\n async validateRepository(): Promise<void> {\n try {\n validateGitRepository(this.repoPath);\n const isRepo = await this.git.checkIsRepo();\n\n if (!isRepo) {\n throw new GitError('Not a valid git repository', {\n path: this.repoPath,\n });\n }\n } catch (error: any) {\n if (error instanceof GitError) {\n throw error;\n }\n throw new GitError('Failed to validate git repository', {\n originalError: error.message,\n path: this.repoPath,\n });\n }\n }\n\n /**\n * Get repository information\n */\n async getRepositoryInfo(): Promise<GitRepositoryInfo> {\n try {\n await this.validateRepository();\n\n const status = await this.git.status();\n const remotes = await this.git.getRemotes(true);\n const primaryRemote = remotes.find((r) => r.name === 'origin');\n\n return {\n path: this.repoPath,\n currentBranch: status.current || 'unknown',\n remoteUrl: primaryRemote?.refs?.fetch || primaryRemote?.refs?.push,\n isClean: status.isClean(),\n };\n } catch (error: any) {\n if (error instanceof GitError) {\n throw error;\n }\n throw new GitError('Failed to get repository information', {\n originalError: error.message,\n });\n }\n }\n\n /**\n * Fetch recent commits\n */\n async getRecentCommits(options: FetchCommitsOptions = {}): Promise<GitCommit[]> {\n const { days = 30, limit, author, branch } = options;\n\n try {\n await this.validateRepository();\n\n logger.debug(`Fetching commits from last ${days} days`);\n\n // Calculate date for filtering\n const since = new Date();\n since.setDate(since.getDate() - days);\n\n // Build log options\n const logOptions: any = {\n '--since': since.toISOString(),\n '--no-merges': null,\n };\n\n if (limit) {\n logOptions.maxCount = limit;\n }\n\n if (author) {\n logOptions['--author'] = author;\n }\n\n // Fetch commits\n const log: LogResult<DefaultLogFields> = await this.git.log(logOptions);\n\n logger.debug(`Found ${log.all.length} commits`);\n\n // Convert to our GitCommit format\n const commits: GitCommit[] = log.all.map((commit) => ({\n sha: commit.hash,\n message: commit.message,\n author: commit.author_name,\n authorEmail: commit.author_email,\n date: commit.date,\n }));\n\n return commits;\n } catch (error: any) {\n if (error instanceof GitError) {\n throw error;\n }\n throw new GitError('Failed to fetch commits', {\n originalError: error.message,\n days,\n });\n }\n }\n\n /**\n * Get diff statistics for a specific commit\n */\n async getCommitStats(sha: string): Promise<DiffStats> {\n try {\n logger.debug(`Getting stats for commit ${sha}`);\n\n // Get diff summary for the commit\n const diffSummary = await this.git.diffSummary([`${sha}^`, sha]);\n\n const stats: DiffStats = {\n filesChanged: diffSummary.files.length,\n insertions: diffSummary.insertions,\n deletions: diffSummary.deletions,\n };\n\n logger.debug(`Commit ${sha}: ${stats.filesChanged} files, +${stats.insertions} -${stats.deletions}`);\n\n return stats;\n } catch (error: any) {\n // If this is the first commit, there's no parent to diff against\n if (error.message && error.message.includes('unknown revision')) {\n logger.debug(`Commit ${sha} has no parent (first commit)`);\n // Try to get stats for first commit\n try {\n const diffSummary = await this.git.diffSummary([sha]);\n return {\n filesChanged: diffSummary.files.length,\n insertions: diffSummary.insertions,\n deletions: diffSummary.deletions,\n };\n } catch {\n // Return zeros if we can't get stats\n return {\n filesChanged: 0,\n insertions: 0,\n deletions: 0,\n };\n }\n }\n\n throw new GitError('Failed to get commit statistics', {\n originalError: error.message,\n sha,\n });\n }\n }\n\n /**\n * Get commits with their diff statistics\n */\n async getCommitsWithStats(options: FetchCommitsOptions = {}): Promise<GitCommit[]> {\n const commits = await this.getRecentCommits(options);\n\n logger.debug(`Fetching diff stats for ${commits.length} commits`);\n\n // Fetch stats for each commit in parallel\n const commitsWithStats = await Promise.all(\n commits.map(async (commit) => {\n try {\n const stats = await this.getCommitStats(commit.sha);\n return {\n ...commit,\n diffStats: stats,\n };\n } catch (error) {\n logger.debug(`Failed to get stats for commit ${commit.sha}, continuing without stats`);\n return commit;\n }\n })\n );\n\n return commitsWithStats;\n }\n\n /**\n * Get the current git user email\n */\n async getCurrentUserEmail(): Promise<string | null> {\n try {\n const email = await this.git.raw(['config', 'user.email']);\n return email.trim() || null;\n } catch (error) {\n logger.debug('Failed to get git user email');\n return null;\n }\n }\n\n /**\n * Get the current git user name\n */\n async getCurrentUserName(): Promise<string | null> {\n try {\n const name = await this.git.raw(['config', 'user.name']);\n return name.trim() || null;\n } catch (error) {\n logger.debug('Failed to get git user name');\n return null;\n }\n }\n\n /**\n * Filter commits by current user\n */\n async getCommitsByCurrentUser(options: FetchCommitsOptions = {}): Promise<GitCommit[]> {\n const userEmail = await this.getCurrentUserEmail();\n\n if (!userEmail) {\n logger.warning('Could not determine git user email, returning all commits');\n return this.getCommitsWithStats(options);\n }\n\n logger.debug(`Filtering commits by user: ${userEmail}`);\n\n return this.getCommitsWithStats({\n ...options,\n author: userEmail,\n });\n }\n}\n\n// Export singleton instance for the current working directory\nexport const gitService = new GitService();\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport { GitError, ValidationError } from './errors.js';\n\n/**\n * Validate that a directory is a git repository\n */\nexport function validateGitRepository(path: string): void {\n const gitDir = join(path, '.git');\n\n if (!existsSync(gitDir)) {\n throw new GitError(\n 'Not a git repository. Please run this command from within a git repository.',\n {\n path,\n hint: 'Run \"git init\" to initialize a git repository, or navigate to an existing one',\n }\n );\n }\n}\n\n/**\n * Validate email format\n */\nexport function validateEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n}\n\n/**\n * Validate that a value is not empty\n */\nexport function validateNotEmpty(value: string, fieldName: string): void {\n if (!value || value.trim().length === 0) {\n throw new ValidationError(`${fieldName} cannot be empty`);\n }\n}\n\n/**\n * Validate date is in valid format\n */\nexport function validateDate(dateString: string): boolean {\n const date = new Date(dateString);\n return !isNaN(date.getTime());\n}\n\n/**\n * Validate number is positive\n */\nexport function validatePositiveNumber(value: number, fieldName: string): void {\n if (value <= 0) {\n throw new ValidationError(`${fieldName} must be a positive number`);\n }\n}\n\n/**\n * Validate commit SHA format (40 character hex string)\n */\nexport function validateCommitSha(sha: string): boolean {\n const shaRegex = /^[a-f0-9]{40}$/i;\n return shaRegex.test(sha);\n}\n","import { checkbox, confirm, input, select } from '@inquirer/prompts';\nimport type { GitCommit } from '../types/git.types.js';\nimport { formatCommitChoice } from './formatters.js';\n\n/**\n * Prompt user to select commits\n */\nexport async function promptSelectCommits(commits: GitCommit[]): Promise<string[]> {\n if (commits.length === 0) {\n return [];\n }\n\n const choices = commits.map((commit) => ({\n name: formatCommitChoice(commit),\n value: commit.sha,\n checked: false,\n }));\n\n const selected = await checkbox({\n message: 'Select commits to brag about (use space to select, enter to confirm):',\n choices,\n pageSize: 10,\n loop: false,\n });\n\n return selected;\n}\n\n/**\n * Prompt user to confirm action\n */\nexport async function promptConfirm(\n message: string,\n defaultValue: boolean = true\n): Promise<boolean> {\n return await confirm({\n message,\n default: defaultValue,\n });\n}\n\n/**\n * Prompt user for text input\n */\nexport async function promptInput(message: string, defaultValue?: string): Promise<string> {\n return await input({\n message,\n default: defaultValue,\n });\n}\n\n/**\n * Prompt user to select from options\n */\nexport async function promptSelect<T extends string>(\n message: string,\n choices: Array<{ name: string; value: T; description?: string }>\n): Promise<T> {\n return await select({\n message,\n choices,\n });\n}\n\n/**\n * Prompt for number of days to scan\n */\nexport async function promptDaysToScan(defaultDays: number = 30): Promise<number> {\n const choices = [\n { name: '7 days', value: '7', description: 'Last week' },\n { name: '30 days (Recommended)', value: '30', description: 'Last month' },\n { name: '60 days', value: '60', description: 'Last 2 months' },\n { name: '90 days', value: '90', description: 'Last 3 months' },\n { name: 'Custom', value: 'custom', description: 'Enter custom number of days' },\n ];\n\n const selected = await select({\n message: 'How many days back should we scan for commits?',\n choices,\n default: '30',\n });\n\n if (selected === 'custom') {\n const customDays = await input({\n message: 'Enter number of days:',\n default: defaultDays.toString(),\n validate: (value) => {\n const num = parseInt(value, 10);\n if (isNaN(num) || num <= 0) {\n return 'Please enter a valid positive number';\n }\n return true;\n },\n });\n return parseInt(customDays, 10);\n }\n\n return parseInt(selected, 10);\n}\n","import chalk from 'chalk';\nimport Table from 'cli-table3';\nimport type { GitCommit } from '../types/git.types.js';\nimport type { RefinedCommit } from '../types/api.types.js';\n\n/**\n * Format a commit for display in checkbox list\n */\nexport function formatCommitChoice(commit: GitCommit): string {\n const sha = chalk.yellow(commit.sha.substring(0, 7));\n const message = commit.message.split('\\n')[0]; // First line only\n const author = chalk.gray(`by ${commit.author}`);\n const date = chalk.gray(new Date(commit.date).toLocaleDateString());\n\n let stats = '';\n if (commit.diffStats) {\n const { filesChanged, insertions, deletions } = commit.diffStats;\n stats = chalk.gray(\n ` [${filesChanged} files, ${chalk.green(`+${insertions}`)} ${chalk.red(`-${deletions}`)}]`\n );\n }\n\n return `${sha} ${message}${stats}\\n ${author} • ${date}`;\n}\n\n/**\n * Format refined commits as a preview table\n */\nexport function formatRefinedCommitsTable(commits: RefinedCommit[]): string {\n const table = new Table({\n head: [\n chalk.cyan('SHA'),\n chalk.cyan('Original'),\n chalk.cyan('Refined Title'),\n chalk.cyan('Description'),\n chalk.cyan('Tags'),\n ],\n colWidths: [10, 30, 30, 40, 20],\n wordWrap: true,\n style: {\n head: [],\n border: ['gray'],\n },\n });\n\n commits.forEach((commit) => {\n const sha = commit.sha.substring(0, 7);\n const original = commit.original_message.split('\\n')[0] || '';\n const title = commit.refined_title;\n const description = commit.refined_description.substring(0, 100) + '...';\n const tags = (commit.suggested_tags || []).join(', ') || 'none';\n\n table.push([\n chalk.yellow(sha),\n chalk.gray(original),\n chalk.white(title),\n chalk.dim(description),\n chalk.blue(tags),\n ]);\n });\n\n return table.toString();\n}\n\n/**\n * Format commit statistics\n */\nexport function formatCommitStats(commits: GitCommit[]): string {\n const totalFiles = commits.reduce((sum, c) => sum + (c.diffStats?.filesChanged || 0), 0);\n const totalInsertions = commits.reduce((sum, c) => sum + (c.diffStats?.insertions || 0), 0);\n const totalDeletions = commits.reduce((sum, c) => sum + (c.diffStats?.deletions || 0), 0);\n\n return (\n chalk.gray('Total changes: ') +\n chalk.white(`${totalFiles} files`) +\n chalk.gray(', ') +\n chalk.green(`+${totalInsertions}`) +\n chalk.gray(' ') +\n chalk.red(`-${totalDeletions}`)\n );\n}\n\n/**\n * Format success message for created brags\n */\nexport function formatSuccessMessage(count: number): string {\n const emoji = '🎉';\n const title = chalk.green.bold(`${emoji} Successfully created ${count} brag${count > 1 ? 's' : ''}!`);\n const message = chalk.white('\\nYour achievements are now saved and ready to showcase.');\n const hint = chalk.dim('\\nRun ') + chalk.cyan('bragduck list') + chalk.dim(' to see all your brags');\n\n return `${title}${message}${hint}`;\n}\n\n/**\n * Format error message for display\n */\nexport function formatErrorMessage(message: string, hint?: string): string {\n const title = chalk.red.bold('✗ Error');\n const error = chalk.white(message);\n const hintText = hint ? chalk.dim('\\n\\nHint: ') + chalk.cyan(hint) : '';\n\n return `${title}\\n\\n${error}${hintText}`;\n}\n\n/**\n * Format progress message\n */\nexport function formatProgress(current: number, total: number, label: string): string {\n const percentage = Math.round((current / total) * 100);\n const bar = '█'.repeat(Math.floor(percentage / 5)) + '░'.repeat(20 - Math.floor(percentage / 5));\n\n return `${chalk.cyan(bar)} ${chalk.white(`${percentage}%`)} ${chalk.gray(label)}`;\n}\n","import ora, { Ora } from 'ora';\nimport chalk from 'chalk';\n\n/**\n * Create a spinner with consistent styling\n */\nexport function createSpinner(text: string): Ora {\n return ora({\n text,\n color: 'cyan',\n spinner: 'dots',\n });\n}\n\n/**\n * Spinner for fetching commits\n */\nexport function fetchingCommitsSpinner(days: number): Ora {\n return createSpinner(`Fetching commits from the last ${days} days...`);\n}\n\n/**\n * Spinner for refining commits\n */\nexport function refiningCommitsSpinner(count: number): Ora {\n return createSpinner(`Refining ${count} commit${count > 1 ? 's' : ''} with AI...`);\n}\n\n/**\n * Spinner for creating brags\n */\nexport function creatingBragsSpinner(count: number): Ora {\n return createSpinner(`Creating ${count} brag${count > 1 ? 's' : ''}...`);\n}\n\n/**\n * Spinner for fetching brags\n */\nexport function fetchingBragsSpinner(): Ora {\n return createSpinner('Fetching your brags...');\n}\n\n/**\n * Update spinner with new text\n */\nexport function updateSpinner(spinner: Ora, text: string): void {\n spinner.text = text;\n}\n\n/**\n * Succeed spinner with custom text\n */\nexport function succeedSpinner(spinner: Ora, text?: string): void {\n if (text) {\n spinner.succeed(chalk.green(text));\n } else {\n spinner.succeed();\n }\n}\n\n/**\n * Fail spinner with custom text\n */\nexport function failSpinner(spinner: Ora, text?: string): void {\n if (text) {\n spinner.fail(chalk.red(text));\n } else {\n spinner.fail();\n }\n}\n\n/**\n * Warn spinner with custom text\n */\nexport function warnSpinner(spinner: Ora, text?: string): void {\n if (text) {\n spinner.warn(chalk.yellow(text));\n } else {\n spinner.warn();\n }\n}\n","import boxen from 'boxen';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { apiService } from '../services/api.service.js';\nimport { authService } from '../services/auth.service.js';\nimport { logger } from '../utils/logger.js';\nimport { formatErrorMessage } from '../ui/formatters.js';\nimport { fetchingBragsSpinner, succeedSpinner, failSpinner } from '../ui/spinners.js';\nimport type { BragduckError } from '../utils/errors.js';\nimport type { Brag } from '../types/api.types.js';\n\n/**\n * List command options\n */\nexport interface ListCommandOptions {\n limit?: number;\n offset?: number;\n tags?: string;\n search?: string;\n}\n\n/**\n * List command: Fetch and display existing brags\n */\nexport async function listCommand(options: ListCommandOptions = {}): Promise<void> {\n logger.log('');\n\n try {\n // 1. Check authentication\n const isAuthenticated = await authService.isAuthenticated();\n if (!isAuthenticated) {\n logger.log(\n boxen(\n `${chalk.yellow.bold('⚠ Not authenticated')}\\n\\n` +\n `Please run ${chalk.cyan('bragduck init')} to login first.`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'yellow',\n }\n )\n );\n process.exit(1);\n }\n\n // 2. Parse options\n const limit = options.limit || 50;\n const offset = options.offset || 0;\n const tags = options.tags ? options.tags.split(',').map((t) => t.trim()) : undefined;\n const search = options.search;\n\n // 3. Fetch brags\n const spinner = fetchingBragsSpinner();\n spinner.start();\n\n const response = await apiService.listBrags({\n limit,\n offset,\n tags,\n search,\n });\n\n if (response.brags.length === 0) {\n failSpinner(spinner, 'No brags found');\n logger.log('');\n\n if (search || tags) {\n logger.info('Try adjusting your filters or run without filters to see all brags');\n } else {\n logger.info(`Run ${chalk.cyan('bragduck scan')} to create your first brag!`);\n }\n return;\n }\n\n succeedSpinner(spinner, `Found ${response.total} brag${response.total > 1 ? 's' : ''}`);\n logger.log('');\n\n // 4. Display brags in table\n logger.log(formatBragsTable(response.brags));\n logger.log('');\n\n // 5. Show pagination info\n if (response.has_more) {\n const nextOffset = offset + limit;\n logger.info(\n `Showing ${offset + 1}-${offset + response.brags.length} of ${response.total} total brags`\n );\n logger.info(\n chalk.dim(`Run `) +\n chalk.cyan(`bragduck list --offset ${nextOffset}`) +\n chalk.dim(` to see more`)\n );\n logger.log('');\n } else if (offset > 0) {\n logger.info(\n `Showing ${offset + 1}-${offset + response.brags.length} of ${response.total} total brags`\n );\n logger.log('');\n }\n\n // 6. Show filter info if filters are applied\n if (search || tags) {\n const filterInfo: string[] = [];\n if (search) filterInfo.push(`search: \"${search}\"`);\n if (tags) filterInfo.push(`tags: ${tags.join(', ')}`);\n logger.info(chalk.dim(`Filters applied: ${filterInfo.join(', ')}`));\n logger.log('');\n }\n } catch (error) {\n const err = error as BragduckError;\n\n logger.log('');\n logger.log(\n boxen(formatErrorMessage(err.message, getErrorHint(err)), {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'red',\n })\n );\n\n process.exit(1);\n }\n}\n\n/**\n * Format brags as a table\n */\nfunction formatBragsTable(brags: Brag[]): string {\n const table = new Table({\n head: [\n chalk.cyan('Date'),\n chalk.cyan('Title'),\n chalk.cyan('Description'),\n chalk.cyan('Tags'),\n chalk.cyan('Repository'),\n ],\n colWidths: [12, 30, 40, 20, 30],\n wordWrap: true,\n style: {\n head: [],\n border: ['gray'],\n },\n });\n\n brags.forEach((brag) => {\n const date = new Date(brag.date).toLocaleDateString();\n const title = brag.title;\n const description = truncateText(brag.description, 100);\n const tags = brag.tags.length > 0 ? brag.tags.join(', ') : chalk.dim('none');\n const repository = brag.repository\n ? truncateText(extractRepoName(brag.repository), 25)\n : chalk.dim('none');\n\n table.push([\n chalk.yellow(date),\n chalk.white(title),\n chalk.dim(description),\n chalk.blue(tags),\n chalk.gray(repository),\n ]);\n });\n\n return table.toString();\n}\n\n/**\n * Truncate text with ellipsis\n */\nfunction truncateText(text: string, maxLength: number): string {\n if (text.length <= maxLength) {\n return text;\n }\n return text.substring(0, maxLength - 3) + '...';\n}\n\n/**\n * Extract repository name from URL\n */\nfunction extractRepoName(url: string): string {\n try {\n // Handle GitHub URLs like: https://github.com/user/repo.git\n const match = url.match(/([^/]+\\/[^/]+?)(\\.git)?$/);\n return match ? match[1] : url;\n } catch {\n return url;\n }\n}\n\n/**\n * Get helpful hint based on error type\n */\nfunction getErrorHint(error: BragduckError): string {\n if (error.name === 'TokenExpiredError' || error.name === 'AuthenticationError') {\n return 'Run \"bragduck init\" to login again';\n }\n\n if (error.name === 'NetworkError') {\n return 'Check your internet connection and try again';\n }\n\n if (error.name === 'ApiError') {\n return 'The server might be experiencing issues. Try again later';\n }\n\n return 'Try running with DEBUG=* for more information';\n}\n","import boxen from 'boxen';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { storageService } from '../services/storage.service.js';\nimport { apiService } from '../services/api.service.js';\nimport { logger } from '../utils/logger.js';\nimport { CONFIG_KEYS, DEFAULT_CONFIG } from '../constants.js';\nimport { formatErrorMessage } from '../ui/formatters.js';\nimport { ValidationError } from '../utils/errors.js';\n\n/**\n * Valid configuration keys\n */\nconst VALID_CONFIG_KEYS = Object.values(CONFIG_KEYS);\n\n/**\n * Config subcommands\n */\ntype ConfigSubcommand = 'list' | 'get' | 'set';\n\n/**\n * Config command: Manage CLI configuration\n */\nexport async function configCommand(\n subcommand?: ConfigSubcommand,\n key?: string,\n value?: string\n): Promise<void> {\n logger.log('');\n\n try {\n // If no subcommand provided, default to 'list'\n if (!subcommand) {\n subcommand = 'list';\n }\n\n switch (subcommand) {\n case 'list':\n await handleListConfig();\n break;\n\n case 'get':\n if (!key) {\n throw new ValidationError('Config key is required for \"get\" command');\n }\n await handleGetConfig(key);\n break;\n\n case 'set':\n if (!key || value === undefined) {\n throw new ValidationError('Config key and value are required for \"set\" command');\n }\n await handleSetConfig(key, value);\n break;\n\n default:\n throw new ValidationError(\n `Invalid subcommand: \"${subcommand}\". Valid subcommands: list, get, set`\n );\n }\n } catch (error: any) {\n logger.log('');\n logger.log(\n boxen(formatErrorMessage(error.message, getConfigHint(error)), {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'red',\n })\n );\n\n process.exit(1);\n }\n}\n\n/**\n * Handle 'list' subcommand - Display all configuration values\n */\nasync function handleListConfig(): Promise<void> {\n const config = {\n apiBaseUrl: storageService.getConfig('apiBaseUrl'),\n defaultCommitDays: storageService.getConfig('defaultCommitDays'),\n autoVersionCheck: storageService.getConfig('autoVersionCheck'),\n };\n\n const table = new Table({\n head: [chalk.cyan('Key'), chalk.cyan('Value'), chalk.cyan('Default')],\n colWidths: [25, 40, 40],\n wordWrap: true,\n style: {\n head: [],\n border: ['gray'],\n },\n });\n\n table.push([\n chalk.white('apiBaseUrl'),\n chalk.yellow(config.apiBaseUrl),\n chalk.dim(DEFAULT_CONFIG.apiBaseUrl),\n ]);\n\n table.push([\n chalk.white('defaultCommitDays'),\n chalk.yellow(String(config.defaultCommitDays)),\n chalk.dim(String(DEFAULT_CONFIG.defaultCommitDays)),\n ]);\n\n table.push([\n chalk.white('autoVersionCheck'),\n chalk.yellow(String(config.autoVersionCheck)),\n chalk.dim(String(DEFAULT_CONFIG.autoVersionCheck)),\n ]);\n\n logger.info('Current configuration:');\n logger.log('');\n logger.log(table.toString());\n logger.log('');\n logger.info(chalk.dim('To change a value: ') + chalk.cyan('bragduck config set <key> <value>'));\n logger.log('');\n}\n\n/**\n * Handle 'get' subcommand - Get a specific configuration value\n */\nasync function handleGetConfig(key: string): Promise<void> {\n validateConfigKey(key);\n\n const value = storageService.getConfig(key as keyof typeof CONFIG_KEYS);\n const defaultValue = DEFAULT_CONFIG[key as keyof typeof DEFAULT_CONFIG];\n\n logger.info(`Configuration for ${chalk.cyan(key)}:`);\n logger.log('');\n logger.log(` ${chalk.white('Current:')} ${chalk.yellow(String(value))}`);\n logger.log(` ${chalk.white('Default:')} ${chalk.dim(String(defaultValue))}`);\n logger.log('');\n\n if (value === defaultValue) {\n logger.info(chalk.dim('Using default value'));\n } else {\n logger.info(\n chalk.dim('Custom value set. Reset with: ') +\n chalk.cyan(`bragduck config set ${key} ${defaultValue}`)\n );\n }\n logger.log('');\n}\n\n/**\n * Handle 'set' subcommand - Set a configuration value\n */\nasync function handleSetConfig(key: string, value: string): Promise<void> {\n validateConfigKey(key);\n\n // Validate and convert value based on key type\n const typedValue = validateAndConvertValue(key, value);\n\n // Store the configuration\n storageService.setConfig(key as keyof typeof CONFIG_KEYS, typedValue);\n\n // If setting apiBaseUrl, update the API service\n if (key === CONFIG_KEYS.API_BASE_URL) {\n apiService.setBaseURL(typedValue as string);\n }\n\n logger.log(\n boxen(\n `${chalk.green.bold('✓ Configuration updated')}\\n\\n` +\n `${chalk.white(key)}: ${chalk.yellow(String(typedValue))}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'green',\n }\n )\n );\n}\n\n/**\n * Validate configuration key\n */\nfunction validateConfigKey(key: string): void {\n if (!VALID_CONFIG_KEYS.includes(key as any)) {\n throw new ValidationError(\n `Invalid config key: \"${key}\"\\n\\nValid keys:\\n${VALID_CONFIG_KEYS.map((k) => ` - ${k}`).join('\\n')}`\n );\n }\n}\n\n/**\n * Validate and convert value based on key type\n */\nfunction validateAndConvertValue(key: string, value: string): string | number | boolean {\n switch (key) {\n case CONFIG_KEYS.API_BASE_URL:\n // Validate URL format\n if (!isValidUrl(value)) {\n throw new ValidationError(\n `Invalid URL format: \"${value}\"\\n\\nExample: https://api.bragduck.com`\n );\n }\n return value;\n\n case CONFIG_KEYS.DEFAULT_COMMIT_DAYS:\n // Convert to number and validate\n const days = parseInt(value, 10);\n if (isNaN(days) || days < 1 || days > 365) {\n throw new ValidationError(\n `Invalid value for defaultCommitDays: \"${value}\"\\n\\nMust be a number between 1 and 365`\n );\n }\n return days;\n\n case CONFIG_KEYS.AUTO_VERSION_CHECK:\n // Convert to boolean\n const lowerValue = value.toLowerCase();\n if (lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes') {\n return true;\n } else if (lowerValue === 'false' || lowerValue === '0' || lowerValue === 'no') {\n return false;\n }\n throw new ValidationError(\n `Invalid value for autoVersionCheck: \"${value}\"\\n\\nMust be one of: true, false, yes, no, 1, 0`\n );\n\n default:\n return value;\n }\n}\n\n/**\n * Validate URL format\n */\nfunction isValidUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * Get helpful hint for config errors\n */\nfunction getConfigHint(error: any): string {\n if (error.name === 'ValidationError') {\n return 'Run \"bragduck config list\" to see all available configuration keys';\n }\n\n return 'Run \"bragduck config --help\" for usage information';\n}\n"],"mappings":"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","names":["fileURLToPath","join","randomBytes","readFileSync","fileURLToPath","dirname","join","chalk","boxen","packageJsonPath","__dirname","packageJson","__filename","ofetch","version","readFileSync","fileURLToPath","dirname","join","chalk","boxen","chalk","ora","boxen","chalk","existsSync","join","path","confirm","chalk","confirm","ora","chalk","chalk","boxen","chalk","createSpinner","getErrorHint","boxen","chalk","Table","boxen","chalk","getErrorHint","Table","boxen","chalk","Table","boxen","config","Table","chalk","__filename","fileURLToPath","__dirname","dirname","join","readFileSync"]}
|
|
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/utils/version.ts","../../src/services/api.service.ts","../../src/cli.ts","../../src/commands/init.ts","../../src/commands/logout.ts","../../src/commands/scan.ts","../../src/services/git.service.ts","../../src/utils/validators.ts","../../src/ui/prompts.ts","../../src/ui/formatters.ts","../../src/ui/spinners.ts","../../src/commands/list.ts","../../src/commands/config.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 API_BASE_URL: 'apiBaseUrl',\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 apiBaseUrl: process.env.API_BASE_URL || 'https://api.bragduck.com',\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","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","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 { 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, OAuthError, NetworkError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type { StoredCredentials, UserInfo } from '../types/config.types.js';\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 // Prioritize environment variable, fallback to default API URL\n this.apiBaseUrl =\n process.env.API_BASE_URL ||\n storageService.getConfig('apiBaseUrl') ||\n '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 },\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 },\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 { 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","import { ofetch, type FetchOptions } from 'ofetch';\nimport { storageService } from './storage.service.js';\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\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 // Prioritize environment variable over stored config\n this.baseURL = process.env.API_BASE_URL || storageService.getConfig('apiBaseUrl');\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.baseURL}${options.url}`);\n\n // Add authentication header\n const token = await authService.getAccessToken();\n if (token) {\n options.headers = {\n ...options.headers,\n Authorization: `Bearer ${token}`,\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 = {\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.baseURL}${options.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 (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 storageService.setConfig('apiBaseUrl', 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 { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { initCommand } from './commands/init.js';\nimport { logoutCommand } from './commands/logout.js';\nimport { scanCommand } from './commands/scan.js';\nimport { listCommand } from './commands/list.js';\nimport { configCommand } from './commands/config.js';\nimport { checkForUpdates } from './utils/version.js';\nimport { logger } from './utils/logger.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Read package.json for version (go up two levels from dist/bin/)\nconst packageJsonPath = join(__dirname, '../../package.json');\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n\nconst program = new Command();\n\nprogram\n .name('bragduck')\n .description('CLI tool for managing developer achievements and brags')\n .version(packageJson.version, '-v, --version', 'Display version number')\n .helpOption('-h, --help', 'Display help information')\n .option('--skip-version-check', 'Skip automatic version check on startup')\n .option('--debug', 'Enable debug mode (shows detailed logs)');\n\n// Init command - OAuth authentication\nprogram\n .command('init')\n .description('Authenticate with Bragduck')\n .action(async () => {\n try {\n await initCommand();\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// Scan command - Interactive commit selection and brag creation\nprogram\n .command('scan')\n .description('Scan git commits and create brags')\n .option('-d, --days <number>', 'Number of days to scan', (val) => parseInt(val, 10))\n .option('-a, --all', 'Include all commits (not just current user)')\n .action(async (options) => {\n try {\n await scanCommand(options);\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// List command - Display existing brags\nprogram\n .command('list')\n .description('List your existing brags')\n .option('-l, --limit <number>', 'Number of brags to display', (val) => parseInt(val, 10), 50)\n .option('-o, --offset <number>', 'Number of brags to skip', (val) => parseInt(val, 10), 0)\n .option('-t, --tags <tags>', 'Filter by tags (comma-separated)')\n .option('-s, --search <query>', 'Search brags by keyword')\n .action(async (options) => {\n try {\n await listCommand(options);\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// Logout command - Clear credentials\nprogram\n .command('logout')\n .description('Clear stored credentials')\n .action(async () => {\n try {\n await logoutCommand();\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// Config command - Manage CLI configuration\nprogram\n .command('config [subcommand] [key] [value]')\n .description('Manage CLI configuration (subcommands: list, get, set)')\n .action(async (subcommand, key, value) => {\n try {\n await configCommand(subcommand, key, value);\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n });\n\n// Hook to run before any command execution\nprogram.hook('preAction', async (_thisCommand) => {\n const options = program.opts();\n\n // Enable debug mode if --debug flag is set\n if (options.debug) {\n process.env.DEBUG = 'true';\n logger.debug('Debug mode enabled');\n }\n\n // Check for updates (unless --skip-version-check is set or --version/--help is used)\n const isVersionOrHelp = process.argv.includes('--version') ||\n process.argv.includes('-v') ||\n process.argv.includes('--help') ||\n process.argv.includes('-h');\n\n if (!options.skipVersionCheck && !isVersionOrHelp) {\n try {\n await checkForUpdates({ silent: false });\n } catch (error) {\n // Non-critical, continue execution\n logger.debug('Version check failed, continuing...');\n }\n }\n});\n\n// Parse command line arguments\nprogram.parse(process.argv);\n\n// Show help if no command is provided\nif (!process.argv.slice(2).length) {\n program.outputHelp();\n}\n","import ora from 'ora';\nimport boxen from 'boxen';\nimport chalk from 'chalk';\nimport { authService } from '../services/auth.service.js';\nimport { logger } from '../utils/logger.js';\nimport type { BragduckError } from '../utils/errors.js';\n\n/**\n * Init command: Authenticate with Bragduck\n */\nexport async function initCommand(): Promise<void> {\n logger.log('');\n logger.info('Starting authentication flow...');\n logger.log('');\n\n // Check if already authenticated\n const isAuthenticated = await authService.isAuthenticated();\n if (isAuthenticated) {\n const userInfo = authService.getUserInfo();\n if (userInfo) {\n logger.log(\n boxen(\n `${chalk.yellow('Already authenticated!')}\\n\\n` +\n `${chalk.gray('User:')} ${userInfo.name}\\n` +\n `${chalk.gray('Email:')} ${userInfo.email}\\n\\n` +\n `${chalk.dim('Run')} ${chalk.cyan('bragduck logout')} ${chalk.dim('to sign out')}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'yellow',\n }\n )\n );\n logger.log('');\n setTimeout(() => {\n process.exit(0);\n }, 100);\n return;\n }\n }\n\n const spinner = ora('Opening browser for authentication...').start();\n\n try {\n // Start OAuth flow\n spinner.text = 'Waiting for authentication...';\n const userInfo = await authService.login();\n\n spinner.succeed('Authentication successful!');\n logger.log('');\n\n // Show success message\n logger.log(\n boxen(\n `${chalk.green.bold('✓ Successfully authenticated!')}\\n\\n` +\n `${chalk.gray('Welcome,')} ${chalk.cyan(userInfo.name)}\\n` +\n `${chalk.gray('Email:')} ${userInfo.email}\\n\\n` +\n `${chalk.dim('You can now use')} ${chalk.cyan('bragduck scan')} ${chalk.dim('to create brags!')}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'green',\n }\n )\n );\n logger.log('');\n\n // Exit successfully - force immediate exit\n // Use setTimeout to ensure all logs are flushed\n setTimeout(() => {\n process.exit(0);\n }, 100);\n\n // Return to prevent further execution\n return;\n } catch (error) {\n spinner.fail('Authentication failed');\n logger.log('');\n\n const err = error as BragduckError;\n\n // Show error message\n logger.log(\n boxen(\n `${chalk.red.bold('✗ Authentication Failed')}\\n\\n` +\n `${err.message}\\n\\n` +\n `${chalk.dim('Hint:')} ${getErrorHint(err)}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'red',\n }\n )\n );\n\n process.exit(1);\n }\n}\n\n/**\n * Get helpful hint based on error type\n */\nfunction getErrorHint(error: BragduckError): string {\n if (error.name === 'OAuthError') {\n if (error.message.includes('timeout')) {\n return 'Try again and complete the authentication within 2 minutes';\n }\n if (error.message.includes('CSRF')) {\n return 'This might be a security issue. Try running the command again';\n }\n return 'Check your internet connection and try again';\n }\n\n if (error.name === 'NetworkError') {\n return 'Check your internet connection and firewall settings';\n }\n\n if (error.name === 'AuthenticationError') {\n return 'Verify your credentials and try again';\n }\n\n return 'Try running the command again or check the logs with DEBUG=* bragduck init';\n}\n","import { confirm } from '@inquirer/prompts';\nimport boxen from 'boxen';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { authService } from '../services/auth.service.js';\nimport { logger } from '../utils/logger.js';\n\n/**\n * Logout command: Clear stored credentials\n */\nexport async function logoutCommand(): Promise<void> {\n // Check if user is authenticated\n const isAuthenticated = await authService.isAuthenticated();\n\n if (!isAuthenticated) {\n logger.log(\n boxen(`${chalk.yellow('Not currently authenticated')}\\n\\n${chalk.dim('Nothing to logout from')}`, {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'yellow',\n })\n );\n return;\n }\n\n // Get user info to show in confirmation\n const userInfo = authService.getUserInfo();\n const userName = userInfo?.name || 'Unknown User';\n\n logger.log('');\n\n // Confirm logout\n const shouldLogout = await confirm({\n message: `Are you sure you want to logout? (${chalk.cyan(userName)})`,\n default: false,\n });\n\n if (!shouldLogout) {\n logger.info('Logout cancelled');\n return;\n }\n\n const spinner = ora('Logging out...').start();\n\n try {\n await authService.logout();\n spinner.succeed('Logged out successfully');\n logger.log('');\n\n logger.log(\n boxen(\n `${chalk.green.bold('✓ Logged out successfully')}\\n\\n` +\n `${chalk.dim('Your credentials have been cleared')}\\n\\n` +\n `${chalk.dim('Run')} ${chalk.cyan('bragduck init')} ${chalk.dim('to login again')}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'green',\n }\n )\n );\n } catch (error) {\n spinner.fail('Logout failed');\n logger.error('Failed to logout. Please try again.');\n process.exit(1);\n }\n}\n","import boxen from 'boxen';\nimport chalk from 'chalk';\nimport { gitService } from '../services/git.service.js';\nimport { apiService } from '../services/api.service.js';\nimport { authService } from '../services/auth.service.js';\nimport { storageService } from '../services/storage.service.js';\nimport { logger } from '../utils/logger.js';\nimport type { BragduckError } from '../utils/errors.js';\nimport {\n promptSelectCommits,\n promptConfirm,\n promptDaysToScan,\n} from '../ui/prompts.js';\nimport {\n fetchingCommitsSpinner,\n refiningCommitsSpinner,\n creatingBragsSpinner,\n succeedSpinner,\n failSpinner,\n} from '../ui/spinners.js';\nimport {\n formatRefinedCommitsTable,\n formatSuccessMessage,\n formatErrorMessage,\n formatCommitStats,\n} from '../ui/formatters.js';\nimport type { GitCommit } from '../types/git.types.js';\nimport type { CreateBragItem } from '../types/api.types.js';\n\n/**\n * Scan command options\n */\nexport interface ScanCommandOptions {\n days?: number;\n all?: boolean; // Include all commits, not just current user's\n}\n\n/**\n * Scan command: Scan git commits and create brags\n */\nexport async function scanCommand(options: ScanCommandOptions = {}): Promise<void> {\n logger.log('');\n\n try {\n // 1. Check authentication\n const isAuthenticated = await authService.isAuthenticated();\n if (!isAuthenticated) {\n logger.log(\n boxen(\n `${chalk.yellow.bold('⚠ Not authenticated')}\\n\\n` +\n `Please run ${chalk.cyan('bragduck init')} to login first.`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'yellow',\n }\n )\n );\n process.exit(1);\n }\n\n // 2. Validate git repository\n await gitService.validateRepository();\n const repoInfo = await gitService.getRepositoryInfo();\n\n logger.info(`Repository: ${chalk.cyan(repoInfo.currentBranch)} branch`);\n logger.log('');\n\n // 3. Prompt for days to scan (if not provided)\n let days = options.days;\n if (!days) {\n const defaultDays = storageService.getConfig('defaultCommitDays');\n days = await promptDaysToScan(defaultDays);\n logger.log('');\n }\n\n // 4. Fetch commits\n const spinner = fetchingCommitsSpinner(days);\n spinner.start();\n\n let commits: GitCommit[];\n if (options.all) {\n commits = await gitService.getCommitsWithStats({ days });\n } else {\n commits = await gitService.getCommitsByCurrentUser({ days });\n }\n\n if (commits.length === 0) {\n failSpinner(spinner, `No commits found in the last ${days} days`);\n logger.log('');\n logger.info('Try increasing the number of days or check your git configuration');\n return;\n }\n\n succeedSpinner(spinner, `Found ${commits.length} commit${commits.length > 1 ? 's' : ''}`);\n logger.log('');\n\n // Show commit statistics\n logger.log(formatCommitStats(commits));\n logger.log('');\n\n // 5. Interactive commit selection\n const selectedShas = await promptSelectCommits(commits);\n\n if (selectedShas.length === 0) {\n logger.warning('No commits selected');\n return;\n }\n\n const selectedCommits = commits.filter((c) => selectedShas.includes(c.sha));\n logger.log('');\n logger.success(`Selected ${selectedCommits.length} commit${selectedCommits.length > 1 ? 's' : ''}`);\n logger.log('');\n\n // 6. Refine commits with AI\n const refineSpinner = refiningCommitsSpinner(selectedCommits.length);\n refineSpinner.start();\n\n const refineRequest = {\n commits: selectedCommits.map((c) => ({\n sha: c.sha,\n message: c.message,\n author: c.author,\n date: c.date,\n diff_stats: c.diffStats\n ? {\n files_changed: c.diffStats.filesChanged,\n insertions: c.diffStats.insertions,\n deletions: c.diffStats.deletions,\n }\n : undefined,\n })),\n };\n\n const refineResponse = await apiService.refineCommits(refineRequest);\n const refinedCommits = refineResponse.refined_commits;\n\n succeedSpinner(refineSpinner, 'Commits refined successfully');\n logger.log('');\n\n // 7. Show preview\n logger.info('Preview of refined brags:');\n logger.log('');\n logger.log(formatRefinedCommitsTable(refinedCommits));\n logger.log('');\n\n // 8. Confirm creation\n const shouldCreate = await promptConfirm('Create these brags?', true);\n\n if (!shouldCreate) {\n logger.warning('Cancelled');\n return;\n }\n\n logger.log('');\n\n // 9. Create brags\n const createSpinner = creatingBragsSpinner(refinedCommits.length);\n createSpinner.start();\n\n const createRequest = {\n brags: refinedCommits.map((refined): CreateBragItem => {\n const originalCommit = selectedCommits.find((c) => c.sha === refined.sha);\n return {\n commit_sha: refined.sha,\n title: refined.refined_title,\n description: refined.refined_description,\n tags: refined.suggested_tags,\n repository: repoInfo.remoteUrl,\n date: originalCommit?.date || new Date().toISOString(),\n };\n }),\n };\n\n const createResponse = await apiService.createBrags(createRequest);\n\n succeedSpinner(createSpinner, `Created ${createResponse.created} brags`);\n logger.log('');\n\n // 10. Show success message\n logger.log(\n boxen(formatSuccessMessage(createResponse.created), {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'green',\n })\n );\n } catch (error) {\n const err = error as BragduckError;\n\n logger.log('');\n logger.log(\n boxen(formatErrorMessage(err.message, getErrorHint(err)), {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'red',\n })\n );\n\n process.exit(1);\n }\n}\n\n/**\n * Get helpful hint based on error type\n */\nfunction getErrorHint(error: BragduckError): string {\n if (error.name === 'GitError') {\n return 'Make sure you are in a git repository with commits';\n }\n\n if (error.name === 'TokenExpiredError' || error.name === 'AuthenticationError') {\n return 'Run \"bragduck init\" to login again';\n }\n\n if (error.name === 'NetworkError') {\n return 'Check your internet connection and try again';\n }\n\n if (error.name === 'ApiError') {\n return 'The server might be experiencing issues. Try again later';\n }\n\n return 'Try running with DEBUG=* for more information';\n}\n","import simpleGit, { SimpleGit, LogResult, DefaultLogFields } from 'simple-git';\nimport { validateGitRepository } from '../utils/validators.js';\nimport { GitError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type {\n GitCommit,\n DiffStats,\n FetchCommitsOptions,\n GitRepositoryInfo,\n} from '../types/git.types.js';\n\n/**\n * Git service for interacting with git repositories\n */\nexport class GitService {\n private git: SimpleGit;\n private repoPath: string;\n\n constructor(repoPath: string = process.cwd()) {\n this.repoPath = repoPath;\n this.git = simpleGit(repoPath);\n }\n\n /**\n * Validate that the current directory is a git repository\n */\n async validateRepository(): Promise<void> {\n try {\n validateGitRepository(this.repoPath);\n const isRepo = await this.git.checkIsRepo();\n\n if (!isRepo) {\n throw new GitError('Not a valid git repository', {\n path: this.repoPath,\n });\n }\n } catch (error: any) {\n if (error instanceof GitError) {\n throw error;\n }\n throw new GitError('Failed to validate git repository', {\n originalError: error.message,\n path: this.repoPath,\n });\n }\n }\n\n /**\n * Get repository information\n */\n async getRepositoryInfo(): Promise<GitRepositoryInfo> {\n try {\n await this.validateRepository();\n\n const status = await this.git.status();\n const remotes = await this.git.getRemotes(true);\n const primaryRemote = remotes.find((r) => r.name === 'origin');\n\n return {\n path: this.repoPath,\n currentBranch: status.current || 'unknown',\n remoteUrl: primaryRemote?.refs?.fetch || primaryRemote?.refs?.push,\n isClean: status.isClean(),\n };\n } catch (error: any) {\n if (error instanceof GitError) {\n throw error;\n }\n throw new GitError('Failed to get repository information', {\n originalError: error.message,\n });\n }\n }\n\n /**\n * Fetch recent commits\n */\n async getRecentCommits(options: FetchCommitsOptions = {}): Promise<GitCommit[]> {\n const { days = 30, limit, author, branch } = options;\n\n try {\n await this.validateRepository();\n\n logger.debug(`Fetching commits from last ${days} days`);\n\n // Calculate date for filtering\n const since = new Date();\n since.setDate(since.getDate() - days);\n\n // Build log options\n const logOptions: any = {\n '--since': since.toISOString(),\n '--no-merges': null,\n };\n\n if (limit) {\n logOptions.maxCount = limit;\n }\n\n if (author) {\n logOptions['--author'] = author;\n }\n\n // Fetch commits\n const log: LogResult<DefaultLogFields> = await this.git.log(logOptions);\n\n logger.debug(`Found ${log.all.length} commits`);\n\n // Convert to our GitCommit format\n const commits: GitCommit[] = log.all.map((commit) => ({\n sha: commit.hash,\n message: commit.message,\n author: commit.author_name,\n authorEmail: commit.author_email,\n date: commit.date,\n }));\n\n return commits;\n } catch (error: any) {\n if (error instanceof GitError) {\n throw error;\n }\n throw new GitError('Failed to fetch commits', {\n originalError: error.message,\n days,\n });\n }\n }\n\n /**\n * Get diff statistics for a specific commit\n */\n async getCommitStats(sha: string): Promise<DiffStats> {\n try {\n logger.debug(`Getting stats for commit ${sha}`);\n\n // Get diff summary for the commit\n const diffSummary = await this.git.diffSummary([`${sha}^`, sha]);\n\n const stats: DiffStats = {\n filesChanged: diffSummary.files.length,\n insertions: diffSummary.insertions,\n deletions: diffSummary.deletions,\n };\n\n logger.debug(`Commit ${sha}: ${stats.filesChanged} files, +${stats.insertions} -${stats.deletions}`);\n\n return stats;\n } catch (error: any) {\n // If this is the first commit, there's no parent to diff against\n if (error.message && error.message.includes('unknown revision')) {\n logger.debug(`Commit ${sha} has no parent (first commit)`);\n // Try to get stats for first commit\n try {\n const diffSummary = await this.git.diffSummary([sha]);\n return {\n filesChanged: diffSummary.files.length,\n insertions: diffSummary.insertions,\n deletions: diffSummary.deletions,\n };\n } catch {\n // Return zeros if we can't get stats\n return {\n filesChanged: 0,\n insertions: 0,\n deletions: 0,\n };\n }\n }\n\n throw new GitError('Failed to get commit statistics', {\n originalError: error.message,\n sha,\n });\n }\n }\n\n /**\n * Get commits with their diff statistics\n */\n async getCommitsWithStats(options: FetchCommitsOptions = {}): Promise<GitCommit[]> {\n const commits = await this.getRecentCommits(options);\n\n logger.debug(`Fetching diff stats for ${commits.length} commits`);\n\n // Fetch stats for each commit in parallel\n const commitsWithStats = await Promise.all(\n commits.map(async (commit) => {\n try {\n const stats = await this.getCommitStats(commit.sha);\n return {\n ...commit,\n diffStats: stats,\n };\n } catch (error) {\n logger.debug(`Failed to get stats for commit ${commit.sha}, continuing without stats`);\n return commit;\n }\n })\n );\n\n return commitsWithStats;\n }\n\n /**\n * Get the current git user email\n */\n async getCurrentUserEmail(): Promise<string | null> {\n try {\n const email = await this.git.raw(['config', 'user.email']);\n return email.trim() || null;\n } catch (error) {\n logger.debug('Failed to get git user email');\n return null;\n }\n }\n\n /**\n * Get the current git user name\n */\n async getCurrentUserName(): Promise<string | null> {\n try {\n const name = await this.git.raw(['config', 'user.name']);\n return name.trim() || null;\n } catch (error) {\n logger.debug('Failed to get git user name');\n return null;\n }\n }\n\n /**\n * Filter commits by current user\n */\n async getCommitsByCurrentUser(options: FetchCommitsOptions = {}): Promise<GitCommit[]> {\n const userEmail = await this.getCurrentUserEmail();\n\n if (!userEmail) {\n logger.warning('Could not determine git user email, returning all commits');\n return this.getCommitsWithStats(options);\n }\n\n logger.debug(`Filtering commits by user: ${userEmail}`);\n\n return this.getCommitsWithStats({\n ...options,\n author: userEmail,\n });\n }\n}\n\n// Export singleton instance for the current working directory\nexport const gitService = new GitService();\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport { GitError, ValidationError } from './errors.js';\n\n/**\n * Validate that a directory is a git repository\n */\nexport function validateGitRepository(path: string): void {\n const gitDir = join(path, '.git');\n\n if (!existsSync(gitDir)) {\n throw new GitError(\n 'Not a git repository. Please run this command from within a git repository.',\n {\n path,\n hint: 'Run \"git init\" to initialize a git repository, or navigate to an existing one',\n }\n );\n }\n}\n\n/**\n * Validate email format\n */\nexport function validateEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n}\n\n/**\n * Validate that a value is not empty\n */\nexport function validateNotEmpty(value: string, fieldName: string): void {\n if (!value || value.trim().length === 0) {\n throw new ValidationError(`${fieldName} cannot be empty`);\n }\n}\n\n/**\n * Validate date is in valid format\n */\nexport function validateDate(dateString: string): boolean {\n const date = new Date(dateString);\n return !isNaN(date.getTime());\n}\n\n/**\n * Validate number is positive\n */\nexport function validatePositiveNumber(value: number, fieldName: string): void {\n if (value <= 0) {\n throw new ValidationError(`${fieldName} must be a positive number`);\n }\n}\n\n/**\n * Validate commit SHA format (40 character hex string)\n */\nexport function validateCommitSha(sha: string): boolean {\n const shaRegex = /^[a-f0-9]{40}$/i;\n return shaRegex.test(sha);\n}\n","import { checkbox, confirm, input, select } from '@inquirer/prompts';\nimport type { GitCommit } from '../types/git.types.js';\nimport { formatCommitChoice } from './formatters.js';\n\n/**\n * Prompt user to select commits\n */\nexport async function promptSelectCommits(commits: GitCommit[]): Promise<string[]> {\n if (commits.length === 0) {\n return [];\n }\n\n const choices = commits.map((commit) => ({\n name: formatCommitChoice(commit),\n value: commit.sha,\n checked: false,\n }));\n\n const selected = await checkbox({\n message: 'Select commits to brag about (use space to select, enter to confirm):',\n choices,\n pageSize: 10,\n loop: false,\n });\n\n return selected;\n}\n\n/**\n * Prompt user to confirm action\n */\nexport async function promptConfirm(\n message: string,\n defaultValue: boolean = true\n): Promise<boolean> {\n return await confirm({\n message,\n default: defaultValue,\n });\n}\n\n/**\n * Prompt user for text input\n */\nexport async function promptInput(message: string, defaultValue?: string): Promise<string> {\n return await input({\n message,\n default: defaultValue,\n });\n}\n\n/**\n * Prompt user to select from options\n */\nexport async function promptSelect<T extends string>(\n message: string,\n choices: Array<{ name: string; value: T; description?: string }>\n): Promise<T> {\n return await select({\n message,\n choices,\n });\n}\n\n/**\n * Prompt for number of days to scan\n */\nexport async function promptDaysToScan(defaultDays: number = 30): Promise<number> {\n const choices = [\n { name: '7 days', value: '7', description: 'Last week' },\n { name: '30 days (Recommended)', value: '30', description: 'Last month' },\n { name: '60 days', value: '60', description: 'Last 2 months' },\n { name: '90 days', value: '90', description: 'Last 3 months' },\n { name: 'Custom', value: 'custom', description: 'Enter custom number of days' },\n ];\n\n const selected = await select({\n message: 'How many days back should we scan for commits?',\n choices,\n default: '30',\n });\n\n if (selected === 'custom') {\n const customDays = await input({\n message: 'Enter number of days:',\n default: defaultDays.toString(),\n validate: (value) => {\n const num = parseInt(value, 10);\n if (isNaN(num) || num <= 0) {\n return 'Please enter a valid positive number';\n }\n return true;\n },\n });\n return parseInt(customDays, 10);\n }\n\n return parseInt(selected, 10);\n}\n","import chalk from 'chalk';\nimport Table from 'cli-table3';\nimport type { GitCommit } from '../types/git.types.js';\nimport type { RefinedCommit } from '../types/api.types.js';\n\n/**\n * Format a commit for display in checkbox list\n */\nexport function formatCommitChoice(commit: GitCommit): string {\n const sha = chalk.yellow(commit.sha.substring(0, 7));\n const message = commit.message.split('\\n')[0]; // First line only\n const author = chalk.gray(`by ${commit.author}`);\n const date = chalk.gray(new Date(commit.date).toLocaleDateString());\n\n let stats = '';\n if (commit.diffStats) {\n const { filesChanged, insertions, deletions } = commit.diffStats;\n stats = chalk.gray(\n ` [${filesChanged} files, ${chalk.green(`+${insertions}`)} ${chalk.red(`-${deletions}`)}]`\n );\n }\n\n return `${sha} ${message}${stats}\\n ${author} • ${date}`;\n}\n\n/**\n * Format refined commits as a preview table\n */\nexport function formatRefinedCommitsTable(commits: RefinedCommit[]): string {\n const table = new Table({\n head: [\n chalk.cyan('SHA'),\n chalk.cyan('Original'),\n chalk.cyan('Refined Title'),\n chalk.cyan('Description'),\n chalk.cyan('Tags'),\n ],\n colWidths: [10, 30, 30, 40, 20],\n wordWrap: true,\n style: {\n head: [],\n border: ['gray'],\n },\n });\n\n commits.forEach((commit) => {\n const sha = commit.sha.substring(0, 7);\n const original = commit.original_message.split('\\n')[0] || '';\n const title = commit.refined_title;\n const description = commit.refined_description.substring(0, 100) + '...';\n const tags = (commit.suggested_tags || []).join(', ') || 'none';\n\n table.push([\n chalk.yellow(sha),\n chalk.gray(original),\n chalk.white(title),\n chalk.dim(description),\n chalk.blue(tags),\n ]);\n });\n\n return table.toString();\n}\n\n/**\n * Format commit statistics\n */\nexport function formatCommitStats(commits: GitCommit[]): string {\n const totalFiles = commits.reduce((sum, c) => sum + (c.diffStats?.filesChanged || 0), 0);\n const totalInsertions = commits.reduce((sum, c) => sum + (c.diffStats?.insertions || 0), 0);\n const totalDeletions = commits.reduce((sum, c) => sum + (c.diffStats?.deletions || 0), 0);\n\n return (\n chalk.gray('Total changes: ') +\n chalk.white(`${totalFiles} files`) +\n chalk.gray(', ') +\n chalk.green(`+${totalInsertions}`) +\n chalk.gray(' ') +\n chalk.red(`-${totalDeletions}`)\n );\n}\n\n/**\n * Format success message for created brags\n */\nexport function formatSuccessMessage(count: number): string {\n const emoji = '🎉';\n const title = chalk.green.bold(`${emoji} Successfully created ${count} brag${count > 1 ? 's' : ''}!`);\n const message = chalk.white('\\nYour achievements are now saved and ready to showcase.');\n const hint = chalk.dim('\\nRun ') + chalk.cyan('bragduck list') + chalk.dim(' to see all your brags');\n\n return `${title}${message}${hint}`;\n}\n\n/**\n * Format error message for display\n */\nexport function formatErrorMessage(message: string, hint?: string): string {\n const title = chalk.red.bold('✗ Error');\n const error = chalk.white(message);\n const hintText = hint ? chalk.dim('\\n\\nHint: ') + chalk.cyan(hint) : '';\n\n return `${title}\\n\\n${error}${hintText}`;\n}\n\n/**\n * Format progress message\n */\nexport function formatProgress(current: number, total: number, label: string): string {\n const percentage = Math.round((current / total) * 100);\n const bar = '█'.repeat(Math.floor(percentage / 5)) + '░'.repeat(20 - Math.floor(percentage / 5));\n\n return `${chalk.cyan(bar)} ${chalk.white(`${percentage}%`)} ${chalk.gray(label)}`;\n}\n","import ora, { Ora } from 'ora';\nimport chalk from 'chalk';\n\n/**\n * Create a spinner with consistent styling\n */\nexport function createSpinner(text: string): Ora {\n return ora({\n text,\n color: 'cyan',\n spinner: 'dots',\n });\n}\n\n/**\n * Spinner for fetching commits\n */\nexport function fetchingCommitsSpinner(days: number): Ora {\n return createSpinner(`Fetching commits from the last ${days} days...`);\n}\n\n/**\n * Spinner for refining commits\n */\nexport function refiningCommitsSpinner(count: number): Ora {\n return createSpinner(`Refining ${count} commit${count > 1 ? 's' : ''} with AI...`);\n}\n\n/**\n * Spinner for creating brags\n */\nexport function creatingBragsSpinner(count: number): Ora {\n return createSpinner(`Creating ${count} brag${count > 1 ? 's' : ''}...`);\n}\n\n/**\n * Spinner for fetching brags\n */\nexport function fetchingBragsSpinner(): Ora {\n return createSpinner('Fetching your brags...');\n}\n\n/**\n * Update spinner with new text\n */\nexport function updateSpinner(spinner: Ora, text: string): void {\n spinner.text = text;\n}\n\n/**\n * Succeed spinner with custom text\n */\nexport function succeedSpinner(spinner: Ora, text?: string): void {\n if (text) {\n spinner.succeed(chalk.green(text));\n } else {\n spinner.succeed();\n }\n}\n\n/**\n * Fail spinner with custom text\n */\nexport function failSpinner(spinner: Ora, text?: string): void {\n if (text) {\n spinner.fail(chalk.red(text));\n } else {\n spinner.fail();\n }\n}\n\n/**\n * Warn spinner with custom text\n */\nexport function warnSpinner(spinner: Ora, text?: string): void {\n if (text) {\n spinner.warn(chalk.yellow(text));\n } else {\n spinner.warn();\n }\n}\n","import boxen from 'boxen';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { apiService } from '../services/api.service.js';\nimport { authService } from '../services/auth.service.js';\nimport { logger } from '../utils/logger.js';\nimport { formatErrorMessage } from '../ui/formatters.js';\nimport { fetchingBragsSpinner, succeedSpinner, failSpinner } from '../ui/spinners.js';\nimport type { BragduckError } from '../utils/errors.js';\nimport type { Brag } from '../types/api.types.js';\n\n/**\n * List command options\n */\nexport interface ListCommandOptions {\n limit?: number;\n offset?: number;\n tags?: string;\n search?: string;\n}\n\n/**\n * List command: Fetch and display existing brags\n */\nexport async function listCommand(options: ListCommandOptions = {}): Promise<void> {\n logger.log('');\n\n try {\n // 1. Check authentication\n const isAuthenticated = await authService.isAuthenticated();\n if (!isAuthenticated) {\n logger.log(\n boxen(\n `${chalk.yellow.bold('⚠ Not authenticated')}\\n\\n` +\n `Please run ${chalk.cyan('bragduck init')} to login first.`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'yellow',\n }\n )\n );\n process.exit(1);\n }\n\n // 2. Parse options\n const limit = options.limit || 50;\n const offset = options.offset || 0;\n const tags = options.tags ? options.tags.split(',').map((t) => t.trim()) : undefined;\n const search = options.search;\n\n // 3. Fetch brags\n const spinner = fetchingBragsSpinner();\n spinner.start();\n\n const response = await apiService.listBrags({\n limit,\n offset,\n tags,\n search,\n });\n\n if (response.brags.length === 0) {\n failSpinner(spinner, 'No brags found');\n logger.log('');\n\n if (search || tags) {\n logger.info('Try adjusting your filters or run without filters to see all brags');\n } else {\n logger.info(`Run ${chalk.cyan('bragduck scan')} to create your first brag!`);\n }\n return;\n }\n\n succeedSpinner(spinner, `Found ${response.total} brag${response.total > 1 ? 's' : ''}`);\n logger.log('');\n\n // 4. Display brags in table\n logger.log(formatBragsTable(response.brags));\n logger.log('');\n\n // 5. Show pagination info\n if (response.has_more) {\n const nextOffset = offset + limit;\n logger.info(\n `Showing ${offset + 1}-${offset + response.brags.length} of ${response.total} total brags`\n );\n logger.info(\n chalk.dim(`Run `) +\n chalk.cyan(`bragduck list --offset ${nextOffset}`) +\n chalk.dim(` to see more`)\n );\n logger.log('');\n } else if (offset > 0) {\n logger.info(\n `Showing ${offset + 1}-${offset + response.brags.length} of ${response.total} total brags`\n );\n logger.log('');\n }\n\n // 6. Show filter info if filters are applied\n if (search || tags) {\n const filterInfo: string[] = [];\n if (search) filterInfo.push(`search: \"${search}\"`);\n if (tags) filterInfo.push(`tags: ${tags.join(', ')}`);\n logger.info(chalk.dim(`Filters applied: ${filterInfo.join(', ')}`));\n logger.log('');\n }\n } catch (error) {\n const err = error as BragduckError;\n\n logger.log('');\n logger.log(\n boxen(formatErrorMessage(err.message, getErrorHint(err)), {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'red',\n })\n );\n\n process.exit(1);\n }\n}\n\n/**\n * Format brags as a table\n */\nfunction formatBragsTable(brags: Brag[]): string {\n const table = new Table({\n head: [\n chalk.cyan('Date'),\n chalk.cyan('Title'),\n chalk.cyan('Description'),\n chalk.cyan('Tags'),\n chalk.cyan('Repository'),\n ],\n colWidths: [12, 30, 40, 20, 30],\n wordWrap: true,\n style: {\n head: [],\n border: ['gray'],\n },\n });\n\n brags.forEach((brag) => {\n const date = new Date(brag.date).toLocaleDateString();\n const title = brag.title;\n const description = truncateText(brag.description, 100);\n const tags = brag.tags.length > 0 ? brag.tags.join(', ') : chalk.dim('none');\n const repository = brag.repository\n ? truncateText(extractRepoName(brag.repository), 25)\n : chalk.dim('none');\n\n table.push([\n chalk.yellow(date),\n chalk.white(title),\n chalk.dim(description),\n chalk.blue(tags),\n chalk.gray(repository),\n ]);\n });\n\n return table.toString();\n}\n\n/**\n * Truncate text with ellipsis\n */\nfunction truncateText(text: string, maxLength: number): string {\n if (text.length <= maxLength) {\n return text;\n }\n return text.substring(0, maxLength - 3) + '...';\n}\n\n/**\n * Extract repository name from URL\n */\nfunction extractRepoName(url: string): string {\n try {\n // Handle GitHub URLs like: https://github.com/user/repo.git\n const match = url.match(/([^/]+\\/[^/]+?)(\\.git)?$/);\n return match ? match[1] : url;\n } catch {\n return url;\n }\n}\n\n/**\n * Get helpful hint based on error type\n */\nfunction getErrorHint(error: BragduckError): string {\n if (error.name === 'TokenExpiredError' || error.name === 'AuthenticationError') {\n return 'Run \"bragduck init\" to login again';\n }\n\n if (error.name === 'NetworkError') {\n return 'Check your internet connection and try again';\n }\n\n if (error.name === 'ApiError') {\n return 'The server might be experiencing issues. Try again later';\n }\n\n return 'Try running with DEBUG=* for more information';\n}\n","import boxen from 'boxen';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { storageService } from '../services/storage.service.js';\nimport { apiService } from '../services/api.service.js';\nimport { logger } from '../utils/logger.js';\nimport { CONFIG_KEYS, DEFAULT_CONFIG } from '../constants.js';\nimport { formatErrorMessage } from '../ui/formatters.js';\nimport { ValidationError } from '../utils/errors.js';\n\n/**\n * Valid configuration keys\n */\nconst VALID_CONFIG_KEYS = Object.values(CONFIG_KEYS);\n\n/**\n * Config subcommands\n */\ntype ConfigSubcommand = 'list' | 'get' | 'set';\n\n/**\n * Config command: Manage CLI configuration\n */\nexport async function configCommand(\n subcommand?: ConfigSubcommand,\n key?: string,\n value?: string\n): Promise<void> {\n logger.log('');\n\n try {\n // If no subcommand provided, default to 'list'\n if (!subcommand) {\n subcommand = 'list';\n }\n\n switch (subcommand) {\n case 'list':\n await handleListConfig();\n break;\n\n case 'get':\n if (!key) {\n throw new ValidationError('Config key is required for \"get\" command');\n }\n await handleGetConfig(key);\n break;\n\n case 'set':\n if (!key || value === undefined) {\n throw new ValidationError('Config key and value are required for \"set\" command');\n }\n await handleSetConfig(key, value);\n break;\n\n default:\n throw new ValidationError(\n `Invalid subcommand: \"${subcommand}\". Valid subcommands: list, get, set`\n );\n }\n } catch (error: any) {\n logger.log('');\n logger.log(\n boxen(formatErrorMessage(error.message, getConfigHint(error)), {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'red',\n })\n );\n\n process.exit(1);\n }\n}\n\n/**\n * Handle 'list' subcommand - Display all configuration values\n */\nasync function handleListConfig(): Promise<void> {\n const config = {\n apiBaseUrl: storageService.getConfig('apiBaseUrl'),\n defaultCommitDays: storageService.getConfig('defaultCommitDays'),\n autoVersionCheck: storageService.getConfig('autoVersionCheck'),\n };\n\n const table = new Table({\n head: [chalk.cyan('Key'), chalk.cyan('Value'), chalk.cyan('Default')],\n colWidths: [25, 40, 40],\n wordWrap: true,\n style: {\n head: [],\n border: ['gray'],\n },\n });\n\n table.push([\n chalk.white('apiBaseUrl'),\n chalk.yellow(config.apiBaseUrl),\n chalk.dim(DEFAULT_CONFIG.apiBaseUrl),\n ]);\n\n table.push([\n chalk.white('defaultCommitDays'),\n chalk.yellow(String(config.defaultCommitDays)),\n chalk.dim(String(DEFAULT_CONFIG.defaultCommitDays)),\n ]);\n\n table.push([\n chalk.white('autoVersionCheck'),\n chalk.yellow(String(config.autoVersionCheck)),\n chalk.dim(String(DEFAULT_CONFIG.autoVersionCheck)),\n ]);\n\n logger.info('Current configuration:');\n logger.log('');\n logger.log(table.toString());\n logger.log('');\n logger.info(chalk.dim('To change a value: ') + chalk.cyan('bragduck config set <key> <value>'));\n logger.log('');\n}\n\n/**\n * Handle 'get' subcommand - Get a specific configuration value\n */\nasync function handleGetConfig(key: string): Promise<void> {\n validateConfigKey(key);\n\n const value = storageService.getConfig(key as keyof typeof CONFIG_KEYS);\n const defaultValue = DEFAULT_CONFIG[key as keyof typeof DEFAULT_CONFIG];\n\n logger.info(`Configuration for ${chalk.cyan(key)}:`);\n logger.log('');\n logger.log(` ${chalk.white('Current:')} ${chalk.yellow(String(value))}`);\n logger.log(` ${chalk.white('Default:')} ${chalk.dim(String(defaultValue))}`);\n logger.log('');\n\n if (value === defaultValue) {\n logger.info(chalk.dim('Using default value'));\n } else {\n logger.info(\n chalk.dim('Custom value set. Reset with: ') +\n chalk.cyan(`bragduck config set ${key} ${defaultValue}`)\n );\n }\n logger.log('');\n}\n\n/**\n * Handle 'set' subcommand - Set a configuration value\n */\nasync function handleSetConfig(key: string, value: string): Promise<void> {\n validateConfigKey(key);\n\n // Validate and convert value based on key type\n const typedValue = validateAndConvertValue(key, value);\n\n // Store the configuration\n storageService.setConfig(key as keyof typeof CONFIG_KEYS, typedValue);\n\n // If setting apiBaseUrl, update the API service\n if (key === CONFIG_KEYS.API_BASE_URL) {\n apiService.setBaseURL(typedValue as string);\n }\n\n logger.log(\n boxen(\n `${chalk.green.bold('✓ Configuration updated')}\\n\\n` +\n `${chalk.white(key)}: ${chalk.yellow(String(typedValue))}`,\n {\n padding: 1,\n margin: 1,\n borderStyle: 'round',\n borderColor: 'green',\n }\n )\n );\n}\n\n/**\n * Validate configuration key\n */\nfunction validateConfigKey(key: string): void {\n if (!VALID_CONFIG_KEYS.includes(key as any)) {\n throw new ValidationError(\n `Invalid config key: \"${key}\"\\n\\nValid keys:\\n${VALID_CONFIG_KEYS.map((k) => ` - ${k}`).join('\\n')}`\n );\n }\n}\n\n/**\n * Validate and convert value based on key type\n */\nfunction validateAndConvertValue(key: string, value: string): string | number | boolean {\n switch (key) {\n case CONFIG_KEYS.API_BASE_URL:\n // Validate URL format\n if (!isValidUrl(value)) {\n throw new ValidationError(\n `Invalid URL format: \"${value}\"\\n\\nExample: https://api.bragduck.com`\n );\n }\n return value;\n\n case CONFIG_KEYS.DEFAULT_COMMIT_DAYS:\n // Convert to number and validate\n const days = parseInt(value, 10);\n if (isNaN(days) || days < 1 || days > 365) {\n throw new ValidationError(\n `Invalid value for defaultCommitDays: \"${value}\"\\n\\nMust be a number between 1 and 365`\n );\n }\n return days;\n\n case CONFIG_KEYS.AUTO_VERSION_CHECK:\n // Convert to boolean\n const lowerValue = value.toLowerCase();\n if (lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes') {\n return true;\n } else if (lowerValue === 'false' || lowerValue === '0' || lowerValue === 'no') {\n return false;\n }\n throw new ValidationError(\n `Invalid value for autoVersionCheck: \"${value}\"\\n\\nMust be one of: true, false, yes, no, 1, 0`\n );\n\n default:\n return value;\n }\n}\n\n/**\n * Validate URL format\n */\nfunction isValidUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * Get helpful hint for config errors\n */\nfunction getConfigHint(error: any): string {\n if (error.name === 'ValidationError') {\n return 'Run \"bragduck config list\" to see all available configuration keys';\n }\n\n return 'Run \"bragduck config --help\" for usage information';\n}\n"],"mappings":"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","names":["fileURLToPath","join","randomBytes","readFileSync","fileURLToPath","dirname","join","chalk","boxen","packageJsonPath","__dirname","packageJson","__filename","ofetch","version","readFileSync","fileURLToPath","dirname","join","chalk","boxen","chalk","ora","boxen","chalk","existsSync","join","path","confirm","chalk","confirm","ora","chalk","chalk","boxen","chalk","createSpinner","getErrorHint","boxen","chalk","Table","boxen","chalk","getErrorHint","Table","boxen","chalk","Table","boxen","config","Table","chalk","__filename","fileURLToPath","__dirname","dirname","join","readFileSync"]}
|