# SOP – CadRoute MVP ## Obiettivo Realizzare un'app desktop (.exe) che: - accetti una cartella o uno ZIP - legga file CAD (.prt .asm .dwr) - analizzi nome file ed estensione - applichi regole di routing - copi i file verso destinazioni configurate (anche share di rete) Tecnologie: - Node.js - Electron - unzipper - fs-extra --- ## 1. Prerequisiti Installare: - Node.js LTS - Git - Visual Studio Code / VSCodium Verifica: ``` node -v npm -v ``` --- ## 2. Creazione progetto ``` mkdir cadroute cd cadroute npm init -y ``` Installare dipendenze: ``` npm install electron unzipper fs-extra npm install electron-builder --save-dev ``` --- ## 3. Struttura progetto ``` cadroute │ ├── package.json ├── main.js ├── preload.js │ ├── renderer │ ├── index.html │ └── renderer.js │ ├── services │ ├── router.js │ ├── zipProcessor.js │ └── folderProcessor.js ``` --- ## 4. Configurazione runtime La destinazione viene gestita in memoria in `main.js` e modificata dalla UI durante l'esecuzione. --- ## 5. Motore di routing `services/router.js` ``` const path = require("path") function findDestination(filename, config){ const ext = path.extname(filename).slice(1) for(const rule of config.rules){ if(rule.ext !== ext) continue if(!rule.pattern) return rule.destination const regex = new RegExp(rule.pattern) if(regex.test(filename)) return rule.destination } return null } module.exports = { findDestination } ``` --- ## 7. Processare una cartella `services/folderProcessor.js` ``` const fs = require("fs-extra") const path = require("path") const { findDestination } = require("./router") async function processFolder(folder, config){ const files = await fs.readdir(folder) for(const file of files){ const src = path.join(folder,file) const destDir = findDestination(file, config) if(!destDir) continue const dest = path.join(destDir,file) await fs.copy(src,dest) } } module.exports = { processFolder } ``` --- ## 8. Processare ZIP `services/zipProcessor.js` ``` const unzipper = require("unzipper") const fs = require("fs-extra") const path = require("path") const { findDestination } = require("./router") async function processZip(zipPath, config){ const stream = fs.createReadStream(zipPath) .pipe(unzipper.Parse()) for await (const entry of stream){ const file = entry.path const destDir = findDestination(file, config) if(!destDir){ entry.autodrain() continue } const dest = path.join(destDir,path.basename(file)) entry.pipe(fs.createWriteStream(dest)) } } module.exports = { processZip } ``` --- ## 9. Main Electron `main.js` ``` const { app, BrowserWindow, dialog, ipcMain } = require("electron") const path = require("path") const { processFolder } = require("./services/folderProcessor") const { processZip } = require("./services/zipProcessor") const CAD_EXTENSIONS = ["prt", "asm", "dwr"] const DEFAULT_DESTINATION = "./output/cad" let config = { destination: DEFAULT_DESTINATION, rules: CAD_EXTENSIONS.map((ext) => ({ ext, destination: DEFAULT_DESTINATION })) } function createWindow(){ const win = new BrowserWindow({ width:800, height:600, webPreferences:{ preload: path.join(__dirname,"preload.js") } }) win.loadFile("renderer/index.html") } app.whenReady().then(createWindow) ipcMain.handle("select-folder", async () => { const result = await dialog.showOpenDialog({ properties:["openDirectory"] }) if(result.canceled) return await processFolder(result.filePaths[0], config) }) ipcMain.handle("select-zip", async () => { const result = await dialog.showOpenDialog({ filters:[{ name:"Zip", extensions:["zip"] }] }) if(result.canceled) return await processZip(result.filePaths[0], config) }) ``` --- ## 10. Preload `preload.js` ``` const { contextBridge, ipcRenderer } = require("electron") contextBridge.exposeInMainWorld("api", { selectFolder: () => ipcRenderer.invoke("select-folder"), selectZip: () => ipcRenderer.invoke("select-zip") }) ``` --- ## 11. UI minima `renderer/index.html` ```

CadRoute

``` --- ## 12. Avvio applicazione Nel package.json aggiungere: ``` "scripts": { "start": "electron ." } ``` Avviare: ``` npm start ``` --- ## 13. Build .exe Aggiungere nel package.json: ``` "build": { "appId": "com.cadroute", "win": { "target": "nsis" } } ``` Build: ``` npx electron-builder ``` Output: ``` dist/ CadRoute Setup.exe ``` --- ## MVP completato quando - l'app si avvia - si seleziona ZIP o cartella - i file .prt .asm .dwr vengono analizzati - i file vengono copiati nelle destinazioni configurate --- ## Migliorie future - progress bar - drag and drop ZIP - modifica regole avanzate da UI - logging operazioni - parallelismo file - watch folder automatico