/ scripts / demo-file-operations.js
demo-file-operations.js
  1  #!/usr/bin/env node
  2  /**
  3   * Demo: File Operations Module
  4   *
  5   * Demonstrates safe file operations with backup/restore capabilities.
  6   * This script creates a test file, edits it, and shows various features.
  7   */
  8  
  9  import {
 10    readFile,
 11    writeFile,
 12    editFile,
 13    backupFile,
 14    restoreBackup,
 15    validateJavaScript,
 16    getFileContext,
 17    listBackups,
 18    cleanupBackups,
 19  } from '../src/agents/utils/file-operations.js';
 20  import fs from 'fs/promises';
 21  
 22  const TEST_FILE = 'tests/agents/fixtures/demo-file.js';
 23  
 24  async function demo() {
 25    console.log('='.repeat(60));
 26    console.log('File Operations Module Demo');
 27    console.log('='.repeat(60));
 28    console.log();
 29  
 30    // Ensure fixtures directory exists
 31    await fs.mkdir('tests/agents/fixtures', { recursive: true });
 32  
 33    try {
 34      // Step 1: Create initial file
 35      console.log('Step 1: Creating initial file...');
 36      const initialCode = `const greet = (name) => {
 37    return 'Hello, ' + name;
 38  };
 39  
 40  export default greet;
 41  `;
 42  
 43      const result1 = await writeFile(TEST_FILE, initialCode);
 44      console.log('✓ File created successfully');
 45      console.log(`  Backup: ${result1.backupPath || 'N/A (new file)'}`);
 46      console.log();
 47  
 48      // Step 2: Read file and get context
 49      console.log('Step 2: Reading file and analyzing context...');
 50      const file = await readFile(TEST_FILE);
 51      console.log(`✓ File size: ${file.size} bytes`);
 52      console.log(`✓ Last modified: ${file.lastModified.toISOString()}`);
 53  
 54      const context = await getFileContext(TEST_FILE);
 55      console.log(`✓ Imports: ${context.imports.length}`);
 56      console.log(`✓ Dependencies: ${context.dependencies.length}`);
 57      console.log();
 58  
 59      // Step 3: Edit file
 60      console.log('Step 3: Editing file (fixing string concatenation)...');
 61      const result2 = await editFile(TEST_FILE, {
 62        oldContent: "return 'Hello, ' + name;",
 63        newContent: 'return `Hello, ${name}!`;',
 64      });
 65  
 66      console.log('✓ File edited successfully');
 67      console.log('✓ Diff:');
 68      console.log(
 69        result2.diff
 70          .split('\n')
 71          .slice(0, 10)
 72          .map(line => `  ${line}`)
 73          .join('\n')
 74      );
 75      console.log();
 76  
 77      // Step 4: Validate JavaScript
 78      console.log('Step 4: Validating syntax...');
 79      const { content } = await readFile(TEST_FILE);
 80      const validation = await validateJavaScript(content);
 81      console.log(`✓ Valid: ${validation.valid}`);
 82      console.log(`✓ Errors: ${validation.errors.length}`);
 83      console.log();
 84  
 85      // Step 5: List backups
 86      console.log('Step 5: Listing backups...');
 87      const backups = await listBackups(TEST_FILE);
 88      console.log(`✓ Found ${backups.length} backup(s)`);
 89      backups.forEach((backup, i) => {
 90        console.log(`  ${i + 1}. ${backup}`);
 91      });
 92      console.log();
 93  
 94      // Step 6: Create multiple backups
 95      console.log('Step 6: Creating multiple backups...');
 96      for (let i = 0; i < 3; i++) {
 97        await new Promise(resolve => setTimeout(resolve, 100));
 98        await backupFile(TEST_FILE);
 99      }
100      const allBackups = await listBackups(TEST_FILE);
101      console.log(`✓ Now have ${allBackups.length} backup(s)`);
102      console.log();
103  
104      // Step 7: Cleanup old backups
105      console.log('Step 7: Cleaning up old backups (keep 2)...');
106      const deleted = await cleanupBackups(TEST_FILE, 2);
107      console.log(`✓ Deleted ${deleted} old backup(s)`);
108      const remainingBackups = await listBackups(TEST_FILE);
109      console.log(`✓ Remaining: ${remainingBackups.length} backup(s)`);
110      console.log();
111  
112      // Step 8: Restore from backup
113      console.log('Step 8: Restoring from most recent backup...');
114      if (remainingBackups.length > 0) {
115        await restoreBackup(remainingBackups[0]);
116        console.log('✓ Restored successfully');
117      }
118      console.log();
119  
120      // Step 9: Attempt invalid operation (will fail safely)
121      console.log('Step 9: Testing error handling (invalid syntax)...');
122      try {
123        await writeFile(TEST_FILE, 'const x = ;'); // Syntax error
124        console.log('✗ Should have failed!');
125      } catch (error) {
126        console.log('✓ Correctly rejected invalid syntax');
127        console.log(`  Error: ${error.message.split('\n')[0]}`);
128  
129        // Verify file was restored from backup
130        const restoredContent = await readFile(TEST_FILE);
131        console.log('✓ Original content preserved (restored from backup)');
132      }
133      console.log();
134  
135      // Final summary
136      console.log('='.repeat(60));
137      console.log('Demo Complete!');
138      console.log('='.repeat(60));
139      console.log();
140      console.log('Key Features Demonstrated:');
141      console.log('  ✓ Safe file writing with automatic backups');
142      console.log('  ✓ Atomic writes (temp file → move)');
143      console.log('  ✓ Syntax validation before writing');
144      console.log('  ✓ Diff generation for all edits');
145      console.log('  ✓ Context awareness (imports, dependencies)');
146      console.log('  ✓ Backup management (list, cleanup, restore)');
147      console.log('  ✓ Error handling with automatic rollback');
148      console.log();
149    } catch (error) {
150      console.error('Demo failed:', error);
151      process.exit(1);
152    }
153  }
154  
155  demo();