faj-cli
Version:
FAJ - A powerful CLI resume builder with AI enhancement and multi-format export
345 lines • 14.1 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigCommand = void 0;
const chalk_1 = __importDefault(require("chalk"));
const inquirer_1 = __importDefault(require("inquirer"));
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const ConfigManager_1 = require("../../core/config/ConfigManager");
const Logger_1 = require("../../utils/Logger");
class ConfigCommand {
logger;
configManager;
constructor() {
this.logger = new Logger_1.Logger('ConfigCommand');
this.configManager = ConfigManager_1.ConfigManager.getInstance();
}
register(program) {
const config = program
.command('config')
.description('Manage configuration settings');
config
.command('get <key>')
.description('Get configuration value')
.action(async (key) => {
try {
const value = await this.configManager.getNested(key);
if (value !== undefined) {
console.log(chalk_1.default.green(`${key}: ${JSON.stringify(value, null, 2)}`));
}
else {
console.log(chalk_1.default.yellow(`Configuration key '${key}' not found`));
}
}
catch (error) {
this.logger.error('Failed to get configuration', error);
}
});
config
.command('set <key> <value>')
.description('Set configuration value')
.action(async (key, value) => {
try {
await this.configManager.setNested(key, value);
console.log(chalk_1.default.green(`✓ ${key} set to: ${value}`));
}
catch (error) {
this.logger.error('Failed to set configuration', error);
}
});
config
.command('list')
.description('List all configuration')
.action(async () => {
try {
await this.configManager.load();
const config = await this.configManager.get('profile');
console.log(chalk_1.default.cyan('Current configuration:'));
console.log(JSON.stringify(config, null, 2));
}
catch (error) {
this.logger.error('Failed to list configuration', error);
}
});
// New command: config ai
config
.command('ai')
.description('Configure AI settings (provider, model, language)')
.option('-p, --provider <provider>', 'AI provider (gemini, openai, anthropic)')
.option('-m, --model <model>', 'AI model (e.g., gemini-1.5-flash, gpt-4)')
.option('-k, --api-key <key>', 'API key for the provider')
.option('-l, --language <lang>', 'Resume language (zh, en, ja, etc.)')
.option('--interactive', 'Interactive configuration mode')
.action(async (options) => {
try {
if (options.interactive) {
await this.configureAIInteractive();
}
else {
await this.configureAI(options);
}
}
catch (error) {
this.logger.error('Failed to configure AI settings', error);
console.error(chalk_1.default.red('Failed to configure AI settings'));
}
});
// New command: config language
config
.command('language <lang>')
.description('Set resume language (zh=中文, en=English, ja=日本語, etc.)')
.action(async (lang) => {
try {
await this.setLanguage(lang);
}
catch (error) {
this.logger.error('Failed to set language', error);
}
});
// New command: config api-key
config
.command('api-key')
.description('Securely configure API keys')
.option('-p, --provider <provider>', 'Provider name (gemini, openai, anthropic)')
.action(async (options) => {
try {
await this.configureApiKey(options.provider);
}
catch (error) {
this.logger.error('Failed to configure API key', error);
}
});
// New command: config show
config
.command('show')
.description('Show current AI configuration')
.action(async () => {
try {
await this.showConfiguration();
}
catch (error) {
this.logger.error('Failed to show configuration', error);
}
});
}
async configureAIInteractive() {
console.log(chalk_1.default.cyan('\n🤖 AI Configuration Setup\n'));
const answers = await inquirer_1.default.prompt([
{
type: 'list',
name: 'provider',
message: 'Select AI provider:',
choices: [
{ name: 'Google Gemini', value: 'gemini' },
{ name: 'OpenAI', value: 'openai' },
{ name: 'Anthropic Claude', value: 'anthropic' },
],
default: 'gemini',
},
{
type: 'input',
name: 'model',
message: 'Enter AI model (or press Enter for default):',
default: (answers) => {
switch (answers.provider) {
case 'gemini': return 'gemini-1.5-flash';
case 'openai': return 'gpt-3.5-turbo';
case 'anthropic': return 'claude-3-sonnet';
default: return '';
}
},
},
{
type: 'password',
name: 'apiKey',
message: 'Enter API key:',
mask: '*',
validate: (input) => input.length > 0 || 'API key is required',
},
{
type: 'list',
name: 'language',
message: 'Select resume language:',
choices: [
{ name: '中文 (Chinese)', value: 'zh' },
{ name: 'English', value: 'en' },
{ name: '日本語 (Japanese)', value: 'ja' },
{ name: '한국어 (Korean)', value: 'ko' },
{ name: 'Español (Spanish)', value: 'es' },
{ name: 'Français (French)', value: 'fr' },
{ name: 'Deutsch (German)', value: 'de' },
],
default: 'zh',
},
]);
await this.saveConfiguration(answers);
}
async configureAI(options) {
const updates = {};
if (options.provider) {
updates.provider = options.provider;
console.log(chalk_1.default.green(`✓ AI provider set to: ${options.provider}`));
}
if (options.model) {
updates.model = options.model;
console.log(chalk_1.default.green(`✓ AI model set to: ${options.model}`));
}
if (options.language) {
updates.language = options.language;
console.log(chalk_1.default.green(`✓ Resume language set to: ${options.language}`));
}
if (options.apiKey) {
updates.apiKey = options.apiKey;
console.log(chalk_1.default.green('✓ API key configured'));
}
if (Object.keys(updates).length > 0) {
await this.saveConfiguration(updates);
}
else {
console.log(chalk_1.default.yellow('No changes made. Use --interactive for guided setup.'));
}
}
async setLanguage(lang) {
const languageMap = {
'zh': '中文',
'en': 'English',
'ja': '日本語',
'ko': '한국어',
'es': 'Español',
'fr': 'Français',
'de': 'Deutsch',
};
if (!languageMap[lang]) {
console.log(chalk_1.default.yellow(`Unsupported language: ${lang}`));
console.log('Supported languages:', Object.keys(languageMap).join(', '));
return;
}
await this.updateEnvFile({ FAJ_RESUME_LANGUAGE: lang });
console.log(chalk_1.default.green(`✓ Resume language set to: ${languageMap[lang]} (${lang})`));
}
async configureApiKey(provider) {
if (!provider) {
const answer = await inquirer_1.default.prompt({
type: 'list',
name: 'provider',
message: 'Select provider:',
choices: ['gemini', 'openai', 'anthropic'],
});
provider = answer.provider;
}
const answer = await inquirer_1.default.prompt({
type: 'password',
name: 'apiKey',
message: `Enter ${provider.toUpperCase()} API key:`,
mask: '*',
validate: (input) => input.length > 0 || 'API key is required',
});
const envKey = `FAJ_${provider.toUpperCase()}_API_KEY`;
await this.updateEnvFile({ [envKey]: answer.apiKey });
console.log(chalk_1.default.green(`✓ ${provider} API key configured`));
console.log(chalk_1.default.gray('API key saved to .env file'));
}
async saveConfiguration(config) {
const envUpdates = {};
if (config.provider) {
envUpdates.FAJ_AI_PROVIDER = config.provider;
}
if (config.model) {
envUpdates.FAJ_AI_MODEL = config.model;
}
if (config.language) {
envUpdates.FAJ_RESUME_LANGUAGE = config.language;
}
if (config.apiKey && config.provider) {
const envKey = `FAJ_${config.provider.toUpperCase()}_API_KEY`;
envUpdates[envKey] = config.apiKey;
}
await this.updateEnvFile(envUpdates);
console.log(chalk_1.default.green('\n✓ Configuration saved successfully!'));
console.log(chalk_1.default.gray('Settings saved to .env file'));
}
async updateEnvFile(updates) {
const envPath = path.join(process.cwd(), '.env');
let content = '';
// Read existing .env file
try {
content = await fs.promises.readFile(envPath, 'utf-8');
}
catch {
// File doesn't exist, create new
}
// Update or add each key
for (const [key, value] of Object.entries(updates)) {
const regex = new RegExp(`^${key}=.*$`, 'gm');
if (regex.test(content)) {
// Update existing
content = content.replace(regex, `${key}=${value}`);
}
else {
// Add new
content += `\n${key}=${value}`;
}
}
// Write back to file
await fs.promises.writeFile(envPath, content.trim() + '\n');
}
async showConfiguration() {
console.log(chalk_1.default.cyan('\n📋 Current AI Configuration\n'));
// Read from environment
const provider = process.env.FAJ_AI_PROVIDER || 'Not set';
const model = process.env.FAJ_AI_MODEL || 'Using default';
const language = process.env.FAJ_RESUME_LANGUAGE || 'zh (default)';
// Check API keys (don't show actual keys)
const geminiKey = process.env.FAJ_GEMINI_API_KEY ? '✓ Configured' : '✗ Not set';
const openaiKey = process.env.FAJ_OPENAI_API_KEY ? '✓ Configured' : '✗ Not set';
const anthropicKey = process.env.FAJ_ANTHROPIC_API_KEY ? '✓ Configured' : '✗ Not set';
console.log(chalk_1.default.white('AI Provider:'), chalk_1.default.yellow(provider));
console.log(chalk_1.default.white('AI Model:'), chalk_1.default.yellow(model));
console.log(chalk_1.default.white('Resume Language:'), chalk_1.default.yellow(language));
console.log();
console.log(chalk_1.default.white('API Keys:'));
console.log(' Gemini:', geminiKey);
console.log(' OpenAI:', openaiKey);
console.log(' Anthropic:', anthropicKey);
console.log();
console.log(chalk_1.default.gray('Use "faj config ai --interactive" to change settings'));
}
}
exports.ConfigCommand = ConfigCommand;
//# sourceMappingURL=config.js.map
;