UNPKG

embedia

Version:

Zero-configuration AI chatbot integration CLI - direct file copy with embedded API keys

122 lines (101 loc) 3.36 kB
const fs = require('fs-extra'); const path = require('path'); const parser = require('@babel/parser'); const ASTModifier = require('./astModifier'); class SafeASTModifier { constructor() { this.astModifier = new ASTModifier(); } async modifyWithRollback(filePath, modifier) { // Create backup const backup = await this.createBackup(filePath); try { // Read current content const content = await fs.readFile(filePath, 'utf-8'); // Apply modification const modified = await modifier(content); // Validate the modified content await this.validateModifiedCode(modified, filePath); // Write the modified content await fs.writeFile(filePath, modified); // Test that the modification works await this.testModification(filePath); // Success - remove backup await this.removeBackup(backup); return { success: true, filePath }; } catch (error) { // Rollback on any error await this.rollback(filePath, backup); return { success: false, error: error.message, suggestion: this.getSuggestion(error) }; } } async createBackup(filePath) { const backupPath = `${filePath}.embedia-backup`; await fs.copy(filePath, backupPath); return backupPath; } async removeBackup(backupPath) { try { await fs.remove(backupPath); } catch (error) { // Ignore errors when removing backup } } async rollback(filePath, backupPath) { try { await fs.copy(backupPath, filePath, { overwrite: true }); await fs.remove(backupPath); } catch (error) { console.error('Failed to rollback:', error); } } async validateModifiedCode(code, filePath) { const isTypeScript = filePath.endsWith('.ts') || filePath.endsWith('.tsx'); try { // Parse to ensure valid syntax parser.parse(code, { sourceType: 'module', plugins: [ 'jsx', isTypeScript && 'typescript', 'decorators-legacy', 'dynamicImport', 'classProperties', 'optionalChaining', 'nullishCoalescingOperator' ].filter(Boolean) }); } catch (error) { throw new Error(`Invalid syntax after modification: ${error.message}`); } } async testModification(filePath) { // Basic validation - check if file exists and is readable try { await fs.access(filePath, fs.constants.R_OK); const stats = await fs.stat(filePath); if (stats.size === 0) { throw new Error('Modified file is empty'); } } catch (error) { throw new Error(`File validation failed: ${error.message}`); } } getSuggestion(error) { if (error.message.includes('Unexpected token')) { return 'The file may have custom syntax. Consider manual integration.'; } if (error.message.includes('body')) { return 'Could not find body element. The layout structure may be non-standard.'; } if (error.message.includes('Invalid syntax')) { return 'The modified code has syntax errors. This may be due to complex JSX structure.'; } return 'Automatic modification failed. See manual integration guide.'; } } module.exports = SafeASTModifier;