// @ts-check const { execSync } = require("child_process"); const fs = require("fs"); const path = require("path"); const delay = require("../../utils/delay"); /** @type {any} */ let timeout; const UPDATE_TIMEOUT = 2000; /** * * @param {SyncFilesFnParams} param0 */ async function watchFiles({ files, options }) { try { for (let i = 0; i < files.length; i++) { const file = files[i]; const filePath = typeof file == "string" ? file : file?.path ? file.path : null; const interval = typeof file == "object" ? file.interval : null; if (!filePath) continue; if (typeof file == "string" && !fs.existsSync(filePath)) { try { const existingFilePath = files.find((fl) => { if (typeof fl == "string") return fs.existsSync(fl); if (!fl.host) return fs.existsSync(fl.path); // TODO handle remote }); if (!existingFilePath) { throw new Error("No existing Files for reference"); } const fileDirPath = typeof existingFilePath == "string" ? existingFilePath : existingFilePath.path; if (!fs.existsSync(fileDirPath)) { fs.mkdirSync(fileDirPath, { recursive: true }); } fs.writeFileSync(filePath, ""); if (typeof existingFilePath == "string") { sync({ filePath: existingFilePath, files, options }); } else { sync({ filePath: existingFilePath.path, files, options, }); } } catch (error) { throw new Error( `File Doesn't exist and couldn't be created. Please check if Directory exists.\nERROR => ${error.message}` ); } } if (typeof file == "string" && !fs.statSync(filePath).isFile()) { throw new Error(`'${filePath}' is not a File!`); } if (typeof file == "object" && file.host) { // TODO Handle SSH } else if (typeof file == "string") { sync({ options, filePath, files }); await delay(); fs.watchFile( filePath, { interval: interval || 500, }, (curr, prev) => { const INTERVAL = options?.interval ? options.interval : UPDATE_TIMEOUT; clearTimeout(timeout); timeout = setTimeout(() => { sync({ options, filePath, files }); process.exit(1); }, INTERVAL); } ); } } } catch (error) { console.log("ERROR:", error.message); process.exit(0); } } /** * * @param {SyncFilesSyncFnParams} param0 */ function sync({ options, filePath, files }) { const destFiles = files.filter((fl) => { if (typeof fl == "string") return fl !== filePath; if (fl?.path) return fl.path !== filePath; return false; }); for (let j = 0; j < destFiles.length; j++) { let cmdArray = ["rsync", "-avh"]; if (options?.delete) { cmdArray.push("--delete"); } if (options?.exclude?.[0]) { options.exclude.forEach((excl) => { cmdArray.push(`--exclude '${excl}'`); }); } const dstFl = destFiles[j]; if (typeof dstFl == "string") { if (!fs.existsSync(dstFl)) continue; if (filePath === dstFl) { console.log( `You can't sync the same paths. Please check your configuration and resolve duplicate paths` ); process.exit(6); } cmdArray.push(filePath, dstFl); const cmd = cmdArray.join(" "); console.log(`Running cmd 1 => ${cmd}`); execSync(cmd, { stdio: "inherit", }); } else if (dstFl.path) { if (!dstFl.host && !fs.existsSync(dstFl.path)) continue; if (filePath === dstFl.path) { console.log( `You can't sync the same paths. Please check your configuration and resolve duplicate paths` ); process.exit(6); } if (dstFl.host && dstFl.ssh_key && dstFl.user) { cmdArray.push("-e", `'ssh -i ${dstFl.ssh_key}'`); cmdArray.push( filePath, `${dstFl.user}@${dstFl.host}:${dstFl.path}` ); const cmd = cmdArray.join(" "); execSync(cmd, { stdio: "inherit", }); } else { cmdArray.push(filePath, dstFl.path); const cmd = cmdArray.join(" "); console.log(`Running cmd 2 => ${cmd}`); execSync(cmd, { stdio: "inherit", }); } } } } module.exports = watchFiles;