scp-next 1.0.7 → 1.0.8
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/README.md +5 -7
- package/dist/cli/index.js +14 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +12 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,8 +44,7 @@ scp-next run <job> [source] [destination] [options]
|
|
|
44
44
|
CLI commands use `<source> <destination>`. Programmatic upload and download APIs use
|
|
45
45
|
`localPath` and `remotePath`.
|
|
46
46
|
|
|
47
|
-
Destination paths follow familiar `cp`/`scp` behavior. If the destination exists as a directory or ends with a path separator, `scp-next` places the source inside that directory using the source basename.
|
|
48
|
-
Use `--create-directories` when a destination directory may be missing.
|
|
47
|
+
Destination paths follow familiar `cp`/`scp` behavior. If the destination exists as a directory or ends with a path separator, `scp-next` places the source inside that directory using the source basename. Missing destination directories are created by default.
|
|
49
48
|
|
|
50
49
|
## Upload Examples
|
|
51
50
|
|
|
@@ -54,8 +53,7 @@ scp-next upload ./dist /var/www/example \
|
|
|
54
53
|
--host example.com \
|
|
55
54
|
--username deploy \
|
|
56
55
|
--private-key-file ~/.ssh/id_ed25519 \
|
|
57
|
-
--recursive
|
|
58
|
-
--create-directories
|
|
56
|
+
--recursive
|
|
59
57
|
```
|
|
60
58
|
|
|
61
59
|
Password authentication:
|
|
@@ -77,8 +75,7 @@ Prefer `SCP_NEXT_PASSWORD`, SSH agents, or protected private-key files for share
|
|
|
77
75
|
scp-next download /var/log/example.log ./logs/example.log \
|
|
78
76
|
--host example.com \
|
|
79
77
|
--username deploy \
|
|
80
|
-
--private-key-file ~/.ssh/id_ed25519
|
|
81
|
-
--create-directories
|
|
78
|
+
--private-key-file ~/.ssh/id_ed25519
|
|
82
79
|
```
|
|
83
80
|
|
|
84
81
|
## CLI Options
|
|
@@ -96,7 +93,8 @@ scp-next download /var/log/example.log ./logs/example.log \
|
|
|
96
93
|
| `--profile <name>` | Named server profile from the configuration file. |
|
|
97
94
|
| `--recursive` | Transfer directories recursively. |
|
|
98
95
|
| `--overwrite` | Allow replacing existing destination files. |
|
|
99
|
-
| `--create-directories` | Create missing destination directories
|
|
96
|
+
| `--create-directories` | Create missing destination directories. Enabled by default. |
|
|
97
|
+
| `--no-create-directories` | Disable automatic destination directory creation. |
|
|
100
98
|
| `--dry-run` | Resolve and validate the operation without connecting or transferring. |
|
|
101
99
|
| `--timeout <milliseconds>` | Connection and operation timeout in milliseconds. |
|
|
102
100
|
| `--verbose` | Print non-sensitive diagnostic details. |
|
package/dist/cli/index.js
CHANGED
|
@@ -564,7 +564,7 @@ async function validateDownloadOptions(options) {
|
|
|
564
564
|
}
|
|
565
565
|
assertRemotePath(options.remotePath, "remotePath");
|
|
566
566
|
validateTimeout(options.timeout);
|
|
567
|
-
await assertDownloadDestination(options.localPath, options.createDirectories);
|
|
567
|
+
await assertDownloadDestination(options.localPath, options.createDirectories ?? true);
|
|
568
568
|
if (!options.dryRun) {
|
|
569
569
|
await validateServerOptions(options);
|
|
570
570
|
}
|
|
@@ -580,6 +580,9 @@ function percentage(transferredBytes, totalBytes) {
|
|
|
580
580
|
function mergeOptions(serverOptions, transferOptions) {
|
|
581
581
|
return { ...serverOptions, ...transferOptions ?? {} };
|
|
582
582
|
}
|
|
583
|
+
function shouldCreateDirectories(options) {
|
|
584
|
+
return options.createDirectories ?? true;
|
|
585
|
+
}
|
|
583
586
|
function hasTrailingPathSeparator(inputPath) {
|
|
584
587
|
return /[\\/]$/.test(inputPath);
|
|
585
588
|
}
|
|
@@ -721,7 +724,7 @@ var ScpNextClientImpl = class {
|
|
|
721
724
|
const remoteKind = await this.transport.exists(remotePath);
|
|
722
725
|
const isDirectoryLikeDestination = remoteKind === "d" || remotePath.endsWith("/");
|
|
723
726
|
if (!isDirectoryLikeDestination) {
|
|
724
|
-
await this.ensureRemoteParent(remotePath, options
|
|
727
|
+
await this.ensureRemoteParent(remotePath, shouldCreateDirectories(options));
|
|
725
728
|
await this.assertRemoteOverwrite(remotePath, options.overwrite);
|
|
726
729
|
return remotePath;
|
|
727
730
|
}
|
|
@@ -732,7 +735,7 @@ var ScpNextClientImpl = class {
|
|
|
732
735
|
}
|
|
733
736
|
const remoteDirectory = remotePath.replace(/\/+$/g, "") || "/";
|
|
734
737
|
if (!remoteKind) {
|
|
735
|
-
if (!options
|
|
738
|
+
if (!shouldCreateDirectories(options)) {
|
|
736
739
|
throw new TransferError(`Remote destination directory does not exist: ${remoteDirectory}`, {
|
|
737
740
|
context: { remotePath }
|
|
738
741
|
});
|
|
@@ -758,7 +761,7 @@ var ScpNextClientImpl = class {
|
|
|
758
761
|
if (isDirectoryLikeDestination) {
|
|
759
762
|
const remoteDirectory = trimmedRemoteDirectory(remotePath);
|
|
760
763
|
if (!remoteKind) {
|
|
761
|
-
if (!options
|
|
764
|
+
if (!shouldCreateDirectories(options)) {
|
|
762
765
|
throw new TransferError(`Remote destination directory does not exist: ${remoteDirectory}`, {
|
|
763
766
|
context: { remotePath }
|
|
764
767
|
});
|
|
@@ -770,7 +773,7 @@ var ScpNextClientImpl = class {
|
|
|
770
773
|
return destinationRoot;
|
|
771
774
|
}
|
|
772
775
|
if (!remoteKind) {
|
|
773
|
-
if (!options
|
|
776
|
+
if (!shouldCreateDirectories(options)) {
|
|
774
777
|
throw new TransferError(`Remote destination directory does not exist: ${remotePath}`, {
|
|
775
778
|
context: { remotePath }
|
|
776
779
|
});
|
|
@@ -799,7 +802,7 @@ var ScpNextClientImpl = class {
|
|
|
799
802
|
async downloadSingleFile(options, remotePath) {
|
|
800
803
|
const localPath = await this.resolveLocalDestinationForRemoteFile(options, remotePath);
|
|
801
804
|
await this.assertLocalOverwrite(localPath, options.overwrite);
|
|
802
|
-
if (options
|
|
805
|
+
if (shouldCreateDirectories(options)) {
|
|
803
806
|
await mkdir2(path4.dirname(localPath), { recursive: true });
|
|
804
807
|
}
|
|
805
808
|
await this.transport.downloadFile(remotePath, localPath, (step) => {
|
|
@@ -821,7 +824,7 @@ var ScpNextClientImpl = class {
|
|
|
821
824
|
const totalBytes = files.reduce((sum, file) => sum + file.size, 0);
|
|
822
825
|
let completedBytes = 0;
|
|
823
826
|
let completedFiles = 0;
|
|
824
|
-
await ensureLocalDirectory(localRoot,
|
|
827
|
+
await ensureLocalDirectory(localRoot, shouldCreateDirectories(options));
|
|
825
828
|
for (const file of files) {
|
|
826
829
|
const localFile = path4.join(localRoot, ...file.relativePath.split("/"));
|
|
827
830
|
await this.assertLocalOverwrite(localFile, options.overwrite);
|
|
@@ -851,7 +854,7 @@ var ScpNextClientImpl = class {
|
|
|
851
854
|
return localDestination;
|
|
852
855
|
}
|
|
853
856
|
if (!await isExistingLocalDirectory(localDestination)) {
|
|
854
|
-
if (!options
|
|
857
|
+
if (!shouldCreateDirectories(options)) {
|
|
855
858
|
throw new TransferError(`Local destination directory does not exist: ${localDestination}`, {
|
|
856
859
|
context: { localPath: options.localPath }
|
|
857
860
|
});
|
|
@@ -867,7 +870,7 @@ var ScpNextClientImpl = class {
|
|
|
867
870
|
return localDestination;
|
|
868
871
|
}
|
|
869
872
|
if (!await isExistingLocalDirectory(localDestination)) {
|
|
870
|
-
if (!options
|
|
873
|
+
if (!shouldCreateDirectories(options)) {
|
|
871
874
|
throw new TransferError(`Local destination directory does not exist: ${localDestination}`, {
|
|
872
875
|
context: { localPath: options.localPath }
|
|
873
876
|
});
|
|
@@ -1133,7 +1136,7 @@ var DEFAULT_TRANSFER = {
|
|
|
1133
1136
|
port: 22,
|
|
1134
1137
|
recursive: false,
|
|
1135
1138
|
overwrite: false,
|
|
1136
|
-
createDirectories:
|
|
1139
|
+
createDirectories: true,
|
|
1137
1140
|
dryRun: false
|
|
1138
1141
|
};
|
|
1139
1142
|
function assignDefined(target, source) {
|
|
@@ -1323,6 +1326,7 @@ function addTransferOptions(command) {
|
|
|
1323
1326
|
command.option("--recursive", "Transfer directories recursively");
|
|
1324
1327
|
command.option("--overwrite", "Overwrite existing destination files");
|
|
1325
1328
|
command.option("--create-directories", "Create missing destination directories");
|
|
1329
|
+
command.option("--no-create-directories", "Do not create missing destination directories");
|
|
1326
1330
|
command.option("--dry-run", "Resolve and validate without connecting or transferring");
|
|
1327
1331
|
command.addOption(new Option("--timeout <milliseconds>", "Connection/operation timeout").argParser(parseInteger2));
|
|
1328
1332
|
command.option("--verbose", "Print verbose diagnostic output");
|