farmcontrol-api/fcdev.js
Tom Butcher e2a135aa3d 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.
2026-08-24 19:04:15 +01:00

82 lines
2.4 KiB
JavaScript

import { diffLines } from 'diff';
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
async function syncModelsWithWS() {
const sourceDir = path.resolve(__dirname, 'src/database/schemas');
const targetDir = path.resolve(__dirname, '../farmcontrol-ws/src/database/schemas');
console.log(`Syncing schemas from ${sourceDir} to ${targetDir}...`);
const stats = { copied: 0, added: 0, skipped: 0 };
try {
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);
}
}
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 });
}
const items = await fs.readdir(source, { withFileTypes: true });
for (const item of items) {
const sourcePath = path.join(source, item.name);
const targetPath = path.join(target, item.name);
if (item.isDirectory()) {
await syncDirectory(sourcePath, targetPath, rootSource, stats);
} else if (item.isFile()) {
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;
}
}
}
}
// Run the sync function when executed directly
syncModelsWithWS();
export { syncModelsWithWS };