const fs = require('fs-extra'); const path = require('path'); const { getDestinationDecision, getCadInfo } = require('./router'); const { buildDestinationIndex } = require('./destinationIndex'); const { buildExistingCadKeyIndex, toCadKey } = require('./duplicateIndex'); const { prepareUnroutedTarget, prepareDuplicateTarget, getSkippedTarget } = require('./unrouted'); function parseNumericVersion(version) { const rawVersion = String(version || '').trim(); if (!rawVersion || !/^\d+$/.test(rawVersion)) { return null; } try { return BigInt(rawVersion); } catch { return null; } } function buildHighestNumericVersionByCadKey(files) { const index = new Map(); for (const row of files) { const cadInfo = getCadInfo(row.fileName); if (!cadInfo) { continue; } const version = parseNumericVersion(cadInfo.version); if (version === null) { continue; } const key = toCadKey(cadInfo); const current = index.get(key); if (current === undefined || version > current) { index.set(key, version); } } return index; } async function collectFilesRecursively(rootDir) { const files = []; async function walk(currentDir) { const entries = await fs.readdir(currentDir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(currentDir, entry.name); if (entry.isDirectory()) { await walk(fullPath); continue; } if (entry.isFile()) { files.push({ fullPath, fileName: entry.name }); } } } await walk(rootDir); return files; } async function processFolder(folder, config, onProgress) { onProgress?.({ phase: 'scan' }); const files = await collectFilesRecursively(folder); const destinationIndex = await buildDestinationIndex(config?.destination, onProgress); const existingCadKeys = await buildExistingCadKeyIndex(config?.destination, onProgress); const sourceMaxVersions = buildHighestNumericVersionByCadKey(files); const result = { scanned: 0, copied: 0, skipped: 0, unrouted: 0, duplicates: 0, details: [], }; const total = files.length; for (let i = 0; i < files.length; i++) { const { fullPath, fileName } = files[i]; const file = fileName; result.scanned += 1; onProgress?.({ phase: 'copy', current: i + 1, total, file }); const cadInfo = getCadInfo(file); if (!cadInfo) { const skippedTarget = await getSkippedTarget(file); await fs.copy(fullPath, skippedTarget.destinationPath); result.skipped += 1; result.copied += 1; continue; } if (existingCadKeys.has(toCadKey(cadInfo))) { const incomingVersion = parseNumericVersion(cadInfo.version); const highestInSource = sourceMaxVersions.get(toCadKey(cadInfo)); if (incomingVersion !== null && highestInSource !== undefined && incomingVersion < highestInSource) { result.details.push({ file, reason: 'Versione piu alta presente nei file da smistare', }); continue; } const duplicateTarget = await prepareDuplicateTarget(file); if (!duplicateTarget.shouldCopy) { result.details.push({ file, destination: duplicateTarget.destinationDir, reason: duplicateTarget.reason || 'Versione piu alta gia presente', }); continue; } await fs.copy(fullPath, duplicateTarget.destinationPath, { overwrite: false }); result.copied += 1; result.duplicates += 1; result.details.push({ file, destination: duplicateTarget.destinationDir, reason: 'Duplicato gia presente prima dello smistamento', }); continue; } const decision = getDestinationDecision(file, config, destinationIndex); const destDir = decision.destination; if (!destDir) { const unroutedTarget = await prepareUnroutedTarget(file); if (!unroutedTarget.shouldCopy) { result.details.push({ file, destination: unroutedTarget.destinationDir, reason: unroutedTarget.reason || 'Versione piu alta gia presente', }); continue; } await fs.copy(fullPath, unroutedTarget.destinationPath, { overwrite: false }); result.copied += 1; result.unrouted += 1; result.details.push({ file, destination: unroutedTarget.destinationDir, reason: decision.reason || 'Nessuna regola trovata', }); continue; } const dest = path.join(destDir, file); await fs.copy(fullPath, dest, { overwrite: true }); result.copied += 1; result.details.push({ file, destination: destDir }); } return result; } module.exports = { processFolder };