Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | 2x 2x 2x 2x | /**
* Configuration Manager
* Handles CLI configuration storage and retrieval
*/
const fs = require('fs-extra')
const path = require('path')
const os = require('os')
class ConfigManager {
static getConfigPath() {
// Use XDG config directory or fallback to home
const configDir = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config')
return path.join(configDir, 'vaultace', 'config.json')
}
static getConfig() {
try {
const configPath = this.getConfigPath()
if (!fs.existsSync(configPath)) {
return this.getDefaultConfig()
}
const config = fs.readJsonSync(configPath)
// Merge with defaults to ensure all keys exist
return {
...this.getDefaultConfig(),
...config
}
} catch (error) {
console.warn(`Config read error: ${error.message}`)
return this.getDefaultConfig()
}
}
static getDefaultConfig() {
return {
apiUrl: 'https://api.vaultace.co',
auth: {
accessToken: null,
refreshToken: null,
expiresAt: null
},
defaults: {
severity: 'medium',
format: 'table',
aiPatterns: true,
respectGitignore: true
},
preferences: {
autoUpdate: true,
verbose: false,
colorOutput: true
}
}
}
static saveConfig(config) {
try {
const configPath = this.getConfigPath()
// Ensure config directory exists
fs.ensureDirSync(path.dirname(configPath))
// Write config with proper permissions
fs.writeJsonSync(configPath, config, { spaces: 2, mode: 0o600 })
} catch (error) {
throw new Error(`Failed to save config: ${error.message}`)
}
}
static set(key, value) {
const config = this.getConfig()
// Handle nested keys (e.g., "defaults.severity")
const keys = key.split('.')
let current = config
for (let i = 0; i < keys.length - 1; i++) {
const k = keys[i]
if (!current[k] || typeof current[k] !== 'object') {
current[k] = {}
}
current = current[k]
}
current[keys[keys.length - 1]] = value
this.saveConfig(config)
}
static get(key) {
const config = this.getConfig()
// Handle nested keys
const keys = key.split('.')
let current = config
for (const k of keys) {
if (current && typeof current === 'object' && k in current) {
current = current[k]
} else {
return undefined
}
}
return current
}
static setAuth(authData) {
const config = this.getConfig()
config.auth = {
...config.auth,
...authData
}
this.saveConfig(config)
}
static clearAuth() {
const config = this.getConfig()
config.auth = {
accessToken: null,
refreshToken: null,
expiresAt: null
}
this.saveConfig(config)
}
static isAuthenticated() {
const config = this.getConfig()
return !!(config.auth?.accessToken && config.auth?.refreshToken)
}
static isTokenExpired() {
const config = this.getConfig()
if (!config.auth?.expiresAt) {
return true
}
// Add 5 minute buffer for token refresh
return Date.now() > (config.auth.expiresAt - 300000)
}
static reset() {
const defaultConfig = this.getDefaultConfig()
this.saveConfig(defaultConfig)
}
static validateConfig(config = null) {
const cfg = config || this.getConfig()
// Validate API URL
if (cfg.apiUrl) {
try {
new URL(cfg.apiUrl)
} catch {
throw new Error('Invalid API URL format')
}
}
// Validate severity levels
const validSeverities = ['low', 'medium', 'high', 'critical']
if (cfg.defaults?.severity && !validSeverities.includes(cfg.defaults.severity)) {
throw new Error(`Invalid severity level. Must be one of: ${validSeverities.join(', ')}`)
}
// Validate output formats
const validFormats = ['table', 'json', 'csv', 'sarif']
if (cfg.defaults?.format && !validFormats.includes(cfg.defaults.format)) {
throw new Error(`Invalid output format. Must be one of: ${validFormats.join(', ')}`)
}
return true
}
// Migration helpers
static migrate() {
try {
const config = this.getConfig()
let migrated = false
// Example migration: rename old keys
if (config.api_url) {
config.apiUrl = config.api_url
delete config.api_url
migrated = true
}
if (migrated) {
this.saveConfig(config)
console.log(chalk.blue('ℹ️ Configuration migrated to latest format'))
}
} catch (error) {
console.warn(`Config migration warning: ${error.message}`)
}
}
}
module.exports = ConfigManager |