This commit is contained in:
Benjamin Toby
2025-07-21 13:51:59 +01:00
parent 5de4d1dc73
commit 822778d43b
39 changed files with 944 additions and 421 deletions
+67
View File
@@ -0,0 +1,67 @@
import fs from "fs";
import path from "path";
type Params = {
dirs?: string[];
files?: string[];
};
export default function getLatestSource({
dirs,
files,
}: Params): string | undefined {
let latestDir = undefined;
let latestMtime = 0;
const isFiles = files?.[0];
const finalPaths = isFiles ? files : dirs;
if (!finalPaths) return undefined;
for (const pth of finalPaths) {
try {
const stats = fs.statSync(pth);
const pathMtime = stats.isDirectory()
? getLatestDirMtime(pth)
: stats.mtimeMs;
if (pathMtime > latestMtime) {
latestMtime = pathMtime;
latestDir = pth;
}
} catch (error: any) {
console.error(`Error accessing ${pth}: ${error.message}`);
}
}
return latestDir;
}
function getLatestDirMtime(dir: string) {
let latestMtime = 0;
try {
const stats = fs.statSync(dir);
if (stats.isDirectory()) {
latestMtime = stats.mtimeMs;
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const entryPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
const subMtime = getLatestDirMtime(entryPath);
latestMtime = Math.max(latestMtime, subMtime);
} else if (entry.isFile()) {
const fileStats = fs.statSync(entryPath);
latestMtime = Math.max(latestMtime, fileStats.mtimeMs);
}
}
}
} catch (error: any) {
console.error(`Error accessing ${dir}: ${error.message}`);
}
return latestMtime;
}
+18
View File
@@ -0,0 +1,18 @@
import fs from "fs";
import grabDirNames from "./grab-dir-names";
import { SyncFileConfig } from "../types";
export default function getSyncConfig(): SyncFileConfig {
try {
const { syncConfigFilePath } = grabDirNames();
if (!fs.existsSync(syncConfigFilePath)) {
fs.writeFileSync(syncConfigFilePath, JSON.stringify({}), "utf-8");
return {};
}
const syncConfigJSON = fs.readFileSync(syncConfigFilePath, "utf-8");
return JSON.parse(syncConfigJSON);
} catch (error) {
return { status: "error" };
}
}
+9
View File
@@ -0,0 +1,9 @@
import path from "path";
export default function grabDirNames() {
const rootDir = process.cwd();
const syncConfigFileName = "__trsyc.json";
const syncConfigFilePath = path.join(rootDir, syncConfigFileName);
return { rootDir, syncConfigFileName, syncConfigFilePath };
}
+31
View File
@@ -0,0 +1,31 @@
import { TurboSyncFileObject } from "../types";
export default function fldFileToStrArr(
srces?: (string | TurboSyncFileObject)[]
) {
if (!srces) return undefined;
let arr: string[] = [];
for (let i = 0; i < srces.length; i++) {
const src = srces[i];
const srcStr = fldFileToStr(src);
if (srcStr) {
arr.push(srcStr);
}
}
return arr;
}
export function fldFileToStr(src?: string | TurboSyncFileObject) {
if (!src) return undefined;
if (typeof src == "string") {
return src;
} else if (typeof src == "object" && src.path) {
return src.path;
}
return undefined;
}
+95
View File
@@ -0,0 +1,95 @@
import fs from "fs";
import path from "path";
import util from "util";
import { exec } from "child_process";
import { SyncFoldersSyncFnParams } from "../types";
const execPromise = util.promisify(exec);
export default async function sync({
options,
dirs,
dirPath,
isFiles,
firstRun,
}: SyncFoldersSyncFnParams) {
const dstDirs = dirs.filter((dr) => {
if (typeof dr == "string") return dr !== dirPath;
if (dr?.path) return dr.path !== dirPath;
return false;
});
const rsyncTrailingSlash = isFiles ? "" : "/";
const allCommandsArr: string[][] = [];
for (let j = 0; j < dstDirs.length; j++) {
const dstDr = dstDirs[j];
let cmdArray = ["rsync", firstRun ? "-az" : "-azu", "--inplace"];
if (options?.delete) {
cmdArray.push("--delete");
}
if (options?.include?.[0]) {
options.include.forEach((incl) => {
cmdArray.push(`--include='${incl}'`);
});
}
if (options?.exclude?.[0]) {
options.exclude.forEach((excl) => {
cmdArray.push(`--exclude='${excl}'`);
});
}
if (typeof dstDr == "string") {
if (!fs.existsSync(dstDr)) continue;
if (dirPath === dstDr) {
console.log(
`You can't sync the same paths. Please check your configuration and resolve duplicate paths`
);
process.exit(6);
}
cmdArray.push(
path.normalize(dirPath) + rsyncTrailingSlash,
path.normalize(dstDr) + rsyncTrailingSlash
);
} else if (dstDr.path) {
if (!dstDr.host && !fs.existsSync(dstDr.path)) continue;
if (dirPath === dstDr.path) {
console.log(
`You can't sync the same paths. Please check your configuration and resolve duplicate paths`
);
process.exit(6);
}
if (dstDr.host && dstDr.ssh_key && dstDr.user) {
cmdArray.push("-e", `'ssh -i ${dstDr.ssh_key}'`);
cmdArray.push(
path.normalize(dirPath) + rsyncTrailingSlash,
`${dstDr.user}@${dstDr.host}:${dstDr.path}${rsyncTrailingSlash}`
);
} else {
cmdArray.push(
path.normalize(dirPath),
path.normalize(dstDr.path)
);
}
}
allCommandsArr.push(cmdArray);
}
await Promise.all(
allCommandsArr.map((cmdArr) => {
return execPromise(cmdArr.join(" "));
})
);
console.log(`${dirPath} Folder Sync Complete. Exiting ...`);
}
+13
View File
@@ -0,0 +1,13 @@
import fs from "fs";
import grabDirNames from "./grab-dir-names";
import { SyncFileConfig } from "../types";
export default function writeSyncConfig(config: SyncFileConfig): boolean {
try {
const { syncConfigFilePath } = grabDirNames();
fs.writeFileSync(syncConfigFilePath, JSON.stringify(config), "utf-8");
return true;
} catch (error) {
return false;
}
}