From e2a135aa3d34c99c800a8e6659da528702b5fed7 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Mon, 24 Aug 2026 19:04:15 +0100 Subject: [PATCH] Enhance schema synchronization by adding change detection and statistics tracking This commit updates the `syncModelsWithWS` function to include detailed statistics on schema synchronization, tracking the number of added, updated, and unchanged files. The `syncDirectory` function is modified to read file contents and determine if changes exist before copying, utilizing a new utility function, `fileHasChanges`, for comparison. Additionally, a helper function, `readFileIfExists`, is introduced to handle file reading more gracefully. These enhancements improve the efficiency and clarity of the schema synchronization process. --- fcdev.js | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/fcdev.js b/fcdev.js index b755b45..bddf84b 100644 --- a/fcdev.js +++ b/fcdev.js @@ -1,3 +1,4 @@ +import { diffLines } from 'diff'; import fs from 'fs/promises'; import path from 'path'; import { fileURLToPath } from 'url'; @@ -11,24 +12,41 @@ async function syncModelsWithWS() { console.log(`Syncing schemas from ${sourceDir} to ${targetDir}...`); + const stats = { copied: 0, added: 0, skipped: 0 }; + try { - await syncDirectory(sourceDir, targetDir, sourceDir); - console.log('✅ Schema sync completed successfully!'); + await syncDirectory(sourceDir, targetDir, sourceDir, stats); + console.log( + `✅ Schema sync completed successfully! (${stats.added} added, ${stats.copied} updated, ${stats.skipped} unchanged)` + ); } catch (error) { console.error('❌ Error syncing schemas:', error); process.exit(1); } } -async function syncDirectory(source, target, rootSource) { - // Create target directory if it doesn't exist +function fileHasChanges(oldContent, newContent) { + return diffLines(oldContent, newContent).some((part) => part.added || part.removed); +} + +async function readFileIfExists(filePath) { + try { + return await fs.readFile(filePath, 'utf8'); + } catch (error) { + if (error.code === 'ENOENT') { + return null; + } + throw error; + } +} + +async function syncDirectory(source, target, rootSource, stats) { try { await fs.access(target); } catch { await fs.mkdir(target, { recursive: true }); } - // Read all items in source directory const items = await fs.readdir(source, { withFileTypes: true }); for (const item of items) { @@ -36,12 +54,23 @@ async function syncDirectory(source, target, rootSource) { const targetPath = path.join(target, item.name); if (item.isDirectory()) { - // Recursively sync subdirectories - await syncDirectory(sourcePath, targetPath, rootSource); + await syncDirectory(sourcePath, targetPath, rootSource, stats); } else if (item.isFile()) { - // Copy file from source to target - await fs.copyFile(sourcePath, targetPath); - console.log(` ✓ Copied: ${path.relative(rootSource, sourcePath)}`); + const sourceContent = await fs.readFile(sourcePath, 'utf8'); + const targetContent = await readFileIfExists(targetPath); + const relativePath = path.relative(rootSource, sourcePath); + + if (targetContent === null) { + await fs.writeFile(targetPath, sourceContent); + stats.added += 1; + console.log(` + Added: ${relativePath}`); + } else if (fileHasChanges(targetContent, sourceContent)) { + await fs.writeFile(targetPath, sourceContent); + stats.copied += 1; + console.log(` ✓ Updated: ${relativePath}`); + } else { + stats.skipped += 1; + } } } }