hsync-cli 1.1.9 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +36 -15
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -68377,6 +68377,9 @@ class LocalScanner {
|
|
|
68377
68377
|
if (this.includeBases.length > 0 && !this.includeBases.some((b) => b === "" || b === dir || b.startsWith(dir + "/") || dir.startsWith(b + "/"))) {
|
|
68378
68378
|
continue;
|
|
68379
68379
|
}
|
|
68380
|
+
if (this.excludePatterns.length > 0 && import_micromatch.default.isMatch(`${dir}/__hsync_probe__`, this.excludePatterns) && import_micromatch.default.isMatch(`${dir}/__hsync_probe__/__hsync_probe__`, this.excludePatterns)) {
|
|
68381
|
+
continue;
|
|
68382
|
+
}
|
|
68380
68383
|
if (!matchesRules(this.ignoreRules, dir, true)) {
|
|
68381
68384
|
await this.walk(fullPath, results);
|
|
68382
68385
|
}
|
|
@@ -68823,6 +68826,7 @@ async function listAllDaemonPids() {
|
|
|
68823
68826
|
return results;
|
|
68824
68827
|
}
|
|
68825
68828
|
var RECONCILE_INTERVAL_MS = 1e4;
|
|
68829
|
+
var LOG_MAX_BYTES = 5 * 1024 * 1024;
|
|
68826
68830
|
async function isGlobalDaemonRunning() {
|
|
68827
68831
|
const globalFile = path6.join(getHsyncDir(), "daemon.pid");
|
|
68828
68832
|
const record = await readPidRecord(globalFile);
|
|
@@ -68833,7 +68837,7 @@ async function executeSyncPass(jobId, activeJobs, ignoreEnabled = false) {
|
|
|
68833
68837
|
const config = await loadConfig();
|
|
68834
68838
|
const busyJob = config.syncJobs?.find((j) => j.id === jobId);
|
|
68835
68839
|
const busyName = busyJob?.name || jobId;
|
|
68836
|
-
console.log(source_default.yellow(`[${new Date().
|
|
68840
|
+
console.log(source_default.yellow(`[${new Date().toLocaleString("sv-SE")}] [Sync: ${busyName}] Skip run — previous run still in progress.`));
|
|
68837
68841
|
return;
|
|
68838
68842
|
}
|
|
68839
68843
|
const freshConfig = await loadConfig();
|
|
@@ -68844,7 +68848,7 @@ async function executeSyncPass(jobId, activeJobs, ignoreEnabled = false) {
|
|
|
68844
68848
|
return;
|
|
68845
68849
|
}
|
|
68846
68850
|
if (!freshServerUrl || !freshApiKey) {
|
|
68847
|
-
console.error(source_default.red(`[${new Date().
|
|
68851
|
+
console.error(source_default.red(`[${new Date().toLocaleString("sv-SE")}] [Sync: ${freshJob.name}] Missing server URL or API key. Run: hsync login`));
|
|
68848
68852
|
return;
|
|
68849
68853
|
}
|
|
68850
68854
|
if (!freshJob.enabled && !ignoreEnabled) {
|
|
@@ -68858,7 +68862,7 @@ async function executeSyncPass(jobId, activeJobs, ignoreEnabled = false) {
|
|
|
68858
68862
|
let skipCount = 0;
|
|
68859
68863
|
let errorCount = 0;
|
|
68860
68864
|
engine.on((event) => {
|
|
68861
|
-
const time = new Date().
|
|
68865
|
+
const time = new Date().toLocaleString("sv-SE");
|
|
68862
68866
|
if (event.type === "start") {
|
|
68863
68867
|
console.log(source_default.blue(`[${time}] [Sync: ${freshJob.name}] Running scan...`));
|
|
68864
68868
|
} else if (event.type === "scan-complete") {
|
|
@@ -68888,7 +68892,7 @@ async function executeSyncPass(jobId, activeJobs, ignoreEnabled = false) {
|
|
|
68888
68892
|
try {
|
|
68889
68893
|
await engine.run();
|
|
68890
68894
|
} catch (runErr) {
|
|
68891
|
-
console.error(source_default.red(`[${new Date().
|
|
68895
|
+
console.error(source_default.red(`[${new Date().toLocaleString("sv-SE")}] [Sync: ${freshJob.name}] Sync crash: ${runErr.message}`));
|
|
68892
68896
|
} finally {
|
|
68893
68897
|
activeJobs.delete(jobId);
|
|
68894
68898
|
}
|
|
@@ -68901,7 +68905,7 @@ function scheduleSyncJob(job, activeJobs, scheduledJobs) {
|
|
|
68901
68905
|
triggerSyncRun();
|
|
68902
68906
|
const intervalId = setInterval(triggerSyncRun, intervalDelay);
|
|
68903
68907
|
scheduledJobs.set(job.id, { intervalId, intervalMs: intervalDelay });
|
|
68904
|
-
console.log(source_default.green(`[${new Date().
|
|
68908
|
+
console.log(source_default.green(`[${new Date().toLocaleString("sv-SE")}] [Scheduler] Registered: ${job.name} (every ${intervalDelay / 1000}s)`));
|
|
68905
68909
|
}
|
|
68906
68910
|
function unscheduleSyncJob(jobId, jobName, scheduledJobs) {
|
|
68907
68911
|
const entry = scheduledJobs.get(jobId);
|
|
@@ -68910,7 +68914,7 @@ function unscheduleSyncJob(jobId, jobName, scheduledJobs) {
|
|
|
68910
68914
|
}
|
|
68911
68915
|
clearInterval(entry.intervalId);
|
|
68912
68916
|
scheduledJobs.delete(jobId);
|
|
68913
|
-
console.log(source_default.yellow(`[${new Date().
|
|
68917
|
+
console.log(source_default.yellow(`[${new Date().toLocaleString("sv-SE")}] [Scheduler] Unregistered: ${jobName || jobId}`));
|
|
68914
68918
|
}
|
|
68915
68919
|
async function reconcileSchedules(activeJobs, scheduledJobs, singleJobName) {
|
|
68916
68920
|
const config = await loadConfig();
|
|
@@ -69036,10 +69040,17 @@ async function startSyncScheduler(name, options) {
|
|
|
69036
69040
|
const scheduledJobs = new Map;
|
|
69037
69041
|
await reconcileSchedules(activeJobs, scheduledJobs, foregroundJobName);
|
|
69038
69042
|
if (isGlobalScheduler) {
|
|
69039
|
-
|
|
69043
|
+
const logFile = path6.join(hsyncDir, "daemon.log");
|
|
69044
|
+
setInterval(async () => {
|
|
69040
69045
|
reconcileSchedules(activeJobs, scheduledJobs).catch((reconcileErr) => {
|
|
69041
69046
|
console.error(source_default.red(`[Scheduler] Failed to refresh job list: ${reconcileErr.message}`));
|
|
69042
69047
|
});
|
|
69048
|
+
try {
|
|
69049
|
+
if ((await fs5.stat(logFile)).size > LOG_MAX_BYTES) {
|
|
69050
|
+
await fs5.copyFile(logFile, `${logFile}.1`);
|
|
69051
|
+
await fs5.truncate(logFile);
|
|
69052
|
+
}
|
|
69053
|
+
} catch {}
|
|
69043
69054
|
}, RECONCILE_INTERVAL_MS);
|
|
69044
69055
|
}
|
|
69045
69056
|
} catch (err) {
|
|
@@ -70624,6 +70635,7 @@ async function listAllDaemonPids2() {
|
|
|
70624
70635
|
return results;
|
|
70625
70636
|
}
|
|
70626
70637
|
var RECONCILE_INTERVAL_MS2 = 1e4;
|
|
70638
|
+
var LOG_MAX_BYTES2 = 5 * 1024 * 1024;
|
|
70627
70639
|
async function isGlobalDaemonRunning2() {
|
|
70628
70640
|
const globalFile = path9.join(getHsyncDir2(), "daemon.pid");
|
|
70629
70641
|
const record = await readPidRecord2(globalFile);
|
|
@@ -70634,7 +70646,7 @@ async function executeSyncPass2(jobId, activeJobs, ignoreEnabled = false) {
|
|
|
70634
70646
|
const config = await loadConfig();
|
|
70635
70647
|
const busyJob = config.syncJobs?.find((j) => j.id === jobId);
|
|
70636
70648
|
const busyName = busyJob?.name || jobId;
|
|
70637
|
-
console.log(source_default.yellow(`[${new Date().
|
|
70649
|
+
console.log(source_default.yellow(`[${new Date().toLocaleString("sv-SE")}] [Sync: ${busyName}] Skip run — previous run still in progress.`));
|
|
70638
70650
|
return;
|
|
70639
70651
|
}
|
|
70640
70652
|
const freshConfig = await loadConfig();
|
|
@@ -70645,7 +70657,7 @@ async function executeSyncPass2(jobId, activeJobs, ignoreEnabled = false) {
|
|
|
70645
70657
|
return;
|
|
70646
70658
|
}
|
|
70647
70659
|
if (!freshServerUrl || !freshApiKey) {
|
|
70648
|
-
console.error(source_default.red(`[${new Date().
|
|
70660
|
+
console.error(source_default.red(`[${new Date().toLocaleString("sv-SE")}] [Sync: ${freshJob.name}] Missing server URL or API key. Run: hsync login`));
|
|
70649
70661
|
return;
|
|
70650
70662
|
}
|
|
70651
70663
|
if (!freshJob.enabled && !ignoreEnabled) {
|
|
@@ -70659,7 +70671,7 @@ async function executeSyncPass2(jobId, activeJobs, ignoreEnabled = false) {
|
|
|
70659
70671
|
let skipCount = 0;
|
|
70660
70672
|
let errorCount = 0;
|
|
70661
70673
|
engine.on((event) => {
|
|
70662
|
-
const time = new Date().
|
|
70674
|
+
const time = new Date().toLocaleString("sv-SE");
|
|
70663
70675
|
if (event.type === "start") {
|
|
70664
70676
|
console.log(source_default.blue(`[${time}] [Sync: ${freshJob.name}] Running scan...`));
|
|
70665
70677
|
} else if (event.type === "scan-complete") {
|
|
@@ -70689,7 +70701,7 @@ async function executeSyncPass2(jobId, activeJobs, ignoreEnabled = false) {
|
|
|
70689
70701
|
try {
|
|
70690
70702
|
await engine.run();
|
|
70691
70703
|
} catch (runErr) {
|
|
70692
|
-
console.error(source_default.red(`[${new Date().
|
|
70704
|
+
console.error(source_default.red(`[${new Date().toLocaleString("sv-SE")}] [Sync: ${freshJob.name}] Sync crash: ${runErr.message}`));
|
|
70693
70705
|
} finally {
|
|
70694
70706
|
activeJobs.delete(jobId);
|
|
70695
70707
|
}
|
|
@@ -70702,7 +70714,7 @@ function scheduleSyncJob2(job, activeJobs, scheduledJobs) {
|
|
|
70702
70714
|
triggerSyncRun();
|
|
70703
70715
|
const intervalId = setInterval(triggerSyncRun, intervalDelay);
|
|
70704
70716
|
scheduledJobs.set(job.id, { intervalId, intervalMs: intervalDelay });
|
|
70705
|
-
console.log(source_default.green(`[${new Date().
|
|
70717
|
+
console.log(source_default.green(`[${new Date().toLocaleString("sv-SE")}] [Scheduler] Registered: ${job.name} (every ${intervalDelay / 1000}s)`));
|
|
70706
70718
|
}
|
|
70707
70719
|
function unscheduleSyncJob2(jobId, jobName, scheduledJobs) {
|
|
70708
70720
|
const entry = scheduledJobs.get(jobId);
|
|
@@ -70711,7 +70723,7 @@ function unscheduleSyncJob2(jobId, jobName, scheduledJobs) {
|
|
|
70711
70723
|
}
|
|
70712
70724
|
clearInterval(entry.intervalId);
|
|
70713
70725
|
scheduledJobs.delete(jobId);
|
|
70714
|
-
console.log(source_default.yellow(`[${new Date().
|
|
70726
|
+
console.log(source_default.yellow(`[${new Date().toLocaleString("sv-SE")}] [Scheduler] Unregistered: ${jobName || jobId}`));
|
|
70715
70727
|
}
|
|
70716
70728
|
async function reconcileSchedules2(activeJobs, scheduledJobs, singleJobName) {
|
|
70717
70729
|
const config = await loadConfig();
|
|
@@ -70933,10 +70945,17 @@ async function startSyncScheduler2(name, options) {
|
|
|
70933
70945
|
const scheduledJobs = new Map;
|
|
70934
70946
|
await reconcileSchedules2(activeJobs, scheduledJobs, foregroundJobName);
|
|
70935
70947
|
if (isGlobalScheduler) {
|
|
70936
|
-
|
|
70948
|
+
const logFile = path9.join(hsyncDir, "daemon.log");
|
|
70949
|
+
setInterval(async () => {
|
|
70937
70950
|
reconcileSchedules2(activeJobs, scheduledJobs).catch((reconcileErr) => {
|
|
70938
70951
|
console.error(source_default.red(`[Scheduler] Failed to refresh job list: ${reconcileErr.message}`));
|
|
70939
70952
|
});
|
|
70953
|
+
try {
|
|
70954
|
+
if ((await fs7.stat(logFile)).size > LOG_MAX_BYTES2) {
|
|
70955
|
+
await fs7.copyFile(logFile, `${logFile}.1`);
|
|
70956
|
+
await fs7.truncate(logFile);
|
|
70957
|
+
}
|
|
70958
|
+
} catch {}
|
|
70940
70959
|
}, RECONCILE_INTERVAL_MS2);
|
|
70941
70960
|
}
|
|
70942
70961
|
} catch (err) {
|
|
@@ -71094,6 +71113,8 @@ async function showSyncLogs(name, options) {
|
|
|
71094
71113
|
if (event.eventType === "change") {
|
|
71095
71114
|
const newStat = await fs7.stat(logFile);
|
|
71096
71115
|
const newSize = newStat.size;
|
|
71116
|
+
if (newSize < currentSize)
|
|
71117
|
+
currentSize = 0;
|
|
71097
71118
|
if (newSize > currentSize) {
|
|
71098
71119
|
const sizeDiff = newSize - currentSize;
|
|
71099
71120
|
const readBuffer = Buffer.alloc(sizeDiff);
|
|
@@ -71516,7 +71537,7 @@ Press Ctrl+C to stop the server...
|
|
|
71516
71537
|
// package.json
|
|
71517
71538
|
var package_default = {
|
|
71518
71539
|
name: "hsync-cli",
|
|
71519
|
-
version: "1.1.
|
|
71540
|
+
version: "1.1.10",
|
|
71520
71541
|
description: "hsync CLI for file sync operations",
|
|
71521
71542
|
bin: {
|
|
71522
71543
|
hsync: "./dist/bin.js"
|
package/dist/web/index.html
CHANGED
|
@@ -1163,10 +1163,10 @@
|
|
|
1163
1163
|
div.className += ' system';
|
|
1164
1164
|
}
|
|
1165
1165
|
|
|
1166
|
-
// Parse timestamps [HH:MM:SS] if present
|
|
1166
|
+
// Parse timestamps [YYYY-MM-DD HH:MM:SS] (or legacy [HH:MM:SS AM]) if present
|
|
1167
1167
|
let time = '';
|
|
1168
1168
|
let text = line;
|
|
1169
|
-
const match = line.match(/^(\[
|
|
1169
|
+
const match = line.match(/^(\[(?:\d{4}-\d{2}-\d{2} )?\d{1,2}:\d{2}:\d{2}(?: [AP]M)?\])\s*(.*)/);
|
|
1170
1170
|
if (match) {
|
|
1171
1171
|
time = match[1];
|
|
1172
1172
|
text = match[2];
|