@qodalis/cli-scp 2.0.0-beta.2 → 2.0.0-beta.20
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 +2 -2
- package/public-api.d.mts +6 -3
- package/public-api.d.ts +6 -3
- package/public-api.js +127 -108
- package/public-api.js.map +1 -1
- package/public-api.mjs +128 -109
- package/public-api.mjs.map +1 -1
- package/umd/index.global.js +356 -165
package/public-api.mjs
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import { DefaultLibraryAuthor, ICliFileTransferService_TOKEN } from '@qodalis/cli-core';
|
|
1
|
+
import { createCliToken, DefaultLibraryAuthor, resolveServerHeaders, ICliFileTransferService_TOKEN, resolveHeaders, splitShellWords } from '@qodalis/cli-core';
|
|
2
2
|
|
|
3
3
|
// src/lib/processors/cli-scp-command-processor.ts
|
|
4
4
|
|
|
5
5
|
// src/lib/version.ts
|
|
6
|
-
var LIBRARY_VERSION = "2.0.0-beta.
|
|
6
|
+
var LIBRARY_VERSION = "2.0.0-beta.20";
|
|
7
7
|
var API_VERSION = 2;
|
|
8
|
-
|
|
9
|
-
// src/lib/interfaces/index.ts
|
|
10
|
-
var IScpTransferService_TOKEN = "scp-transfer-service";
|
|
11
|
-
|
|
12
|
-
// src/lib/processors/scp-utils.ts
|
|
8
|
+
var IScpTransferService_TOKEN = createCliToken("scp-transfer-service");
|
|
13
9
|
function resolveServer(serverName, context) {
|
|
14
10
|
const servers = context.options?.servers;
|
|
15
11
|
if (!servers || servers.length === 0) {
|
|
@@ -47,10 +43,10 @@ function parseServerAndPath(value, context, args) {
|
|
|
47
43
|
if (serverArg && pathArg) {
|
|
48
44
|
return [String(serverArg), String(pathArg)];
|
|
49
45
|
}
|
|
50
|
-
|
|
46
|
+
const parts = splitShellWords(value ?? "");
|
|
47
|
+
if (parts.length === 0) {
|
|
51
48
|
return null;
|
|
52
49
|
}
|
|
53
|
-
const parts = value.trim().split(/\s+/);
|
|
54
50
|
if (parts.length < 2) {
|
|
55
51
|
if (serverArg && parts.length >= 1) {
|
|
56
52
|
return [String(serverArg), parts.join(" ")];
|
|
@@ -62,8 +58,6 @@ function parseServerAndPath(value, context, args) {
|
|
|
62
58
|
}
|
|
63
59
|
return [parts[0], parts.slice(1).join(" ")];
|
|
64
60
|
}
|
|
65
|
-
|
|
66
|
-
// src/lib/processors/cli-scp-ls-processor.ts
|
|
67
61
|
var CliScpLsProcessor = class {
|
|
68
62
|
constructor() {
|
|
69
63
|
this.command = "ls";
|
|
@@ -94,7 +88,7 @@ var CliScpLsProcessor = class {
|
|
|
94
88
|
const [serverName, path] = parsed;
|
|
95
89
|
const server = resolveServer(serverName, context);
|
|
96
90
|
if (!server) return;
|
|
97
|
-
const transferService = context.services.
|
|
91
|
+
const transferService = context.services.getRequired(
|
|
98
92
|
IScpTransferService_TOKEN
|
|
99
93
|
);
|
|
100
94
|
if (!transferService) {
|
|
@@ -106,7 +100,7 @@ var CliScpLsProcessor = class {
|
|
|
106
100
|
const entries = await transferService.ls(
|
|
107
101
|
serverUrl(server),
|
|
108
102
|
path,
|
|
109
|
-
server.headers
|
|
103
|
+
resolveServerHeaders(context.services, server.name, server.headers)
|
|
110
104
|
);
|
|
111
105
|
context.spinner?.hide();
|
|
112
106
|
if (entries.length === 0) {
|
|
@@ -131,8 +125,6 @@ var CliScpLsProcessor = class {
|
|
|
131
125
|
context.writer.writeln("List files and directories on a remote server.");
|
|
132
126
|
}
|
|
133
127
|
};
|
|
134
|
-
|
|
135
|
-
// src/lib/processors/cli-scp-cat-processor.ts
|
|
136
128
|
var CliScpCatProcessor = class {
|
|
137
129
|
constructor() {
|
|
138
130
|
this.command = "cat";
|
|
@@ -163,7 +155,7 @@ var CliScpCatProcessor = class {
|
|
|
163
155
|
const [serverName, path] = parsed;
|
|
164
156
|
const server = resolveServer(serverName, context);
|
|
165
157
|
if (!server) return;
|
|
166
|
-
const transferService = context.services.
|
|
158
|
+
const transferService = context.services.getRequired(
|
|
167
159
|
IScpTransferService_TOKEN
|
|
168
160
|
);
|
|
169
161
|
if (!transferService) {
|
|
@@ -175,7 +167,7 @@ var CliScpCatProcessor = class {
|
|
|
175
167
|
const content = await transferService.cat(
|
|
176
168
|
serverUrl(server),
|
|
177
169
|
path,
|
|
178
|
-
server.headers
|
|
170
|
+
resolveServerHeaders(context.services, server.name, server.headers)
|
|
179
171
|
);
|
|
180
172
|
context.spinner?.hide();
|
|
181
173
|
context.writer.writeln(content);
|
|
@@ -233,12 +225,11 @@ var CliScpDownloadProcessor = class {
|
|
|
233
225
|
remotePath = String(args["remote-path"] || args["path"]);
|
|
234
226
|
localPath = args["local-path"] ? String(args["local-path"]) : void 0;
|
|
235
227
|
} else {
|
|
236
|
-
const
|
|
237
|
-
if (
|
|
228
|
+
const parts = command.positionals ?? [];
|
|
229
|
+
if (parts.length === 0) {
|
|
238
230
|
context.writer.writeError("Usage: scp download <server> <remote-path> [local-path]");
|
|
239
231
|
return;
|
|
240
232
|
}
|
|
241
|
-
const parts = value.split(/\s+/);
|
|
242
233
|
if (parts.length < 2) {
|
|
243
234
|
context.writer.writeError("Usage: scp download <server> <remote-path> [local-path]");
|
|
244
235
|
return;
|
|
@@ -254,7 +245,7 @@ var CliScpDownloadProcessor = class {
|
|
|
254
245
|
localPath = localPath || remotePath.split("/").pop() || "download";
|
|
255
246
|
const server = resolveServer(serverName, context);
|
|
256
247
|
if (!server) return;
|
|
257
|
-
const transferService = context.services.
|
|
248
|
+
const transferService = context.services.getRequired(
|
|
258
249
|
IScpTransferService_TOKEN
|
|
259
250
|
);
|
|
260
251
|
if (!transferService) {
|
|
@@ -263,6 +254,7 @@ var CliScpDownloadProcessor = class {
|
|
|
263
254
|
}
|
|
264
255
|
const useBrowserDownload = command.args?.["save"] === true;
|
|
265
256
|
context.spinner?.show(`Downloading ${remotePath} from ${server.name}...`);
|
|
257
|
+
context.notifier.info(`scp: downloading from ${server.name}`);
|
|
266
258
|
const abortController = new AbortController();
|
|
267
259
|
const abortSub = context.onAbort.subscribe(() => abortController.abort());
|
|
268
260
|
try {
|
|
@@ -270,7 +262,7 @@ var CliScpDownloadProcessor = class {
|
|
|
270
262
|
const { content, size } = await transferService.download(
|
|
271
263
|
serverUrl(server),
|
|
272
264
|
remotePath,
|
|
273
|
-
server.headers,
|
|
265
|
+
resolveServerHeaders(context.services, server.name, server.headers),
|
|
274
266
|
(received, total) => {
|
|
275
267
|
const now = Date.now();
|
|
276
268
|
if (now - lastProgressUpdate < 200) return;
|
|
@@ -280,17 +272,19 @@ var CliScpDownloadProcessor = class {
|
|
|
280
272
|
context.spinner?.show(
|
|
281
273
|
`Downloading ${remotePath}... ${pct}% (${formatBytes(received)}/${formatBytes(total)})`
|
|
282
274
|
);
|
|
275
|
+
context.notifier.info(`scp: download ${pct}%`);
|
|
283
276
|
} else {
|
|
284
277
|
context.spinner?.show(
|
|
285
278
|
`Downloading ${remotePath}... ${formatBytes(received)}`
|
|
286
279
|
);
|
|
280
|
+
context.notifier.info(`scp: download ${formatBytes(received)}`);
|
|
287
281
|
}
|
|
288
282
|
},
|
|
289
283
|
abortController.signal
|
|
290
284
|
);
|
|
291
285
|
context.spinner?.hide();
|
|
292
286
|
if (useBrowserDownload) {
|
|
293
|
-
const fileService = context.services.
|
|
287
|
+
const fileService = context.services.getRequired(
|
|
294
288
|
ICliFileTransferService_TOKEN
|
|
295
289
|
);
|
|
296
290
|
if (fileService) {
|
|
@@ -302,7 +296,7 @@ var CliScpDownloadProcessor = class {
|
|
|
302
296
|
context.writer.writeError("File transfer service not available for browser download.");
|
|
303
297
|
}
|
|
304
298
|
} else {
|
|
305
|
-
const fileService = context.services.
|
|
299
|
+
const fileService = context.services.getRequired(
|
|
306
300
|
ICliFileTransferService_TOKEN
|
|
307
301
|
);
|
|
308
302
|
if (fileService) {
|
|
@@ -331,7 +325,7 @@ var CliScpUploadProcessor = class {
|
|
|
331
325
|
constructor() {
|
|
332
326
|
this.command = "upload";
|
|
333
327
|
this.aliases = ["put"];
|
|
334
|
-
this.description = "Upload a
|
|
328
|
+
this.description = "Upload a file to a remote server (use --local to pick from your machine)";
|
|
335
329
|
this.acceptsRawInput = true;
|
|
336
330
|
this.valueRequired = true;
|
|
337
331
|
this.parameters = [
|
|
@@ -343,8 +337,8 @@ var CliScpUploadProcessor = class {
|
|
|
343
337
|
},
|
|
344
338
|
{
|
|
345
339
|
name: "local-path",
|
|
346
|
-
description: "Local file path",
|
|
347
|
-
required:
|
|
340
|
+
description: "Local file path (from virtual filesystem)",
|
|
341
|
+
required: false,
|
|
348
342
|
type: "string"
|
|
349
343
|
},
|
|
350
344
|
{
|
|
@@ -352,71 +346,103 @@ var CliScpUploadProcessor = class {
|
|
|
352
346
|
description: "Remote destination path",
|
|
353
347
|
required: true,
|
|
354
348
|
type: "string"
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
name: "local",
|
|
352
|
+
description: "Pick a file from your local machine via browser file picker",
|
|
353
|
+
required: false,
|
|
354
|
+
type: "boolean"
|
|
355
355
|
}
|
|
356
356
|
];
|
|
357
357
|
}
|
|
358
358
|
async processCommand(command, context) {
|
|
359
359
|
const args = command.args || {};
|
|
360
|
+
const useLocalPicker = !!args["local"];
|
|
360
361
|
let serverName;
|
|
361
362
|
let localPath;
|
|
362
363
|
let remotePath;
|
|
363
|
-
if (args["server"] && args["
|
|
364
|
+
if (args["server"] && args["remote-path"]) {
|
|
364
365
|
serverName = String(args["server"]);
|
|
365
|
-
localPath = String(args["local-path"]);
|
|
366
|
+
localPath = args["local-path"] ? String(args["local-path"]) : void 0;
|
|
366
367
|
remotePath = String(args["remote-path"]);
|
|
367
368
|
} else {
|
|
368
|
-
const
|
|
369
|
-
if (
|
|
370
|
-
context.writer.writeError(
|
|
369
|
+
const parts = command.positionals ?? [];
|
|
370
|
+
if (parts.length === 0) {
|
|
371
|
+
context.writer.writeError(
|
|
372
|
+
useLocalPicker ? "Usage: scp upload --local <server> <remote-path>" : "Usage: scp upload <server> <local-path> <remote-path>"
|
|
373
|
+
);
|
|
371
374
|
return;
|
|
372
375
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
376
|
+
if (useLocalPicker) {
|
|
377
|
+
if (parts.length < 2) {
|
|
378
|
+
context.writer.writeError("Usage: scp upload --local <server> <remote-path>");
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
serverName = parts[0];
|
|
382
|
+
remotePath = parts[1];
|
|
383
|
+
} else {
|
|
384
|
+
if (parts.length < 3) {
|
|
385
|
+
context.writer.writeError("Usage: scp upload <server> <local-path> <remote-path>");
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
serverName = parts[0];
|
|
389
|
+
localPath = parts[1];
|
|
390
|
+
remotePath = parts[2];
|
|
377
391
|
}
|
|
378
|
-
serverName = parts[0];
|
|
379
|
-
localPath = parts[1];
|
|
380
|
-
remotePath = parts[2];
|
|
381
392
|
}
|
|
382
|
-
if (!serverName || !localPath || !remotePath) {
|
|
383
|
-
context.writer.writeError(
|
|
393
|
+
if (!serverName || !useLocalPicker && !localPath || !remotePath) {
|
|
394
|
+
context.writer.writeError(
|
|
395
|
+
useLocalPicker ? "Usage: scp upload --local <server> <remote-path>" : "Usage: scp upload <server> <local-path> <remote-path>"
|
|
396
|
+
);
|
|
384
397
|
return;
|
|
385
398
|
}
|
|
386
399
|
const server = resolveServer(serverName, context);
|
|
387
400
|
if (!server) return;
|
|
388
|
-
const fileService = context.services.
|
|
401
|
+
const fileService = context.services.getRequired(
|
|
389
402
|
ICliFileTransferService_TOKEN
|
|
390
403
|
);
|
|
391
404
|
if (!fileService) {
|
|
392
405
|
context.writer.writeError("File transfer service not available.");
|
|
393
406
|
return;
|
|
394
407
|
}
|
|
395
|
-
const transferService = context.services.
|
|
408
|
+
const transferService = context.services.getRequired(
|
|
396
409
|
IScpTransferService_TOKEN
|
|
397
410
|
);
|
|
398
411
|
if (!transferService) {
|
|
399
412
|
context.writer.writeError("SCP transfer service not available.");
|
|
400
413
|
return;
|
|
401
414
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
415
|
+
let content;
|
|
416
|
+
let filename;
|
|
417
|
+
if (useLocalPicker) {
|
|
418
|
+
const picked = await fileService.uploadFromBrowser();
|
|
419
|
+
if (!picked) {
|
|
420
|
+
context.writer.writeln("Upload cancelled.");
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
content = picked.content;
|
|
424
|
+
filename = picked.name;
|
|
425
|
+
} else {
|
|
426
|
+
context.spinner?.show(`Reading local file "${localPath}"...`);
|
|
427
|
+
content = await fileService.readFile(localPath);
|
|
405
428
|
if (content === null) {
|
|
406
429
|
context.spinner?.hide();
|
|
407
430
|
context.writer.writeError(`Local file not found: ${localPath}`);
|
|
408
431
|
return;
|
|
409
432
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
)
|
|
433
|
+
filename = localPath.split("/").pop() || "file";
|
|
434
|
+
}
|
|
435
|
+
context.spinner?.show(
|
|
436
|
+
`Uploading "${filename}" (${formatBytes(content.length)}) to ${server.name}:${remotePath}...`
|
|
437
|
+
);
|
|
438
|
+
context.notifier.info(`scp: uploading to ${server.name}`);
|
|
439
|
+
try {
|
|
414
440
|
await transferService.upload(
|
|
415
441
|
serverUrl(server),
|
|
416
442
|
remotePath,
|
|
417
443
|
content,
|
|
418
444
|
filename,
|
|
419
|
-
server.headers
|
|
445
|
+
resolveServerHeaders(context.services, server.name, server.headers)
|
|
420
446
|
);
|
|
421
447
|
context.spinner?.hide();
|
|
422
448
|
context.writer.writeSuccess(
|
|
@@ -428,12 +454,13 @@ var CliScpUploadProcessor = class {
|
|
|
428
454
|
}
|
|
429
455
|
}
|
|
430
456
|
writeDescription(context) {
|
|
431
|
-
context.writer.writeln("Upload a
|
|
432
|
-
context.writer.writeln("
|
|
457
|
+
context.writer.writeln("Upload a file to a remote server.");
|
|
458
|
+
context.writer.writeln("");
|
|
459
|
+
context.writer.writeln("Usage:");
|
|
460
|
+
context.writer.writeln(" scp upload <server> <local-path> <remote-path> Upload from virtual filesystem");
|
|
461
|
+
context.writer.writeln(" scp upload --local <server> <remote-path> Pick from your machine via browser");
|
|
433
462
|
}
|
|
434
463
|
};
|
|
435
|
-
|
|
436
|
-
// src/lib/processors/cli-scp-rm-processor.ts
|
|
437
464
|
var CliScpRmProcessor = class {
|
|
438
465
|
constructor() {
|
|
439
466
|
this.command = "rm";
|
|
@@ -464,7 +491,7 @@ var CliScpRmProcessor = class {
|
|
|
464
491
|
const [serverName, path] = parsed;
|
|
465
492
|
const server = resolveServer(serverName, context);
|
|
466
493
|
if (!server) return;
|
|
467
|
-
const transferService = context.services.
|
|
494
|
+
const transferService = context.services.getRequired(
|
|
468
495
|
IScpTransferService_TOKEN
|
|
469
496
|
);
|
|
470
497
|
if (!transferService) {
|
|
@@ -476,7 +503,7 @@ var CliScpRmProcessor = class {
|
|
|
476
503
|
await transferService.rm(
|
|
477
504
|
serverUrl(server),
|
|
478
505
|
path,
|
|
479
|
-
server.headers
|
|
506
|
+
resolveServerHeaders(context.services, server.name, server.headers)
|
|
480
507
|
);
|
|
481
508
|
context.spinner?.hide();
|
|
482
509
|
context.writer.writeSuccess(`Deleted: ${server.name}:${path}`);
|
|
@@ -489,8 +516,6 @@ var CliScpRmProcessor = class {
|
|
|
489
516
|
context.writer.writeln("Delete a file on a remote server.");
|
|
490
517
|
}
|
|
491
518
|
};
|
|
492
|
-
|
|
493
|
-
// src/lib/processors/cli-scp-mkdir-processor.ts
|
|
494
519
|
var CliScpMkdirProcessor = class {
|
|
495
520
|
constructor() {
|
|
496
521
|
this.command = "mkdir";
|
|
@@ -521,7 +546,7 @@ var CliScpMkdirProcessor = class {
|
|
|
521
546
|
const [serverName, path] = parsed;
|
|
522
547
|
const server = resolveServer(serverName, context);
|
|
523
548
|
if (!server) return;
|
|
524
|
-
const transferService = context.services.
|
|
549
|
+
const transferService = context.services.getRequired(
|
|
525
550
|
IScpTransferService_TOKEN
|
|
526
551
|
);
|
|
527
552
|
if (!transferService) {
|
|
@@ -533,7 +558,7 @@ var CliScpMkdirProcessor = class {
|
|
|
533
558
|
await transferService.mkdir(
|
|
534
559
|
serverUrl(server),
|
|
535
560
|
path,
|
|
536
|
-
server.headers
|
|
561
|
+
resolveServerHeaders(context.services, server.name, server.headers)
|
|
537
562
|
);
|
|
538
563
|
context.spinner?.hide();
|
|
539
564
|
context.writer.writeSuccess(`Created directory: ${server.name}:${path}`);
|
|
@@ -546,8 +571,6 @@ var CliScpMkdirProcessor = class {
|
|
|
546
571
|
context.writer.writeln("Create a directory on a remote server.");
|
|
547
572
|
}
|
|
548
573
|
};
|
|
549
|
-
|
|
550
|
-
// src/lib/processors/cli-scp-stat-processor.ts
|
|
551
574
|
var CliScpStatProcessor = class {
|
|
552
575
|
constructor() {
|
|
553
576
|
this.command = "stat";
|
|
@@ -578,7 +601,7 @@ var CliScpStatProcessor = class {
|
|
|
578
601
|
const [serverName, path] = parsed;
|
|
579
602
|
const server = resolveServer(serverName, context);
|
|
580
603
|
if (!server) return;
|
|
581
|
-
const transferService = context.services.
|
|
604
|
+
const transferService = context.services.getRequired(
|
|
582
605
|
IScpTransferService_TOKEN
|
|
583
606
|
);
|
|
584
607
|
if (!transferService) {
|
|
@@ -590,7 +613,7 @@ var CliScpStatProcessor = class {
|
|
|
590
613
|
const stat = await transferService.stat(
|
|
591
614
|
serverUrl(server),
|
|
592
615
|
path,
|
|
593
|
-
server.headers
|
|
616
|
+
resolveServerHeaders(context.services, server.name, server.headers)
|
|
594
617
|
);
|
|
595
618
|
context.spinner?.hide();
|
|
596
619
|
const entries = {
|
|
@@ -621,6 +644,7 @@ var CliScpCommandCommandProcessor = class {
|
|
|
621
644
|
this.description = "SCP-like file transfer between browser and remote servers";
|
|
622
645
|
this.author = DefaultLibraryAuthor;
|
|
623
646
|
this.version = LIBRARY_VERSION;
|
|
647
|
+
this.metadata = { icon: "\u{1F4C1}", module: "file management" };
|
|
624
648
|
this.acceptsRawInput = true;
|
|
625
649
|
this.processors = [
|
|
626
650
|
new CliScpLsProcessor(),
|
|
@@ -633,33 +657,25 @@ var CliScpCommandCommandProcessor = class {
|
|
|
633
657
|
];
|
|
634
658
|
}
|
|
635
659
|
async processCommand(command, context) {
|
|
636
|
-
const
|
|
637
|
-
if (
|
|
638
|
-
const colonIdx =
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
const
|
|
642
|
-
const
|
|
643
|
-
const parts2 = rest.trim().split(/\s+/);
|
|
644
|
-
const remotePath = parts2[0];
|
|
645
|
-
const localPath = parts2[1] || remotePath.split("/").pop() || "download";
|
|
660
|
+
const [first = "", second] = command.positionals ?? [];
|
|
661
|
+
if (first && !first.startsWith("-")) {
|
|
662
|
+
const colonIdx = first.indexOf(":");
|
|
663
|
+
if (colonIdx !== -1) {
|
|
664
|
+
const serverName = first.substring(0, colonIdx);
|
|
665
|
+
const remotePath = first.substring(colonIdx + 1);
|
|
666
|
+
const localPath = second || remotePath.split("/").pop() || "download";
|
|
646
667
|
if (remotePath) {
|
|
647
668
|
await this.doDownload(serverName, remotePath, localPath, command, context);
|
|
648
669
|
return;
|
|
649
670
|
}
|
|
650
671
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
const remotePath = secondPart.substring(srvColonIdx + 1);
|
|
659
|
-
if (remotePath) {
|
|
660
|
-
await this.doUpload(serverName, localPath, remotePath, context);
|
|
661
|
-
return;
|
|
662
|
-
}
|
|
672
|
+
if (second?.includes(":")) {
|
|
673
|
+
const srvColonIdx = second.indexOf(":");
|
|
674
|
+
const serverName = second.substring(0, srvColonIdx);
|
|
675
|
+
const remotePath = second.substring(srvColonIdx + 1);
|
|
676
|
+
if (remotePath) {
|
|
677
|
+
await this.doUpload(serverName, first, remotePath, context);
|
|
678
|
+
return;
|
|
663
679
|
}
|
|
664
680
|
}
|
|
665
681
|
}
|
|
@@ -671,7 +687,7 @@ var CliScpCommandCommandProcessor = class {
|
|
|
671
687
|
async doDownload(serverName, remotePath, localPath, command, context) {
|
|
672
688
|
const server = resolveServer(serverName, context);
|
|
673
689
|
if (!server) return;
|
|
674
|
-
const transferService = context.services.
|
|
690
|
+
const transferService = context.services.getRequired(
|
|
675
691
|
IScpTransferService_TOKEN
|
|
676
692
|
);
|
|
677
693
|
if (!transferService) {
|
|
@@ -680,12 +696,13 @@ var CliScpCommandCommandProcessor = class {
|
|
|
680
696
|
}
|
|
681
697
|
const useBrowserDownload = command.args?.["save"] === true;
|
|
682
698
|
context.spinner?.show(`Downloading ${remotePath} from ${server.name}...`);
|
|
699
|
+
context.notifier.info(`scp: downloading from ${server.name}`);
|
|
683
700
|
try {
|
|
684
701
|
let lastProgressUpdate = 0;
|
|
685
702
|
const { content, size } = await transferService.download(
|
|
686
703
|
serverUrl(server),
|
|
687
704
|
remotePath,
|
|
688
|
-
server.headers,
|
|
705
|
+
resolveServerHeaders(context.services, server.name, server.headers),
|
|
689
706
|
(received, total) => {
|
|
690
707
|
const now = Date.now();
|
|
691
708
|
if (now - lastProgressUpdate < 200) return;
|
|
@@ -695,15 +712,17 @@ var CliScpCommandCommandProcessor = class {
|
|
|
695
712
|
context.spinner?.show(
|
|
696
713
|
`Downloading ${remotePath}... ${pct}% (${formatBytes(received)}/${formatBytes(total)})`
|
|
697
714
|
);
|
|
715
|
+
context.notifier.info(`scp: download ${pct}%`);
|
|
698
716
|
} else {
|
|
699
717
|
context.spinner?.show(
|
|
700
718
|
`Downloading ${remotePath}... ${formatBytes(received)}`
|
|
701
719
|
);
|
|
720
|
+
context.notifier.info(`scp: download ${formatBytes(received)}`);
|
|
702
721
|
}
|
|
703
722
|
}
|
|
704
723
|
);
|
|
705
724
|
context.spinner?.hide();
|
|
706
|
-
const fileService = context.services.
|
|
725
|
+
const fileService = context.services.getRequired(
|
|
707
726
|
ICliFileTransferService_TOKEN
|
|
708
727
|
);
|
|
709
728
|
if (!fileService) {
|
|
@@ -729,14 +748,14 @@ var CliScpCommandCommandProcessor = class {
|
|
|
729
748
|
async doUpload(serverName, localPath, remotePath, context) {
|
|
730
749
|
const server = resolveServer(serverName, context);
|
|
731
750
|
if (!server) return;
|
|
732
|
-
const fileService = context.services.
|
|
751
|
+
const fileService = context.services.getRequired(
|
|
733
752
|
ICliFileTransferService_TOKEN
|
|
734
753
|
);
|
|
735
754
|
if (!fileService) {
|
|
736
755
|
context.writer.writeError("File transfer service not available.");
|
|
737
756
|
return;
|
|
738
757
|
}
|
|
739
|
-
const transferService = context.services.
|
|
758
|
+
const transferService = context.services.getRequired(
|
|
740
759
|
IScpTransferService_TOKEN
|
|
741
760
|
);
|
|
742
761
|
if (!transferService) {
|
|
@@ -744,6 +763,7 @@ var CliScpCommandCommandProcessor = class {
|
|
|
744
763
|
return;
|
|
745
764
|
}
|
|
746
765
|
context.spinner?.show(`Reading local file "${localPath}"...`);
|
|
766
|
+
context.notifier.info(`scp: reading ${localPath}`);
|
|
747
767
|
try {
|
|
748
768
|
const content = await fileService.readFile(localPath);
|
|
749
769
|
if (content === null) {
|
|
@@ -755,12 +775,13 @@ var CliScpCommandCommandProcessor = class {
|
|
|
755
775
|
context.spinner?.show(
|
|
756
776
|
`Uploading "${filename}" (${formatBytes(content.length)}) to ${server.name}:${remotePath}...`
|
|
757
777
|
);
|
|
778
|
+
context.notifier.info(`scp: uploading to ${server.name}`);
|
|
758
779
|
await transferService.upload(
|
|
759
780
|
serverUrl(server),
|
|
760
781
|
remotePath,
|
|
761
782
|
content,
|
|
762
783
|
filename,
|
|
763
|
-
server.headers
|
|
784
|
+
resolveServerHeaders(context.services, server.name, server.headers)
|
|
764
785
|
);
|
|
765
786
|
context.spinner?.hide();
|
|
766
787
|
context.writer.writeSuccess(
|
|
@@ -772,32 +793,30 @@ var CliScpCommandCommandProcessor = class {
|
|
|
772
793
|
}
|
|
773
794
|
}
|
|
774
795
|
};
|
|
775
|
-
|
|
776
|
-
// src/lib/services/scp-transfer.service.ts
|
|
777
796
|
var ScpTransferService = class {
|
|
778
797
|
async ls(serverUrl2, path, headers) {
|
|
779
|
-
const res = await this._fetch(`${serverUrl2}/api/
|
|
780
|
-
headers
|
|
798
|
+
const res = await this._fetch(`${serverUrl2}/api/qcli/fs/ls?path=${encodeURIComponent(path)}`, {
|
|
799
|
+
headers: resolveHeaders(headers)
|
|
781
800
|
});
|
|
782
801
|
const data = await res.json();
|
|
783
802
|
return data.entries;
|
|
784
803
|
}
|
|
785
804
|
async cat(serverUrl2, path, headers) {
|
|
786
|
-
const res = await this._fetch(`${serverUrl2}/api/
|
|
787
|
-
headers
|
|
805
|
+
const res = await this._fetch(`${serverUrl2}/api/qcli/fs/cat?path=${encodeURIComponent(path)}`, {
|
|
806
|
+
headers: resolveHeaders(headers)
|
|
788
807
|
});
|
|
789
808
|
const data = await res.json();
|
|
790
809
|
return data.content;
|
|
791
810
|
}
|
|
792
811
|
async stat(serverUrl2, path, headers) {
|
|
793
|
-
const res = await this._fetch(`${serverUrl2}/api/
|
|
794
|
-
headers
|
|
812
|
+
const res = await this._fetch(`${serverUrl2}/api/qcli/fs/stat?path=${encodeURIComponent(path)}`, {
|
|
813
|
+
headers: resolveHeaders(headers)
|
|
795
814
|
});
|
|
796
815
|
return await res.json();
|
|
797
816
|
}
|
|
798
817
|
async download(serverUrl2, path, headers, onProgress, signal) {
|
|
799
|
-
const res = await this._fetch(`${serverUrl2}/api/
|
|
800
|
-
headers,
|
|
818
|
+
const res = await this._fetch(`${serverUrl2}/api/qcli/fs/download?path=${encodeURIComponent(path)}`, {
|
|
819
|
+
headers: resolveHeaders(headers),
|
|
801
820
|
signal
|
|
802
821
|
});
|
|
803
822
|
const contentLength = parseInt(res.headers.get("content-length") || "0", 10);
|
|
@@ -830,23 +849,23 @@ var ScpTransferService = class {
|
|
|
830
849
|
const formData = new FormData();
|
|
831
850
|
formData.append("path", remotePath);
|
|
832
851
|
formData.append("file", new Blob([content]), filename);
|
|
833
|
-
await this._fetch(`${serverUrl2}/api/
|
|
852
|
+
await this._fetch(`${serverUrl2}/api/qcli/fs/upload`, {
|
|
834
853
|
method: "POST",
|
|
835
854
|
body: formData,
|
|
836
|
-
headers
|
|
855
|
+
headers: resolveHeaders(headers)
|
|
837
856
|
});
|
|
838
857
|
}
|
|
839
858
|
async mkdir(serverUrl2, path, headers) {
|
|
840
|
-
await this._fetch(`${serverUrl2}/api/
|
|
859
|
+
await this._fetch(`${serverUrl2}/api/qcli/fs/mkdir`, {
|
|
841
860
|
method: "POST",
|
|
842
|
-
headers: { "Content-Type": "application/json", ...headers },
|
|
861
|
+
headers: { "Content-Type": "application/json", ...resolveHeaders(headers) },
|
|
843
862
|
body: JSON.stringify({ path })
|
|
844
863
|
});
|
|
845
864
|
}
|
|
846
865
|
async rm(serverUrl2, path, headers) {
|
|
847
|
-
await this._fetch(`${serverUrl2}/api/
|
|
866
|
+
await this._fetch(`${serverUrl2}/api/qcli/fs/rm?path=${encodeURIComponent(path)}`, {
|
|
848
867
|
method: "DELETE",
|
|
849
|
-
headers
|
|
868
|
+
headers: resolveHeaders(headers)
|
|
850
869
|
});
|
|
851
870
|
}
|
|
852
871
|
async _fetch(url, init) {
|