UNPKG

ai-coding-assistants-setup

Version:

Setup tool for integrating AI coding assistants into development workflows

143 lines 5.53 kB
import fs from 'fs-extra'; import path from 'path'; import { createInterface } from 'readline'; import { Feedback } from './feedback.js'; /** * Options for file merging */ export var MergeOption; (function (MergeOption) { MergeOption["OVERWRITE"] = "overwrite"; MergeOption["KEEP_BOTH"] = "keep-both"; MergeOption["SKIP"] = "skip"; })(MergeOption || (MergeOption = {})); /** * File merger utility to handle merging files from this package into a parent project */ export class FileMerger { /** * Merge a file from the source directory to the target directory * * @param sourcePath Source file path * @param targetPath Target file path * @param defaultOption Default option if not in interactive mode * @param interactive Whether to prompt the user for confirmation * @returns Promise resolving to true if the file was merged successfully */ static async mergeFile(sourcePath, targetPath, defaultOption = MergeOption.SKIP, interactive = true) { // Check if source file exists if (!fs.existsSync(sourcePath)) { Feedback.error(`Source file does not exist: ${sourcePath}`); return false; } // If target file doesn't exist, just copy it if (!fs.existsSync(targetPath)) { try { // Ensure target directory exists fs.mkdirpSync(path.dirname(targetPath)); // Copy the file await fs.copyFile(sourcePath, targetPath); Feedback.success(`Created new file: ${targetPath}`); return true; } catch (error) { Feedback.error(`Failed to copy file to ${targetPath}: ${error}`); return false; } } // Target file exists, prompt user for action if in interactive mode let option = defaultOption; if (interactive) { option = await this.promptUser(targetPath); } try { switch (option) { case MergeOption.OVERWRITE: await fs.copyFile(sourcePath, targetPath); Feedback.success(`Overwrote existing file: ${targetPath}`); return true; case MergeOption.KEEP_BOTH: // eslint-disable-next-line no-case-declarations const backupPath = this.generateBackupPath(targetPath); await fs.copyFile(sourcePath, backupPath); Feedback.info(`Kept existing file. New file saved to: ${backupPath}`); return true; case MergeOption.SKIP: Feedback.info(`Skipped file: ${targetPath}`); return true; default: Feedback.warning(`Unknown option: ${option}. Skipping file.`); return false; } } catch (error) { Feedback.error(`Error merging file ${targetPath}: ${error}`); return false; } } /** * Prompt the user for what to do with an existing file * * @param targetPath Target file path * @returns Promise resolving to the selected merge option */ static async promptUser(targetPath) { const rl = createInterface({ input: process.stdin, output: process.stdout, }); return new Promise(resolve => { Feedback.warning(`File already exists: ${targetPath}`); rl.question('❓ What would you like to do?\n' + ' [o] Overwrite existing file\n' + ' [k] Keep both (saves new file with .new extension)\n' + ' [s] Skip this file\n' + 'Choose an option [o/k/s]: ', answer => { rl.close(); switch (answer.toLowerCase()) { case 'o': resolve(MergeOption.OVERWRITE); break; case 'k': resolve(MergeOption.KEEP_BOTH); break; case 's': default: resolve(MergeOption.SKIP); break; } }); }); } /** * Generate a backup path for a file * * @param filePath Original file path * @returns Backup file path with .new extension */ static generateBackupPath(filePath) { return `${filePath}.new`; } /** * Merge multiple files from source directory to target directory * * @param files Map of source files to target files * @param defaultOption Default option if not in interactive mode * @param interactive Whether to prompt the user for confirmation * @returns Promise resolving to number of successfully merged files */ static async mergeFiles(files, defaultOption = MergeOption.SKIP, interactive = true) { let successCount = 0; Feedback.section('Merging Files'); for (const [sourcePath, targetPath] of files.entries()) { const success = await this.mergeFile(sourcePath, targetPath, defaultOption, interactive); if (success) { successCount++; } } Feedback.info(`Completed merging ${successCount} of ${files.size} files`); return successCount; } } export default FileMerger; //# sourceMappingURL=file-merger.js.map