UNPKG

linear-cmd

Version:

A GitHub CLI-like tool for Linear - manage issues, accounts, and more

188 lines (187 loc) 6.29 kB
import { existsSync, mkdirSync } from 'node:fs'; import { getConfigPaths } from '../constants.js'; import { linearConfigSchema, userMetadataSchema } from '../types/local.js'; import { readJson5, writeJson5 } from '../utils/json-utils.js'; export class ConfigManager { userMetadata = null; config = null; constructor() { this.ensureConfigDirectory(); this.initializeUserMetadata(); } ensureConfigDirectory() { const configPaths = getConfigPaths(); if (!existsSync(configPaths.configDir)) { mkdirSync(configPaths.configDir, { recursive: true }); } } initializeUserMetadata() { const configPaths = getConfigPaths(); if (!existsSync(configPaths.userMetadataFile)) { this.createDefaultUserMetadata(); } this.loadUserMetadata(); } createDefaultUserMetadata() { const configPaths = getConfigPaths(); const defaultMetadata = { config_path: configPaths.defaultConfigFile }; writeJson5(configPaths.userMetadataFile, defaultMetadata); } loadUserMetadata() { const configPaths = getConfigPaths(); try { const data = readJson5(configPaths.userMetadataFile); const validated = userMetadataSchema.parse(data); this.userMetadata = validated; } catch (error) { throw new Error(`Failed to load user metadata: ${error instanceof Error ? error.message : 'Unknown error'}`); } } getConfigPath() { if (!this.userMetadata) { throw new Error('User metadata not loaded'); } return this.userMetadata.config_path; } loadConfig(forceReload = false) { if (this.config && !forceReload) { return this.config; } const configPath = this.getConfigPath(); if (!existsSync(configPath)) { this.createDefaultConfig(); } try { const data = readJson5(configPath); const validated = linearConfigSchema.parse(data); this.config = validated; return this.config; } catch (error) { throw new Error(`Failed to load config: ${error instanceof Error ? error.message : 'Unknown error'}`); } } createDefaultConfig() { const defaultConfig = { accounts: {} }; const configPath = this.getConfigPath(); writeJson5(configPath, defaultConfig); } saveConfig() { if (!this.config) { throw new Error('No config to save'); } const configPath = this.getConfigPath(); writeJson5(configPath, this.config); } // Public API Methods async addAccount(name, apiKey, teamId) { const config = this.loadConfig(); if (config.accounts[name]) { throw new Error(`Account '${name}' already exists`); } const account = { name, api_key: apiKey, team_id: teamId }; config.accounts[name] = account; const accountCount = Object.keys(config.accounts).length; if (!config.activeAccountName || accountCount === 1) { config.activeAccountName = name; } this.saveConfig(); } async removeAccount(name) { const config = this.loadConfig(); if (!config.accounts[name]) { throw new Error(`Account '${name}' not found`); } delete config.accounts[name]; if (config.activeAccountName === name) { const remainingAccounts = Object.keys(config.accounts); config.activeAccountName = remainingAccounts.length > 0 ? remainingAccounts[0] : undefined; } this.saveConfig(); } getActiveAccount() { const config = this.loadConfig(true); if (!config.activeAccountName) { return null; } return config.accounts[config.activeAccountName] || null; } getActiveAccountName() { const config = this.loadConfig(true); return config.activeAccountName || null; } setActiveAccount(name) { const config = this.loadConfig(); if (!config.accounts[name]) { return false; } config.activeAccountName = name; this.saveConfig(); return true; } getAllAccounts() { const config = this.loadConfig(true); return Object.values(config.accounts); } getAccount(name) { const config = this.loadConfig(true); return config.accounts[name] || null; } listAccounts() { const config = this.loadConfig(true); return Object.entries(config.accounts).map(([name, account]) => ({ name, teamId: account.team_id })); } updateAccountApiKey(name, apiKey) { const config = this.loadConfig(); if (!config.accounts[name]) { throw new Error(`Account '${name}' not found`); } config.accounts[name].api_key = apiKey; this.saveConfig(); } findAccountByWorkspace(workspace) { const config = this.loadConfig(true); const accounts = Object.values(config.accounts); return accounts.find((a) => a.workspaces?.includes(workspace)) || null; } async updateAccountWorkspaces(accountId, workspaces) { const config = this.loadConfig(); if (!config.accounts[accountId]) { throw new Error(`Account '${accountId}' not found`); } config.accounts[accountId].workspaces = workspaces; this.saveConfig(); } markCompletionInstalled() { const config = this.loadConfig(); if (!config.settings) { config.settings = {}; } config.settings.completion_installed = true; this.saveConfig(); } markCompletionUninstalled() { const config = this.loadConfig(); if (!config.settings) { config.settings = {}; } config.settings.completion_installed = false; this.saveConfig(); } isCompletionInstalled() { const config = this.loadConfig(); return config.settings?.completion_installed === true; } }