@qodalis/cli-scp 2.0.0-beta.8 → 2.0.0-rc.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qodalis/cli-scp",
3
- "version": "2.0.0-beta.8",
3
+ "version": "2.0.0-rc.1",
4
4
  "description": "SCP-like file transfer between browser and remote servers",
5
5
  "author": "Qodalis Solutions",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  "umd": "./umd/index.global.js",
19
19
  "unpkg": "./umd/index.global.js",
20
20
  "dependencies": {
21
- "@qodalis/cli-core": "2.0.0-beta.8"
21
+ "@qodalis/cli-core": "2.0.0-rc.1"
22
22
  },
23
23
  "sideEffects": false,
24
24
  "main": "./public-api.js",
package/public-api.d.mts CHANGED
@@ -1,10 +1,9 @@
1
- import * as _qodalis_cli_core from '@qodalis/cli-core';
2
1
  import { ICliCommandProcessor, ICliCommandChildProcessor, CliProcessCommand, ICliExecutionContext, ICliModule } from '@qodalis/cli-core';
3
2
 
4
3
  declare class CliScpCommandCommandProcessor implements ICliCommandProcessor {
5
4
  command: string;
6
5
  description: string;
7
- author: _qodalis_cli_core.ICliCommandAuthor;
6
+ author: any;
8
7
  version: string;
9
8
  metadata: {
10
9
  icon: string;
@@ -18,7 +17,7 @@ declare class CliScpCommandCommandProcessor implements ICliCommandProcessor {
18
17
  private doUpload;
19
18
  }
20
19
 
21
- declare const LIBRARY_VERSION = "2.0.0-beta.8";
20
+ declare const LIBRARY_VERSION = "2.0.0-rc.1";
22
21
  declare const API_VERSION = 2;
23
22
 
24
23
  declare const scpModule: ICliModule;
package/public-api.d.ts CHANGED
@@ -1,10 +1,9 @@
1
- import * as _qodalis_cli_core from '@qodalis/cli-core';
2
1
  import { ICliCommandProcessor, ICliCommandChildProcessor, CliProcessCommand, ICliExecutionContext, ICliModule } from '@qodalis/cli-core';
3
2
 
4
3
  declare class CliScpCommandCommandProcessor implements ICliCommandProcessor {
5
4
  command: string;
6
5
  description: string;
7
- author: _qodalis_cli_core.ICliCommandAuthor;
6
+ author: any;
8
7
  version: string;
9
8
  metadata: {
10
9
  icon: string;
@@ -18,7 +17,7 @@ declare class CliScpCommandCommandProcessor implements ICliCommandProcessor {
18
17
  private doUpload;
19
18
  }
20
19
 
21
- declare const LIBRARY_VERSION = "2.0.0-beta.8";
20
+ declare const LIBRARY_VERSION = "2.0.0-rc.1";
22
21
  declare const API_VERSION = 2;
23
22
 
24
23
  declare const scpModule: ICliModule;
package/public-api.js CHANGED
@@ -5,13 +5,9 @@ var cliCore = require('@qodalis/cli-core');
5
5
  // src/lib/processors/cli-scp-command-processor.ts
6
6
 
7
7
  // src/lib/version.ts
8
- var LIBRARY_VERSION = "2.0.0-beta.8";
8
+ var LIBRARY_VERSION = "2.0.0-rc.1";
9
9
  var API_VERSION = 2;
10
-
11
- // src/lib/interfaces/index.ts
12
- var IScpTransferService_TOKEN = "scp-transfer-service";
13
-
14
- // src/lib/processors/scp-utils.ts
10
+ var IScpTransferService_TOKEN = cliCore.createCliToken("scp-transfer-service");
15
11
  function resolveServer(serverName, context) {
16
12
  const servers = context.options?.servers;
17
13
  if (!servers || servers.length === 0) {
@@ -49,10 +45,10 @@ function parseServerAndPath(value, context, args) {
49
45
  if (serverArg && pathArg) {
50
46
  return [String(serverArg), String(pathArg)];
51
47
  }
52
- if (!value?.trim()) {
48
+ const parts = cliCore.splitShellWords(value ?? "");
49
+ if (parts.length === 0) {
53
50
  return null;
54
51
  }
55
- const parts = value.trim().split(/\s+/);
56
52
  if (parts.length < 2) {
57
53
  if (serverArg && parts.length >= 1) {
58
54
  return [String(serverArg), parts.join(" ")];
@@ -64,8 +60,6 @@ function parseServerAndPath(value, context, args) {
64
60
  }
65
61
  return [parts[0], parts.slice(1).join(" ")];
66
62
  }
67
-
68
- // src/lib/processors/cli-scp-ls-processor.ts
69
63
  var CliScpLsProcessor = class {
70
64
  constructor() {
71
65
  this.command = "ls";
@@ -96,7 +90,7 @@ var CliScpLsProcessor = class {
96
90
  const [serverName, path] = parsed;
97
91
  const server = resolveServer(serverName, context);
98
92
  if (!server) return;
99
- const transferService = context.services.get(
93
+ const transferService = context.services.getRequired(
100
94
  IScpTransferService_TOKEN
101
95
  );
102
96
  if (!transferService) {
@@ -108,7 +102,7 @@ var CliScpLsProcessor = class {
108
102
  const entries = await transferService.ls(
109
103
  serverUrl(server),
110
104
  path,
111
- server.headers
105
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers)
112
106
  );
113
107
  context.spinner?.hide();
114
108
  if (entries.length === 0) {
@@ -133,8 +127,6 @@ var CliScpLsProcessor = class {
133
127
  context.writer.writeln("List files and directories on a remote server.");
134
128
  }
135
129
  };
136
-
137
- // src/lib/processors/cli-scp-cat-processor.ts
138
130
  var CliScpCatProcessor = class {
139
131
  constructor() {
140
132
  this.command = "cat";
@@ -165,7 +157,7 @@ var CliScpCatProcessor = class {
165
157
  const [serverName, path] = parsed;
166
158
  const server = resolveServer(serverName, context);
167
159
  if (!server) return;
168
- const transferService = context.services.get(
160
+ const transferService = context.services.getRequired(
169
161
  IScpTransferService_TOKEN
170
162
  );
171
163
  if (!transferService) {
@@ -177,7 +169,7 @@ var CliScpCatProcessor = class {
177
169
  const content = await transferService.cat(
178
170
  serverUrl(server),
179
171
  path,
180
- server.headers
172
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers)
181
173
  );
182
174
  context.spinner?.hide();
183
175
  context.writer.writeln(content);
@@ -235,12 +227,11 @@ var CliScpDownloadProcessor = class {
235
227
  remotePath = String(args["remote-path"] || args["path"]);
236
228
  localPath = args["local-path"] ? String(args["local-path"]) : void 0;
237
229
  } else {
238
- const value = command.value?.trim();
239
- if (!value) {
230
+ const parts = command.positionals ?? [];
231
+ if (parts.length === 0) {
240
232
  context.writer.writeError("Usage: scp download <server> <remote-path> [local-path]");
241
233
  return;
242
234
  }
243
- const parts = value.split(/\s+/);
244
235
  if (parts.length < 2) {
245
236
  context.writer.writeError("Usage: scp download <server> <remote-path> [local-path]");
246
237
  return;
@@ -256,7 +247,7 @@ var CliScpDownloadProcessor = class {
256
247
  localPath = localPath || remotePath.split("/").pop() || "download";
257
248
  const server = resolveServer(serverName, context);
258
249
  if (!server) return;
259
- const transferService = context.services.get(
250
+ const transferService = context.services.getRequired(
260
251
  IScpTransferService_TOKEN
261
252
  );
262
253
  if (!transferService) {
@@ -265,6 +256,7 @@ var CliScpDownloadProcessor = class {
265
256
  }
266
257
  const useBrowserDownload = command.args?.["save"] === true;
267
258
  context.spinner?.show(`Downloading ${remotePath} from ${server.name}...`);
259
+ context.notifier.info(`scp: downloading from ${server.name}`);
268
260
  const abortController = new AbortController();
269
261
  const abortSub = context.onAbort.subscribe(() => abortController.abort());
270
262
  try {
@@ -272,7 +264,7 @@ var CliScpDownloadProcessor = class {
272
264
  const { content, size } = await transferService.download(
273
265
  serverUrl(server),
274
266
  remotePath,
275
- server.headers,
267
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers),
276
268
  (received, total) => {
277
269
  const now = Date.now();
278
270
  if (now - lastProgressUpdate < 200) return;
@@ -282,17 +274,19 @@ var CliScpDownloadProcessor = class {
282
274
  context.spinner?.show(
283
275
  `Downloading ${remotePath}... ${pct}% (${formatBytes(received)}/${formatBytes(total)})`
284
276
  );
277
+ context.notifier.info(`scp: download ${pct}%`);
285
278
  } else {
286
279
  context.spinner?.show(
287
280
  `Downloading ${remotePath}... ${formatBytes(received)}`
288
281
  );
282
+ context.notifier.info(`scp: download ${formatBytes(received)}`);
289
283
  }
290
284
  },
291
285
  abortController.signal
292
286
  );
293
287
  context.spinner?.hide();
294
288
  if (useBrowserDownload) {
295
- const fileService = context.services.get(
289
+ const fileService = context.services.getRequired(
296
290
  cliCore.ICliFileTransferService_TOKEN
297
291
  );
298
292
  if (fileService) {
@@ -304,7 +298,7 @@ var CliScpDownloadProcessor = class {
304
298
  context.writer.writeError("File transfer service not available for browser download.");
305
299
  }
306
300
  } else {
307
- const fileService = context.services.get(
301
+ const fileService = context.services.getRequired(
308
302
  cliCore.ICliFileTransferService_TOKEN
309
303
  );
310
304
  if (fileService) {
@@ -374,14 +368,13 @@ var CliScpUploadProcessor = class {
374
368
  localPath = args["local-path"] ? String(args["local-path"]) : void 0;
375
369
  remotePath = String(args["remote-path"]);
376
370
  } else {
377
- const value = command.value?.trim();
378
- if (!value) {
371
+ const parts = command.positionals ?? [];
372
+ if (parts.length === 0) {
379
373
  context.writer.writeError(
380
374
  useLocalPicker ? "Usage: scp upload --local <server> <remote-path>" : "Usage: scp upload <server> <local-path> <remote-path>"
381
375
  );
382
376
  return;
383
377
  }
384
- const parts = value.split(/\s+/);
385
378
  if (useLocalPicker) {
386
379
  if (parts.length < 2) {
387
380
  context.writer.writeError("Usage: scp upload --local <server> <remote-path>");
@@ -407,14 +400,14 @@ var CliScpUploadProcessor = class {
407
400
  }
408
401
  const server = resolveServer(serverName, context);
409
402
  if (!server) return;
410
- const fileService = context.services.get(
403
+ const fileService = context.services.getRequired(
411
404
  cliCore.ICliFileTransferService_TOKEN
412
405
  );
413
406
  if (!fileService) {
414
407
  context.writer.writeError("File transfer service not available.");
415
408
  return;
416
409
  }
417
- const transferService = context.services.get(
410
+ const transferService = context.services.getRequired(
418
411
  IScpTransferService_TOKEN
419
412
  );
420
413
  if (!transferService) {
@@ -444,13 +437,14 @@ var CliScpUploadProcessor = class {
444
437
  context.spinner?.show(
445
438
  `Uploading "${filename}" (${formatBytes(content.length)}) to ${server.name}:${remotePath}...`
446
439
  );
440
+ context.notifier.info(`scp: uploading to ${server.name}`);
447
441
  try {
448
442
  await transferService.upload(
449
443
  serverUrl(server),
450
444
  remotePath,
451
445
  content,
452
446
  filename,
453
- server.headers
447
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers)
454
448
  );
455
449
  context.spinner?.hide();
456
450
  context.writer.writeSuccess(
@@ -469,8 +463,6 @@ var CliScpUploadProcessor = class {
469
463
  context.writer.writeln(" scp upload --local <server> <remote-path> Pick from your machine via browser");
470
464
  }
471
465
  };
472
-
473
- // src/lib/processors/cli-scp-rm-processor.ts
474
466
  var CliScpRmProcessor = class {
475
467
  constructor() {
476
468
  this.command = "rm";
@@ -501,7 +493,7 @@ var CliScpRmProcessor = class {
501
493
  const [serverName, path] = parsed;
502
494
  const server = resolveServer(serverName, context);
503
495
  if (!server) return;
504
- const transferService = context.services.get(
496
+ const transferService = context.services.getRequired(
505
497
  IScpTransferService_TOKEN
506
498
  );
507
499
  if (!transferService) {
@@ -513,7 +505,7 @@ var CliScpRmProcessor = class {
513
505
  await transferService.rm(
514
506
  serverUrl(server),
515
507
  path,
516
- server.headers
508
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers)
517
509
  );
518
510
  context.spinner?.hide();
519
511
  context.writer.writeSuccess(`Deleted: ${server.name}:${path}`);
@@ -526,8 +518,6 @@ var CliScpRmProcessor = class {
526
518
  context.writer.writeln("Delete a file on a remote server.");
527
519
  }
528
520
  };
529
-
530
- // src/lib/processors/cli-scp-mkdir-processor.ts
531
521
  var CliScpMkdirProcessor = class {
532
522
  constructor() {
533
523
  this.command = "mkdir";
@@ -558,7 +548,7 @@ var CliScpMkdirProcessor = class {
558
548
  const [serverName, path] = parsed;
559
549
  const server = resolveServer(serverName, context);
560
550
  if (!server) return;
561
- const transferService = context.services.get(
551
+ const transferService = context.services.getRequired(
562
552
  IScpTransferService_TOKEN
563
553
  );
564
554
  if (!transferService) {
@@ -570,7 +560,7 @@ var CliScpMkdirProcessor = class {
570
560
  await transferService.mkdir(
571
561
  serverUrl(server),
572
562
  path,
573
- server.headers
563
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers)
574
564
  );
575
565
  context.spinner?.hide();
576
566
  context.writer.writeSuccess(`Created directory: ${server.name}:${path}`);
@@ -583,8 +573,6 @@ var CliScpMkdirProcessor = class {
583
573
  context.writer.writeln("Create a directory on a remote server.");
584
574
  }
585
575
  };
586
-
587
- // src/lib/processors/cli-scp-stat-processor.ts
588
576
  var CliScpStatProcessor = class {
589
577
  constructor() {
590
578
  this.command = "stat";
@@ -615,7 +603,7 @@ var CliScpStatProcessor = class {
615
603
  const [serverName, path] = parsed;
616
604
  const server = resolveServer(serverName, context);
617
605
  if (!server) return;
618
- const transferService = context.services.get(
606
+ const transferService = context.services.getRequired(
619
607
  IScpTransferService_TOKEN
620
608
  );
621
609
  if (!transferService) {
@@ -627,7 +615,7 @@ var CliScpStatProcessor = class {
627
615
  const stat = await transferService.stat(
628
616
  serverUrl(server),
629
617
  path,
630
- server.headers
618
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers)
631
619
  );
632
620
  context.spinner?.hide();
633
621
  const entries = {
@@ -671,33 +659,25 @@ var CliScpCommandCommandProcessor = class {
671
659
  ];
672
660
  }
673
661
  async processCommand(command, context) {
674
- const value = command.value?.trim();
675
- if (value && value.includes(":") && !value.startsWith("-")) {
676
- const colonIdx = value.indexOf(":");
677
- const spaceBeforeColon = value.lastIndexOf(" ", colonIdx);
678
- if (spaceBeforeColon === -1) {
679
- const serverName = value.substring(0, colonIdx);
680
- const rest = value.substring(colonIdx + 1);
681
- const parts2 = rest.trim().split(/\s+/);
682
- const remotePath = parts2[0];
683
- const localPath = parts2[1] || remotePath.split("/").pop() || "download";
662
+ const [first = "", second] = command.positionals ?? [];
663
+ if (first && !first.startsWith("-")) {
664
+ const colonIdx = first.indexOf(":");
665
+ if (colonIdx !== -1) {
666
+ const serverName = first.substring(0, colonIdx);
667
+ const remotePath = first.substring(colonIdx + 1);
668
+ const localPath = second || remotePath.split("/").pop() || "download";
684
669
  if (remotePath) {
685
670
  await this.doDownload(serverName, remotePath, localPath, command, context);
686
671
  return;
687
672
  }
688
673
  }
689
- const parts = value.split(/\s+/);
690
- if (parts.length >= 2) {
691
- const secondPart = parts[1];
692
- if (secondPart.includes(":")) {
693
- const localPath = parts[0];
694
- const srvColonIdx = secondPart.indexOf(":");
695
- const serverName = secondPart.substring(0, srvColonIdx);
696
- const remotePath = secondPart.substring(srvColonIdx + 1);
697
- if (remotePath) {
698
- await this.doUpload(serverName, localPath, remotePath, context);
699
- return;
700
- }
674
+ if (second?.includes(":")) {
675
+ const srvColonIdx = second.indexOf(":");
676
+ const serverName = second.substring(0, srvColonIdx);
677
+ const remotePath = second.substring(srvColonIdx + 1);
678
+ if (remotePath) {
679
+ await this.doUpload(serverName, first, remotePath, context);
680
+ return;
701
681
  }
702
682
  }
703
683
  }
@@ -709,7 +689,7 @@ var CliScpCommandCommandProcessor = class {
709
689
  async doDownload(serverName, remotePath, localPath, command, context) {
710
690
  const server = resolveServer(serverName, context);
711
691
  if (!server) return;
712
- const transferService = context.services.get(
692
+ const transferService = context.services.getRequired(
713
693
  IScpTransferService_TOKEN
714
694
  );
715
695
  if (!transferService) {
@@ -718,12 +698,13 @@ var CliScpCommandCommandProcessor = class {
718
698
  }
719
699
  const useBrowserDownload = command.args?.["save"] === true;
720
700
  context.spinner?.show(`Downloading ${remotePath} from ${server.name}...`);
701
+ context.notifier.info(`scp: downloading from ${server.name}`);
721
702
  try {
722
703
  let lastProgressUpdate = 0;
723
704
  const { content, size } = await transferService.download(
724
705
  serverUrl(server),
725
706
  remotePath,
726
- server.headers,
707
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers),
727
708
  (received, total) => {
728
709
  const now = Date.now();
729
710
  if (now - lastProgressUpdate < 200) return;
@@ -733,15 +714,17 @@ var CliScpCommandCommandProcessor = class {
733
714
  context.spinner?.show(
734
715
  `Downloading ${remotePath}... ${pct}% (${formatBytes(received)}/${formatBytes(total)})`
735
716
  );
717
+ context.notifier.info(`scp: download ${pct}%`);
736
718
  } else {
737
719
  context.spinner?.show(
738
720
  `Downloading ${remotePath}... ${formatBytes(received)}`
739
721
  );
722
+ context.notifier.info(`scp: download ${formatBytes(received)}`);
740
723
  }
741
724
  }
742
725
  );
743
726
  context.spinner?.hide();
744
- const fileService = context.services.get(
727
+ const fileService = context.services.getRequired(
745
728
  cliCore.ICliFileTransferService_TOKEN
746
729
  );
747
730
  if (!fileService) {
@@ -767,14 +750,14 @@ var CliScpCommandCommandProcessor = class {
767
750
  async doUpload(serverName, localPath, remotePath, context) {
768
751
  const server = resolveServer(serverName, context);
769
752
  if (!server) return;
770
- const fileService = context.services.get(
753
+ const fileService = context.services.getRequired(
771
754
  cliCore.ICliFileTransferService_TOKEN
772
755
  );
773
756
  if (!fileService) {
774
757
  context.writer.writeError("File transfer service not available.");
775
758
  return;
776
759
  }
777
- const transferService = context.services.get(
760
+ const transferService = context.services.getRequired(
778
761
  IScpTransferService_TOKEN
779
762
  );
780
763
  if (!transferService) {
@@ -782,6 +765,7 @@ var CliScpCommandCommandProcessor = class {
782
765
  return;
783
766
  }
784
767
  context.spinner?.show(`Reading local file "${localPath}"...`);
768
+ context.notifier.info(`scp: reading ${localPath}`);
785
769
  try {
786
770
  const content = await fileService.readFile(localPath);
787
771
  if (content === null) {
@@ -793,12 +777,13 @@ var CliScpCommandCommandProcessor = class {
793
777
  context.spinner?.show(
794
778
  `Uploading "${filename}" (${formatBytes(content.length)}) to ${server.name}:${remotePath}...`
795
779
  );
780
+ context.notifier.info(`scp: uploading to ${server.name}`);
796
781
  await transferService.upload(
797
782
  serverUrl(server),
798
783
  remotePath,
799
784
  content,
800
785
  filename,
801
- server.headers
786
+ cliCore.resolveServerHeaders(context.services, server.name, server.headers)
802
787
  );
803
788
  context.spinner?.hide();
804
789
  context.writer.writeSuccess(
@@ -810,32 +795,30 @@ var CliScpCommandCommandProcessor = class {
810
795
  }
811
796
  }
812
797
  };
813
-
814
- // src/lib/services/scp-transfer.service.ts
815
798
  var ScpTransferService = class {
816
799
  async ls(serverUrl2, path, headers) {
817
800
  const res = await this._fetch(`${serverUrl2}/api/qcli/fs/ls?path=${encodeURIComponent(path)}`, {
818
- headers
801
+ headers: cliCore.resolveHeaders(headers)
819
802
  });
820
803
  const data = await res.json();
821
804
  return data.entries;
822
805
  }
823
806
  async cat(serverUrl2, path, headers) {
824
807
  const res = await this._fetch(`${serverUrl2}/api/qcli/fs/cat?path=${encodeURIComponent(path)}`, {
825
- headers
808
+ headers: cliCore.resolveHeaders(headers)
826
809
  });
827
810
  const data = await res.json();
828
811
  return data.content;
829
812
  }
830
813
  async stat(serverUrl2, path, headers) {
831
814
  const res = await this._fetch(`${serverUrl2}/api/qcli/fs/stat?path=${encodeURIComponent(path)}`, {
832
- headers
815
+ headers: cliCore.resolveHeaders(headers)
833
816
  });
834
817
  return await res.json();
835
818
  }
836
819
  async download(serverUrl2, path, headers, onProgress, signal) {
837
820
  const res = await this._fetch(`${serverUrl2}/api/qcli/fs/download?path=${encodeURIComponent(path)}`, {
838
- headers,
821
+ headers: cliCore.resolveHeaders(headers),
839
822
  signal
840
823
  });
841
824
  const contentLength = parseInt(res.headers.get("content-length") || "0", 10);
@@ -871,20 +854,20 @@ var ScpTransferService = class {
871
854
  await this._fetch(`${serverUrl2}/api/qcli/fs/upload`, {
872
855
  method: "POST",
873
856
  body: formData,
874
- headers
857
+ headers: cliCore.resolveHeaders(headers)
875
858
  });
876
859
  }
877
860
  async mkdir(serverUrl2, path, headers) {
878
861
  await this._fetch(`${serverUrl2}/api/qcli/fs/mkdir`, {
879
862
  method: "POST",
880
- headers: { "Content-Type": "application/json", ...headers },
863
+ headers: { "Content-Type": "application/json", ...cliCore.resolveHeaders(headers) },
881
864
  body: JSON.stringify({ path })
882
865
  });
883
866
  }
884
867
  async rm(serverUrl2, path, headers) {
885
868
  await this._fetch(`${serverUrl2}/api/qcli/fs/rm?path=${encodeURIComponent(path)}`, {
886
869
  method: "DELETE",
887
- headers
870
+ headers: cliCore.resolveHeaders(headers)
888
871
  });
889
872
  }
890
873
  async _fetch(url, init) {