linear-cmd
Version:
A GitHub CLI-like tool for Linear - manage issues, accounts, and more
143 lines (142 loc) • 4.7 kB
JavaScript
import * as fs from 'fs';
import { CONFIG_PATHS } 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() {
if (!fs.existsSync(CONFIG_PATHS.configDir)) {
fs.mkdirSync(CONFIG_PATHS.configDir, { recursive: true });
}
}
initializeUserMetadata() {
if (!fs.existsSync(CONFIG_PATHS.userMetadataFile)) {
this.createDefaultUserMetadata();
}
this.loadUserMetadata();
}
createDefaultUserMetadata() {
const defaultMetadata = {
config_path: CONFIG_PATHS.defaultConfigFile
};
writeJson5(CONFIG_PATHS.userMetadataFile, defaultMetadata);
}
loadUserMetadata() {
try {
const data = readJson5(CONFIG_PATHS.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() {
if (this.config) {
return this.config;
}
const configPath = this.getConfigPath();
if (!fs.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: {},
settings: {
max_results: 50,
date_format: 'relative',
auto_update_accounts: true
}
};
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;
// No longer set as active automatically
this.saveConfig();
}
async removeAccount(name) {
const config = this.loadConfig();
if (!config.accounts[name]) {
throw new Error(`Account '${name}' not found`);
}
delete config.accounts[name];
// No longer manage active account
this.saveConfig();
}
// Active account methods removed - accounts must be specified explicitly
getAllAccounts() {
const config = this.loadConfig();
return Object.values(config.accounts);
}
getAccount(name) {
const config = this.loadConfig();
return config.accounts[name] || null;
}
listAccounts() {
const config = this.loadConfig();
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 accounts = this.getAllAccounts();
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();
}
}