UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

362 lines 13.8 kB
"use strict"; 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; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.AccountConfigManager = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const os = __importStar(require("os")); const account_types_1 = require("../types/account.types"); const account_crypto_1 = require("./account-crypto"); const DEFAULT_CONFIG = { version: '1.0.0', configDir: '.polyv', configFileName: 'accounts.json', filePermissions: 0o600 }; class AccountConfigManager { constructor(configPath, masterKey) { if (configPath) { if (configPath.endsWith('.json')) { this.configPath = configPath; } else { this.configPath = path.join(configPath, DEFAULT_CONFIG.configFileName); } } else { this.configPath = this.getDefaultConfigPath(); } this.crypto = new account_crypto_1.AccountCrypto(masterKey); } getDefaultConfigPath() { const homeDir = process.env['HOME'] || os.homedir(); const configDir = path.join(homeDir, DEFAULT_CONFIG.configDir); return path.join(configDir, DEFAULT_CONFIG.configFileName); } ensureConfigDir() { const configDir = path.dirname(this.configPath); if (!fs.existsSync(configDir)) { fs.mkdirSync(configDir, { recursive: true, mode: 0o700 }); } } setSecurePermissions(filePath) { try { fs.chmodSync(filePath, DEFAULT_CONFIG.filePermissions); } catch (error) { console.warn(`Warning: Could not set file permissions for ${filePath}`); } } validateAccountConfig(config) { const { name, appId, appSecret } = config; if (!name || typeof name !== 'string') { throw new Error('Account name is required and must be a string'); } if (!account_types_1.AccountConfigValidation.name.pattern.test(name)) { throw new Error('Account name can only contain letters, numbers, underscores, and hyphens'); } if (name.length > account_types_1.AccountConfigValidation.name.maxLength) { throw new Error(`Account name must be ${account_types_1.AccountConfigValidation.name.maxLength} characters or less`); } if (!appId || typeof appId !== 'string') { throw new Error('App ID is required and must be a string'); } if (!account_types_1.AccountConfigValidation.appId.pattern.test(appId)) { throw new Error('App ID can only contain letters and numbers'); } if (appId.length < account_types_1.AccountConfigValidation.appId.minLength || appId.length > account_types_1.AccountConfigValidation.appId.maxLength) { throw new Error(`App ID must be between ${account_types_1.AccountConfigValidation.appId.minLength} and ${account_types_1.AccountConfigValidation.appId.maxLength} characters`); } if (!appSecret || typeof appSecret !== 'string') { throw new Error('App Secret is required and must be a string'); } if (appSecret.length < account_types_1.AccountConfigValidation.appSecret.minLength || appSecret.length > account_types_1.AccountConfigValidation.appSecret.maxLength) { throw new Error(`App Secret must be between ${account_types_1.AccountConfigValidation.appSecret.minLength} and ${account_types_1.AccountConfigValidation.appSecret.maxLength} characters`); } } loadAccountsStore() { try { if (!fs.existsSync(this.configPath)) { return this.createEmptyStore(); } const fileContent = fs.readFileSync(this.configPath, 'utf8'); const store = JSON.parse(fileContent); if (!store.version || !store.accounts || !store.metadata) { throw new Error('Invalid accounts store format'); } return store; } catch (error) { if (error instanceof SyntaxError) { throw new Error(`Invalid JSON in accounts configuration file: ${error.message}`); } throw new Error(`Failed to load accounts configuration: ${error instanceof Error ? error.message : 'Unknown error'}`); } } saveAccountsStore(store) { try { this.ensureConfigDir(); store.metadata.updatedAt = new Date().toISOString(); const tempPath = `${this.configPath}.tmp`; fs.writeFileSync(tempPath, JSON.stringify(store, null, 2), 'utf8'); this.setSecurePermissions(tempPath); fs.renameSync(tempPath, this.configPath); } catch (error) { throw new Error(`Failed to save accounts configuration: ${error instanceof Error ? error.message : 'Unknown error'}`); } } createEmptyStore() { const now = new Date().toISOString(); return { version: DEFAULT_CONFIG.version, accounts: {}, metadata: { createdAt: now, updatedAt: now } }; } addAccount(name, appId, appSecret, userId, environment, baseUrl) { try { this.validateAccountConfig({ name, appId, appSecret }); const store = this.loadAccountsStore(); if (store.accounts[name]) { return { success: false, message: `Account '${name}' already exists. Use a different name or remove the existing account first.` }; } const encryptedSecret = this.crypto.encryptSimple(appSecret); const now = new Date().toISOString(); const accountConfig = { name, appId, appSecret: encryptedSecret, ...(userId && { userId }), ...(environment && { environment: environment }), ...(baseUrl && { baseUrl }), createdAt: now, updatedAt: now }; store.accounts[name] = accountConfig; this.saveAccountsStore(store); return { success: true, message: `Account '${name}' added successfully.`, account: { ...accountConfig, appSecret: '[encrypted]' } }; } catch (error) { return { success: false, message: error instanceof Error ? error.message : 'Unknown error occurred' }; } } removeAccount(name) { try { const store = this.loadAccountsStore(); if (!store.accounts[name]) { return { success: false, message: `Account '${name}' not found.` }; } delete store.accounts[name]; this.saveAccountsStore(store); return { success: true, message: `Account '${name}' removed successfully.` }; } catch (error) { return { success: false, message: error instanceof Error ? error.message : 'Unknown error occurred' }; } } getAccount(name) { try { const store = this.loadAccountsStore(); const account = store.accounts[name]; if (!account) { return null; } const decryptedSecret = this.crypto.decryptSimple(account.appSecret); return { ...account, appSecret: decryptedSecret }; } catch (error) { throw new Error(`Failed to get account '${name}': ${error instanceof Error ? error.message : 'Unknown error'}`); } } listAccounts() { try { const store = this.loadAccountsStore(); return Object.values(store.accounts).map(account => ({ name: account.name, appId: account.appId, ...(account.userId && { userId: account.userId }), ...(account.environment && { environment: account.environment }), ...(account.baseUrl && { baseUrl: account.baseUrl }), createdAt: account.createdAt, updatedAt: account.updatedAt })); } catch (error) { throw new Error(`Failed to list accounts: ${error instanceof Error ? error.message : 'Unknown error'}`); } } accountExists(name) { try { const store = this.loadAccountsStore(); return name in store.accounts; } catch { return false; } } getConfigPath() { return this.configPath; } backupConfig(backupPath) { const backup = backupPath || `${this.configPath}.backup.${Date.now()}`; if (fs.existsSync(this.configPath)) { fs.copyFileSync(this.configPath, backup); this.setSecurePermissions(backup); } return backup; } restoreConfig(backupPath) { if (!fs.existsSync(backupPath)) { throw new Error(`Backup file not found: ${backupPath}`); } this.ensureConfigDir(); fs.copyFileSync(backupPath, this.configPath); this.setSecurePermissions(this.configPath); } validateConfig() { try { const store = this.loadAccountsStore(); for (const account of Object.values(store.accounts)) { this.crypto.decryptSimple(account.appSecret); } return true; } catch { return false; } } setDefaultAccount(accountName) { try { const store = this.loadAccountsStore(); if (!store.accounts[accountName]) { const availableAccounts = Object.keys(store.accounts); const suggestion = availableAccounts.length > 0 ? `\n\n可用账号: ${availableAccounts.join(', ')}` : '\n\n当前没有配置任何账号。使用 \'polyv-live-cli account add <account-name>\' 添加账号。'; return { success: false, message: `账号 '${accountName}' 不存在。${suggestion}` }; } store.defaultAccount = accountName; this.saveAccountsStore(store); return { success: true, message: `已将账号 '${accountName}' 设置为默认账号。` }; } catch (error) { return { success: false, message: error instanceof Error ? error.message : '设置默认账号时发生未知错误' }; } } unsetDefaultAccount() { try { const store = this.loadAccountsStore(); if (!store.defaultAccount) { return { success: false, message: '当前没有设置默认账号。' }; } const previousDefault = store.defaultAccount; delete store.defaultAccount; this.saveAccountsStore(store); return { success: true, message: `已取消 '${previousDefault}' 的默认账号设置。` }; } catch (error) { return { success: false, message: error instanceof Error ? error.message : '取消默认账号时发生未知错误' }; } } getDefaultAccount() { try { const store = this.loadAccountsStore(); return store.defaultAccount || null; } catch { return null; } } getDefaultAccountConfig() { try { const defaultAccountName = this.getDefaultAccount(); if (!defaultAccountName) { return null; } return this.getAccount(defaultAccountName); } catch { return null; } } } exports.AccountConfigManager = AccountConfigManager; //# sourceMappingURL=account-config.js.map