UNPKG

@xec-sh/cli

Version:

Xec: The Universal Shell for TypeScript

133 lines 4.55 kB
import { EnvSecretProvider } from './providers/env.js'; import { LocalSecretProvider } from './providers/local.js'; import { SecretError } from './types.js'; export class SecretManager { constructor(config) { this.initialized = false; this.config = config || { type: 'local' }; this.provider = this.createProvider(); } async initialize() { if (this.initialized) return; await this.provider.initialize(); this.initialized = true; } async ensureInitialized() { if (!this.initialized) { await this.initialize(); } } async get(key) { await this.ensureInitialized(); this.validateKey(key); try { return await this.provider.get(key); } catch (error) { throw new SecretError(`Failed to get secret: ${error instanceof Error ? error.message : 'Unknown error'}`, 'GET_ERROR', key); } } async getRequired(key) { const value = await this.get(key); if (value === null) { throw new SecretError(`Required secret '${key}' not found`, 'SECRET_NOT_FOUND', key); } return value; } async set(key, value) { await this.ensureInitialized(); this.validateKey(key); this.validateValue(value); try { return await this.provider.set(key, value); } catch (error) { throw new SecretError(`Failed to set secret: ${error instanceof Error ? error.message : 'Unknown error'}`, 'SET_ERROR', key); } } async delete(key) { await this.ensureInitialized(); this.validateKey(key); return this.provider.delete(key); } async list() { await this.ensureInitialized(); return this.provider.list(); } async has(key) { await this.ensureInitialized(); this.validateKey(key); return this.provider.has(key); } async getMany(keys) { const results = {}; await Promise.all(keys.map(async (key) => { results[key] = await this.get(key); })); return results; } async setMany(secrets) { await Promise.all(Object.entries(secrets).map(([key, value]) => this.set(key, value))); } async deleteMany(keys) { await Promise.all(keys.map(key => this.delete(key))); } async clear() { const keys = await this.list(); await this.deleteMany(keys); } getProviderType() { return this.config.type; } async updateProvider(config) { this.config = config; this.provider = this.createProvider(); this.initialized = false; await this.initialize(); } createProvider() { switch (this.config.type) { case 'local': return new LocalSecretProvider(this.config.config); case 'env': return new EnvSecretProvider(this.config.config); case 'vault': case 'aws-secrets': case '1password': throw new SecretError(`Provider '${this.config.type}' not yet implemented`, 'PROVIDER_NOT_IMPLEMENTED'); default: throw new SecretError(`Unknown secret provider type: ${this.config.type}`, 'INVALID_PROVIDER_TYPE'); } } validateKey(key) { if (!key || typeof key !== 'string') { throw new SecretError('Secret key must be a non-empty string', 'INVALID_KEY'); } if (!/^[a-zA-Z0-9_\-\.]+$/.test(key)) { throw new SecretError('Secret key must contain only alphanumeric characters, underscores, dashes, and dots', 'INVALID_KEY_FORMAT', key); } if (key.length > 256) { throw new SecretError('Secret key must be 256 characters or less', 'KEY_TOO_LONG', key); } } validateValue(value) { if (typeof value !== 'string') { throw new SecretError('Secret value must be a string', 'INVALID_VALUE'); } if (value.length === 0) { throw new SecretError('Secret value cannot be empty', 'EMPTY_VALUE'); } if (value.length > 64 * 1024) { throw new SecretError('Secret value must be 64KB or less', 'VALUE_TOO_LARGE'); } } } let defaultManager = null; export function getDefaultSecretManager(config) { if (!defaultManager) { defaultManager = new SecretManager(config); } return defaultManager; } //# sourceMappingURL=manager.js.map