UNPKG

@necto-ai/pgit

Version:

Private file tracking with dual git repositories

297 lines 10.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigManager = exports.ConfigMigrationError = exports.ConfigValidationError = exports.ConfigError = void 0; const path_1 = __importDefault(require("path")); const config_types_1 = require("../types/config.types"); const config_schema_1 = require("../types/config.schema"); const zod_1 = require("zod"); const filesystem_service_1 = require("./filesystem.service"); const platform_detector_1 = require("../utils/platform.detector"); const base_error_1 = require("../errors/base.error"); /** * Configuration management errors */ class ConfigError extends base_error_1.BaseError { constructor() { super(...arguments); this.code = 'CONFIG_ERROR'; this.recoverable = true; } } exports.ConfigError = ConfigError; class ConfigValidationError extends base_error_1.BaseError { constructor() { super(...arguments); this.code = 'CONFIG_VALIDATION_ERROR'; this.recoverable = true; } } exports.ConfigValidationError = ConfigValidationError; class ConfigMigrationError extends base_error_1.BaseError { constructor() { super(...arguments); this.code = 'CONFIG_MIGRATION_ERROR'; this.recoverable = false; } } exports.ConfigMigrationError = ConfigMigrationError; /** * Configuration manager for private git CLI */ class ConfigManager { constructor(workingDir, fileSystem) { this.configPath = path_1.default.join(workingDir, config_types_1.DEFAULT_PATHS.config); this.fileSystem = fileSystem || new filesystem_service_1.FileSystemService(); } /** * Create initial configuration */ async create(projectPath, options = {}) { const now = new Date(); const projectName = path_1.default.basename(projectPath); const config = { version: config_types_1.CURRENT_CONFIG_VERSION, privateRepoPath: config_types_1.DEFAULT_PATHS.privateRepo, storagePath: config_types_1.DEFAULT_PATHS.storage, trackedPaths: [], initialized: now, settings: { ...config_types_1.DEFAULT_SETTINGS, ...options, }, metadata: { projectName, mainRepoPath: projectPath, cliVersion: config_types_1.CURRENT_CONFIG_VERSION, platform: platform_detector_1.PlatformDetector.getPlatformName(), lastModified: now, }, }; await this.save(config); return config; } /** * Load configuration from file */ async load() { if (this.cachedConfig) { return this.cachedConfig; } try { const content = await this.fileSystem.readFile(this.configPath); const jsonConfig = JSON.parse(content); const validatedConfig = config_schema_1.PrivateConfigJsonSchema.parse(jsonConfig); this.cachedConfig = validatedConfig; return validatedConfig; } catch (error) { if (error instanceof Error && error.name === 'ZodError') { throw new ConfigValidationError('Configuration data is invalid', error.message); } throw new ConfigError('Failed to load configuration', error instanceof Error ? error.message : String(error)); } } /** * Save configuration to file */ async save(config) { try { // Validate configuration const validatedConfig = config_schema_1.PrivateConfigSchema.parse(config); // Update last modified timestamp validatedConfig.metadata.lastModified = new Date(); // Transform for JSON serialization const jsonConfig = this.transformToJson(validatedConfig); // Write to file const configContent = JSON.stringify(jsonConfig, null, 2); await this.fileSystem.writeFileAtomic(this.configPath, configContent); // Update cache this.cachedConfig = validatedConfig; } catch (error) { if (error instanceof zod_1.ZodError) { // Extract specific validation error messages from ZodError const zodError = error; const errors = zodError.issues || []; const errorMessages = errors.map((err) => err.message); // If all errors are "Required", use generic message for better UX const allRequired = errors.length > 0 && errors.every((err) => err.message === 'Required'); const message = allRequired ? 'Configuration data is invalid' : errorMessages.join('; '); throw new ConfigValidationError(message, error.message); } throw new ConfigError('Failed to save configuration', error instanceof Error ? error.message : String(error)); } } /** * Update git exclude settings */ async updateGitExcludeSettings(newSettings) { const config = await this.load(); config.settings.gitExclude = { ...config.settings.gitExclude, ...newSettings, }; await this.save(config); return config; } /** * Get current git exclude settings */ async getGitExcludeSettings() { const config = await this.load(); return config.settings.gitExclude; } /** * Reset git exclude settings to defaults */ async resetGitExcludeSettings() { const config = await this.load(); config.settings.gitExclude = { ...config_types_1.DEFAULT_GIT_EXCLUDE_SETTINGS }; await this.save(config); return config; } /** * Add a tracked path */ async addTrackedPath(filePath) { const config = await this.load(); const normalizedPath = path_1.default.normalize(filePath); if (!config.trackedPaths.includes(normalizedPath)) { config.trackedPaths.push(normalizedPath); await this.save(config); } } /** * Remove a tracked path */ async removeTrackedPath(filePath) { const config = await this.load(); const normalizedPath = path_1.default.normalize(filePath); const index = config.trackedPaths.indexOf(normalizedPath); if (index !== -1) { config.trackedPaths.splice(index, 1); await this.save(config); } } /** * Add multiple tracked paths */ async addMultipleTrackedPaths(filePaths) { const config = await this.load(); const normalizedPaths = filePaths.map(fp => path_1.default.normalize(fp)); const uniquePaths = normalizedPaths.filter(np => !config.trackedPaths.includes(np)); if (uniquePaths.length > 0) { config.trackedPaths.push(...uniquePaths); await this.save(config); } } /** * Remove multiple tracked paths */ async removeMultipleTrackedPaths(filePaths) { const config = await this.load(); const normalizedPaths = filePaths.map(fp => path_1.default.normalize(fp)); const notTracked = []; for (const normalizedPath of normalizedPaths) { const index = config.trackedPaths.indexOf(normalizedPath); if (index !== -1) { config.trackedPaths.splice(index, 1); } else { notTracked.push(normalizedPath); } } if (notTracked.length > 0) { throw new ConfigError(`Some paths were not tracked: ${notTracked.join(', ')}`); } await this.save(config); } /** * Check if configuration exists */ async exists() { return await this.fileSystem.isFile(this.configPath); } /** * Get cached configuration */ getCached() { return this.cachedConfig; } /** * Clear configuration cache */ clearCache() { this.cachedConfig = undefined; } /** * Get configuration file path */ getConfigPath() { return this.configPath; } /** * Get configuration health status */ async getHealth() { try { const exists = await this.exists(); if (!exists) { return { exists: false, valid: false, errors: ['Configuration file does not exist'], needsMigration: false, currentVersion: '', targetVersion: config_types_1.CURRENT_CONFIG_VERSION, }; } const config = await this.load(); const needsMigration = config.version !== config_types_1.CURRENT_CONFIG_VERSION; return { exists: true, valid: true, errors: [], needsMigration, currentVersion: config.version, targetVersion: config_types_1.CURRENT_CONFIG_VERSION, }; } catch (error) { return { exists: true, valid: false, errors: [error instanceof Error ? error.message : String(error)], needsMigration: false, currentVersion: '', targetVersion: config_types_1.CURRENT_CONFIG_VERSION, }; } } /** * Transform configuration to JSON format */ transformToJson(config) { return { version: config.version, privateRepoPath: config.privateRepoPath, storagePath: config.storagePath, trackedPaths: config.trackedPaths, initialized: config.initialized.toISOString(), lastCleanup: config.lastCleanup?.toISOString(), settings: config.settings, metadata: { projectName: config.metadata.projectName, mainRepoPath: config.metadata.mainRepoPath, cliVersion: config.metadata.cliVersion, platform: config.metadata.platform, lastModified: config.metadata.lastModified.toISOString(), }, }; } } exports.ConfigManager = ConfigManager; //# sourceMappingURL=config.manager.js.map