sftp-push-sync 1.0.13 → 1.0.15

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.
@@ -53,7 +53,11 @@ const EXC = pc.redBright("-"); // Excluded
53
53
 
54
54
  const hr1 = () => "─".repeat(65); // horizontal line -
55
55
  const hr2 = () => "=".repeat(65); // horizontal line =
56
- const tab_a = () => " ".repeat(3); // indentation for formatting the output.
56
+ const tab_a = () => " ".repeat(3); // indentation for formatting the terminal output.
57
+ const tab_b = () => " ".repeat(6);
58
+ const cr_a = () => "\n".repeat(1);
59
+ const cr_b = () => "\n".repeat(2);
60
+
57
61
 
58
62
  // ---------------------------------------------------------------------------
59
63
  // CLI arguments
@@ -72,7 +76,7 @@ if (args.includes("--laconic")) cliLogLevel = "laconic";
72
76
 
73
77
  if (!TARGET) {
74
78
  console.error(pc.red("❌ Please specify a connection profile:"));
75
- console.error(pc.yellow(" sftp-push-sync staging --dry-run"));
79
+ console.error(pc.yellow(`${tab_a()}sftp-push-sync staging --dry-run`));
76
80
  process.exit(1);
77
81
  }
78
82
 
@@ -242,8 +246,11 @@ let progressActive = false;
242
246
  function clearProgressLine() {
243
247
  if (!process.stdout.isTTY || !progressActive) return;
244
248
  const width = process.stdout.columns || 80;
245
- const blank = " ".repeat(width - 1);
246
- process.stdout.write("\r" + blank + "\r");
249
+ const blank = " ".repeat(width);
250
+
251
+ // Beide Progress-Zeilen leeren
252
+ process.stdout.write("\r" + blank + cr_a() + blank + "\r");
253
+
247
254
  progressActive = false;
248
255
  }
249
256
 
@@ -346,7 +353,7 @@ function updateProgress2(prefix, current, total, rel = "") {
346
353
  if (line2.length > width) line2 = line2.slice(0, width - 1);
347
354
 
348
355
  // zwei Zeilen überschreiben
349
- process.stdout.write("\r" + line1.padEnd(width) + "\n");
356
+ process.stdout.write("\r" + line1.padEnd(width) + cr_a());
350
357
  process.stdout.write(line2.padEnd(width));
351
358
 
352
359
  // Cursor wieder nach oben (auf die Fortschrittszeile)
@@ -421,8 +428,8 @@ async function walkLocal(root) {
421
428
  scanned += 1;
422
429
  const chunk = IS_VERBOSE ? 1 : SCAN_CHUNK;
423
430
  if (scanned === 1 || scanned % chunk === 0) {
424
- // totally unknown → totally = 0 → no automatic \n
425
- updateProgress2(" Scan local: ", scanned, 0, rel);
431
+ // totally unknown → total = 0 → no automatic \n
432
+ updateProgress2(`${tab_a()}Scan local: `, scanned, 0, rel);
426
433
  }
427
434
  }
428
435
  }
@@ -432,8 +439,8 @@ async function walkLocal(root) {
432
439
 
433
440
  if (scanned > 0) {
434
441
  // last line + neat finish
435
- updateProgress2(" Scan local: ", scanned, 0, "fertig");
436
- process.stdout.write("\n");
442
+ updateProgress2(`${tab_a()}Scan local: `, scanned, 0, "fertig");
443
+ process.stdout.write(cr_a());
437
444
  progressActive = false;
438
445
  }
439
446
 
@@ -473,7 +480,7 @@ async function walkRemote(sftp, remoteRoot) {
473
480
  scanned += 1;
474
481
  const chunk = IS_VERBOSE ? 1 : SCAN_CHUNK;
475
482
  if (scanned === 1 || scanned % chunk === 0) {
476
- updateProgress2(" Scan remote: ", scanned, 0, rel);
483
+ updateProgress2(`${tab_a()}Scan remote: `, scanned, 0, rel);
477
484
  }
478
485
  }
479
486
  }
@@ -482,8 +489,8 @@ async function walkRemote(sftp, remoteRoot) {
482
489
  await recurse(remoteRoot);
483
490
 
484
491
  if (scanned > 0) {
485
- updateProgress2(" Scan remote: ", scanned, 0, "fertig");
486
- process.stdout.write("\n");
492
+ updateProgress2(`${tab_a()}Scan remote: `, scanned, 0, "fertig");
493
+ process.stdout.write(cr_a());
487
494
  progressActive = false;
488
495
  }
489
496
 
@@ -609,18 +616,18 @@ function describeSftpError(err) {
609
616
  async function main() {
610
617
  const start = Date.now();
611
618
 
612
- log(`\n\n${hr2()}`);
619
+ log(`${cr_b()}${hr2()}`);
613
620
  log(
614
621
  pc.bold(
615
622
  `🔐 SFTP Push-Synchronisation: sftp-push-sync v${pkg.version} [logLevel=${LOG_LEVEL}]`
616
623
  )
617
624
  );
618
625
  log(`${tab_a()}Connection: ${pc.cyan(TARGET)}`);
619
- log(`Worker: ${CONNECTION.workers}`);
620
- log(`${tab_a()}Host: ${pc.green(CONNECTION.host)}:${pc.green(CONNECTION.port)}`);
621
- log(`${tab_a()}Local: ${pc.green(CONNECTION.localRoot)}`);
626
+ log(`${tab_a()}Worker: ${CONNECTION.workers}`);
627
+ log(`${tab_a()}Host: ${pc.green(CONNECTION.host)}:${pc.green(CONNECTION.port)}`);
628
+ log(`${tab_a()}Local: ${pc.green(CONNECTION.localRoot)}`);
622
629
  log(`${tab_a()}Remote: ${pc.green(CONNECTION.remoteRoot)}`);
623
- if (DRY_RUN) log(pc.yellow(" Mode: DRY-RUN (no changes)"));
630
+ if (DRY_RUN) log(pc.yellow(`${tab_a()}Mode: DRY-RUN (no changes)`));
624
631
  if (RUN_UPLOAD_LIST || RUN_DOWNLOAD_LIST) {
625
632
  log(
626
633
  pc.blue(
@@ -630,7 +637,7 @@ async function main() {
630
637
  )
631
638
  );
632
639
  }
633
- log(`${hr1()}\n`);
640
+ log(`${hr1()}${cr_a()}`);
634
641
 
635
642
  const sftp = new SftpClient();
636
643
  let connected = false;
@@ -658,7 +665,7 @@ async function main() {
658
665
  process.exit(1);
659
666
  }
660
667
 
661
- log(pc.bold(pc.cyan("📥 Phase 1: Scan local files …")));
668
+ log(cr_a() + pc.bold(pc.cyan("📥 Phase 1: Scan local files …")));
662
669
  const local = await walkLocal(CONNECTION.localRoot);
663
670
  log(`${tab_a()}→ ${local.size} local files`);
664
671
 
@@ -671,14 +678,14 @@ async function main() {
671
678
  log("");
672
679
  }
673
680
 
674
- log(pc.bold(pc.cyan("📤 Phase 2: Scan remote files …")));
681
+ log(cr_a() + pc.bold(pc.cyan("📤 Phase 2: Scan remote files …")));
675
682
  const remote = await walkRemote(sftp, CONNECTION.remoteRoot);
676
- log(`${tab_a()}→ ${remote.size} remote files\n`);
683
+ log(`${tab_a()}→ ${remote.size} remote files${cr_a()}`);
677
684
 
678
685
  const localKeys = new Set(local.keys());
679
686
  const remoteKeys = new Set(remote.keys());
680
687
 
681
- log(pc.bold(pc.cyan("🔎 Phase 3: Compare & decide …")));
688
+ log(cr_a() + pc.bold(pc.cyan("🔎 Phase 3: Compare & decide …")));
682
689
  const totalToCheck = localKeys.size;
683
690
  let checkedCount = 0;
684
691
 
@@ -761,8 +768,8 @@ async function main() {
761
768
 
762
769
  if (IS_VERBOSE) {
763
770
  vlog(`${tab_a()}${CHA} Hash different (binary): ${rel}`);
764
- vlog(`${tab_a()} local: ${localHash}`);
765
- vlog(`${tab_a()} remote: ${remoteHash}`);
771
+ vlog(`${tab_b()}local: ${localHash}`);
772
+ vlog(`${tab_b()}remote: ${remoteHash}`);
766
773
  }
767
774
 
768
775
  toUpdate.push({ rel, local: l, remote: r, remotePath });
@@ -772,8 +779,13 @@ async function main() {
772
779
  }
773
780
  }
774
781
 
782
+ // Wenn Phase 3 nichts gefunden hat, explizit sagen
783
+ if (toAdd.length === 0 && toUpdate.length === 0) {
784
+ log(`${tab_a()}No differences found. Everything is up to date.`);
785
+ }
786
+
775
787
  log(
776
- "\n" + pc.bold(pc.cyan("🧹 Phase 4: Removing orphaned remote files …"))
788
+ cr_a() + pc.bold(pc.cyan("🧹 Phase 4: Removing orphaned remote files …"))
777
789
  );
778
790
  for (const rel of remoteKeys) {
779
791
  if (!localKeys.has(rel)) {
@@ -785,12 +797,17 @@ async function main() {
785
797
  }
786
798
  }
787
799
 
800
+ // Auch für Phase 4 eine „nix zu tun“-Meldung
801
+ if (toDelete.length === 0) {
802
+ log(`${tab_a()}No orphaned remote files found.`);
803
+ }
804
+
788
805
  // -------------------------------------------------------------------
789
806
  // Phase 5: Execute changes (parallel, worker-based)
790
807
  // -------------------------------------------------------------------
791
808
 
792
809
  if (!DRY_RUN) {
793
- log("\n" + pc.bold(pc.cyan("🚚 Phase 5: Apply changes …")));
810
+ log(cr_a() + pc.bold(pc.cyan("🚚 Phase 5: Apply changes …")));
794
811
 
795
812
  // Upload new files
796
813
  await runTasks(
@@ -844,7 +861,7 @@ async function main() {
844
861
  } else {
845
862
  log(
846
863
  pc.yellow(
847
- "\n💡 DRY-RUN: Connection tested, no files transferred or deleted."
864
+ `${cr_a()}💡 DRY-RUN: Connection tested, no files transferred or deleted.`
848
865
  )
849
866
  );
850
867
  }
@@ -855,7 +872,7 @@ async function main() {
855
872
 
856
873
  if (RUN_UPLOAD_LIST && UPLOAD_LIST.length > 0) {
857
874
  log(
858
- "\n" +
875
+ cr_a() +
859
876
  pc.bold(pc.cyan("⬆️ Extra Phase: Upload-List (explicit files) …"))
860
877
  );
861
878
 
@@ -890,7 +907,7 @@ async function main() {
890
907
 
891
908
  if (RUN_DOWNLOAD_LIST && DOWNLOAD_LIST.length > 0) {
892
909
  log(
893
- "\n" +
910
+ cr_a() +
894
911
  pc.bold(pc.cyan("⬇️ Extra Phase: Download-List (explicit files) …"))
895
912
  );
896
913
 
@@ -924,7 +941,8 @@ async function main() {
924
941
  await saveCache(true);
925
942
 
926
943
  // Summary
927
- log("\n" + pc.bold(pc.cyan("📊 Summary:")));
944
+ log(hr1());
945
+ log(cr_a() + pc.bold(pc.cyan("📊 Summary:")));
928
946
  log(`${tab_a()}Duration: ${pc.green(duration + " s")}`);
929
947
  log(`${tab_a()}${ADD} Added : ${toAdd.length}`);
930
948
  log(`${tab_a()}${CHA} Changed: ${toUpdate.length}`);
@@ -935,7 +953,7 @@ async function main() {
935
953
  );
936
954
  }
937
955
  if (toAdd.length || toUpdate.length || toDelete.length) {
938
- log("\n📄 Changes:");
956
+ log(`${cr_a()}📄 Changes:`);
939
957
  [...toAdd.map((t) => t.rel)]
940
958
  .sort()
941
959
  .forEach((f) => console.log(`${tab_a()}${ADD} ${f}`));
@@ -946,10 +964,10 @@ async function main() {
946
964
  .sort()
947
965
  .forEach((f) => console.log(`${tab_a()}${DEL} ${f}`));
948
966
  } else {
949
- log("\nNo changes.");
967
+ log(`${cr_a()}No changes.`);
950
968
  }
951
969
 
952
- log("\n" + pc.bold(pc.green("✅ Sync complete.")));
970
+ log(cr_a() + pc.bold(pc.green("✅ Sync complete.")));
953
971
  } catch (err) {
954
972
  const hint = describeSftpError(err);
955
973
  elog(pc.red("❌ Synchronisation error:"), err.message || err);
@@ -979,7 +997,7 @@ async function main() {
979
997
  );
980
998
  }
981
999
  }
982
- log(`${hr2()}\n\n`);
1000
+ log(`${hr2()}${cr_b()}`);
983
1001
  }
984
1002
 
985
- main();
1003
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sftp-push-sync",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "SFTP sync tool for Hugo projects (local to remote, with hash cache)",
5
5
  "type": "module",
6
6
  "bin": {