ssh2-sftp-client 7.2.1 → 8.0.0
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 +156 -157
- package/README.org +97 -79
- package/package.json +15 -19
- package/src/index.js +182 -104
- package/src/utils.js +28 -37
package/README.org
CHANGED
|
@@ -9,12 +9,42 @@ convenience abstraction as well as a Promise based API.
|
|
|
9
9
|
Documentation on the methods and available options in the underlying modules can
|
|
10
10
|
be found on the [[https://github.com/mscdex/ssh2][SSH2]] project pages.
|
|
11
11
|
|
|
12
|
-
Current stable release is *
|
|
13
|
-
|
|
14
|
-
Code has been tested against Node versions 14.
|
|
15
|
-
|
|
16
|
-
Node versions <
|
|
17
|
-
|
|
12
|
+
Current stable release is *v8.0.0*.
|
|
13
|
+
|
|
14
|
+
Code has been tested against Node versions 14.19.1, 16.14.2 and 17.8.0
|
|
15
|
+
|
|
16
|
+
Node versions < 12.x are not supported. However, node v10.x should still work,
|
|
17
|
+
although some tests will fail due to changes in file system functions used in
|
|
18
|
+
test setup and tear down.
|
|
19
|
+
|
|
20
|
+
** Version 8.x.x Changes
|
|
21
|
+
|
|
22
|
+
- *Breaking Change*: The API for ~uploadDir()~ and ~downloadDir()~ has been
|
|
23
|
+
changed. These methods now expect a function as the optional 3rd argument.
|
|
24
|
+
Previously, the 3rd argument was a regular expression used to filter out
|
|
25
|
+
which files and directories should be included in the upload or download
|
|
26
|
+
action. The method now expects a predicate function which will return true
|
|
27
|
+
if the target is to be included in the upload or download and false if it is
|
|
28
|
+
to be excluded. The predicate function will be called with two arguments, a
|
|
29
|
+
full path to the target object and a boolean value which is true when the
|
|
30
|
+
target is a directory, false otherwise. If no filter predicate is supplied,
|
|
31
|
+
all files and directories under the initial target directory will be
|
|
32
|
+
transferred. At this time, asynchronous filter functions are not supported.
|
|
33
|
+
|
|
34
|
+
- Internal Change: The ~rmdir()~ method has been refactored to enable
|
|
35
|
+
asynchronous deletion of files and sub-directories. This has significantly
|
|
36
|
+
increased performance when deleting larger directory trees, especially trees
|
|
37
|
+
which are /broad/ with lots of files and directories at the same level. For
|
|
38
|
+
deep narrow trees, there is less performance benefit because sub-directories
|
|
39
|
+
must be removed before parents, which imposes synchronous processing. It is
|
|
40
|
+
likely that for extremely large directory trees, the additional resources
|
|
41
|
+
required to run large numbers of asynchronous tasks will become problematic.
|
|
42
|
+
In such situations, it may be necessary to manually break up the deletion
|
|
43
|
+
process into multiple ~rmdir()~ calls. However, this is considered a fairly
|
|
44
|
+
extreme use case which is rare (a use case which wold also have been
|
|
45
|
+
problematic with the old implementation as performance would have been very
|
|
46
|
+
poor).
|
|
47
|
+
|
|
18
48
|
* Installation
|
|
19
49
|
|
|
20
50
|
#+begin_src shell
|
|
@@ -41,40 +71,6 @@ npm install ssh2-sftp-client
|
|
|
41
71
|
});
|
|
42
72
|
#+end_src
|
|
43
73
|
|
|
44
|
-
* Version 7.x Changes
|
|
45
|
-
|
|
46
|
-
- This version is based on version 1.x.x of ~ssh2~. This version of ~ssh2~ is a
|
|
47
|
-
complete re-write of the ~ssh2~ library. This re-write addresses issues
|
|
48
|
-
encountered when using node v14 as well as some design weaknesses in the
|
|
49
|
-
previous 0.8.x version.
|
|
50
|
-
|
|
51
|
-
- *Breaking Change* Expanded option handling for ~get()~ and ~put()~ methods. A number of use
|
|
52
|
-
cases were identified where setting specific options on the read and write
|
|
53
|
-
streams and the pipe operation are necessary. For example, disabling
|
|
54
|
-
~autoClose~ on streams or the ~end~ event in pipes. The ~options~ argument for
|
|
55
|
-
~get()~ and ~put()~ calls now supports properties for ~readStreamOptions~,
|
|
56
|
-
~writeStreamOptions~ and ~pipeOptions~. Note that options are only applied to
|
|
57
|
-
streams created by the ~get()~ and ~put()~ methods. Streams passed into these
|
|
58
|
-
methods are under the control of the client code and therefore cannot have
|
|
59
|
-
options supplied in arguments to those streams (you would apply such options
|
|
60
|
-
when you create the streams). Options are typically only necessary in special
|
|
61
|
-
use cases. Most of the time, no options are required. However, if you are
|
|
62
|
-
currently using options to either ~put()~ or ~get()~, you will need to update
|
|
63
|
-
your code to map these options to the new structure.
|
|
64
|
-
|
|
65
|
-
- *Breaking Change 7.1.0* A race condition was identified when using a put()
|
|
66
|
-
call with a writeStream option of ~autoClose: false~. In some situations, the
|
|
67
|
-
promise would be resolved before the final close of the write stream. This
|
|
68
|
-
could result in errors if you immediately attempt to access the uploaded
|
|
69
|
-
file. To avoid this situatioin, the promise is now resolved once a ~close~
|
|
70
|
-
event is emitted. This means that setting ~autoClose: false~ can no longer be
|
|
71
|
-
supported. The write stream for ~put()~ will autoClose once data writing has completed.
|
|
72
|
-
|
|
73
|
-
- Improved event handling. A listener for a global error event is now defined to
|
|
74
|
-
catch errors which occur in-between method calls i.e. connection lost
|
|
75
|
-
in-between calls to the library methods. A new mechanism has also been added
|
|
76
|
-
for removal of listeners when no longer required.
|
|
77
|
-
|
|
78
74
|
* Documentation
|
|
79
75
|
|
|
80
76
|
The connection options are the same as those offered by the underlying SSH2
|
|
@@ -422,7 +418,7 @@ is passed to it via a call to pipe(). If ~dst~ is undefined, the method will put
|
|
|
422
418
|
the data into a buffer and return that buffer when the Promise is resolved. If
|
|
423
419
|
~dst~ is defined, it is returned when the Promise is resolved.
|
|
424
420
|
|
|
425
|
-
In general, if
|
|
421
|
+
In general, if you're going to pass in a string as the destination, you are
|
|
426
422
|
better off using the ~fastGet()~ method.
|
|
427
423
|
|
|
428
424
|
- path :: String. Path to the remote file to download
|
|
@@ -890,18 +886,29 @@ The upload process also emits 'upload' events. These events are fired for each
|
|
|
890
886
|
successfully uploaded file. The ~upload~ event calls listeners with 1 argument,
|
|
891
887
|
an object which has properties source and destination. The source property is
|
|
892
888
|
the path of the file uploaded and the destination property is the path to where
|
|
893
|
-
the file was uploaded
|
|
894
|
-
client code to get feedback on the upload progress. You can add your own
|
|
889
|
+
the file was uploaded. The purpose of this event is to provide some way for
|
|
890
|
+
client code to get feedback on the upload progress. You can add your own listener
|
|
895
891
|
using the ~on()~ method.
|
|
896
892
|
|
|
897
|
-
The optionsl /filter/ argument is a
|
|
898
|
-
|
|
893
|
+
The optionsl /filter/ argument is a function which will be called for each item
|
|
894
|
+
to be uploaded. The function will be called with two arguments. The first
|
|
895
|
+
argument is the full path of the item to be uploaded and the second argument is
|
|
896
|
+
a boolean, which will be true if the target path is for a directory. The filter
|
|
897
|
+
function will be called for each item in the source path. If the function
|
|
898
|
+
returns true, the item will be uploaded. If it returns false, it will be
|
|
899
|
+
filtered and not uploaded. The filter function is called via the ~Array.filter~
|
|
900
|
+
method. These array comprehension methods are known to be unsafe for
|
|
901
|
+
asynchronous functions. Therefore, only synchronous filter functions are
|
|
902
|
+
supported at this time.
|
|
899
903
|
|
|
900
904
|
- srcDir :: A local file path specified as a string
|
|
901
905
|
- dstDir :: A remote file path specified as a string
|
|
902
|
-
- filter :: A
|
|
903
|
-
|
|
904
|
-
|
|
906
|
+
- filter :: A filter predicate function which is called for each item in the
|
|
907
|
+
source path. The argument will receive two arguments. The first is the full
|
|
908
|
+
path to the item and the second is a boolean which will be true if the item is
|
|
909
|
+
a directory. If the function returns true, the item will be uploaded,
|
|
910
|
+
otherwise it will be filtered out and ignored.
|
|
911
|
+
|
|
905
912
|
**** Example
|
|
906
913
|
|
|
907
914
|
#+begin_src javascript
|
|
@@ -917,36 +924,38 @@ select which files and directories to include in the upload.
|
|
|
917
924
|
require('dotenv').config({path: dotenvPath});
|
|
918
925
|
|
|
919
926
|
const config = {
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
927
|
+
host: process.env.SFTP_SERVER,
|
|
928
|
+
username: process.env.SFTP_USER,
|
|
929
|
+
password: process.env.SFTP_PASSWORD,
|
|
930
|
+
port: process.env.SFTP_PORT || 22
|
|
924
931
|
};
|
|
925
932
|
|
|
926
933
|
async function main() {
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
934
|
+
const client = new SftpClient('upload-test');
|
|
935
|
+
const src = path.join(__dirname, '..', 'test', 'testData', 'upload-src');
|
|
936
|
+
const dst = '/home/tim/upload-test';
|
|
937
|
+
|
|
938
|
+
try {
|
|
939
|
+
await client.connect(config);
|
|
940
|
+
client.on('upload', info => {
|
|
941
|
+
console.log(`Listener: Uploaded ${info.source}`);
|
|
942
|
+
});
|
|
943
|
+
let rslt = await client.uploadDir(src, dst);
|
|
944
|
+
return rslt;
|
|
945
|
+
} catch (err) {
|
|
946
|
+
console.error(err);
|
|
947
|
+
} finally {
|
|
948
|
+
client.end();
|
|
949
|
+
}
|
|
941
950
|
}
|
|
942
951
|
|
|
943
952
|
main()
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
953
|
+
.then(msg => {
|
|
954
|
+
console.log(msg);
|
|
955
|
+
})
|
|
956
|
+
.catch(err => {
|
|
957
|
+
console.log(`main error: ${err.message}`);
|
|
958
|
+
});
|
|
950
959
|
|
|
951
960
|
#+end_src
|
|
952
961
|
|
|
@@ -965,14 +974,21 @@ the remote file that has been downloaded and the destination is the local path
|
|
|
965
974
|
to where the file was downloaded to. You can add a listener for this event using
|
|
966
975
|
the ~on()~ method.
|
|
967
976
|
|
|
968
|
-
The optional /filter/ argument is a
|
|
969
|
-
|
|
977
|
+
The optional /filter/ argument is a predicate function which will be called with
|
|
978
|
+
two arguments for each potential item to be downloaded. The first argument is
|
|
979
|
+
the full path of the item and the second argument is a boolean, which will be
|
|
980
|
+
true if the item is a directory. If the function returns true, the item will be
|
|
981
|
+
included in the download. If it returns false, it will be filtered and ignored.
|
|
982
|
+
The filter function is called via the ~Array.filter~ method. These array
|
|
983
|
+
comprehension methods are known to be unsafe for asynchronous functions.
|
|
984
|
+
Therefore, only synchronous filter functions are supported at this time.
|
|
970
985
|
|
|
971
986
|
- srcDir :: A remote file path specified as a string
|
|
972
987
|
- dstDir :: A local file path specified as a string
|
|
973
|
-
- filter :: A
|
|
974
|
-
|
|
975
|
-
|
|
988
|
+
- filter :: A predicate function called with two arguments, the full path to an
|
|
989
|
+
item and a boolean value which will be true if the item is a directory. The
|
|
990
|
+
function is called for each item in the download path.
|
|
991
|
+
|
|
976
992
|
**** Example
|
|
977
993
|
|
|
978
994
|
#+begin_src javascript
|
|
@@ -1732,10 +1748,10 @@ the issue. Things which will help
|
|
|
1732
1748
|
Perhaps the best assistance is a minimal reproducible example of the issue. Once
|
|
1733
1749
|
the issue can be readily reproduced, it can usually be fixed very quickly.
|
|
1734
1750
|
|
|
1735
|
-
* Pull Requests
|
|
1751
|
+
* Pull Requests
|
|
1736
1752
|
|
|
1737
1753
|
Pull requests are always welcomed. However, please ensure your changes pass all
|
|
1738
|
-
tests and if
|
|
1754
|
+
tests and if you're adding a new feature, that tests for that feature are
|
|
1739
1755
|
included. Likewise, for new features or enhancements, please include any
|
|
1740
1756
|
relevant documentation updates.
|
|
1741
1757
|
|
|
@@ -1784,3 +1800,5 @@ Thanks to the following for their contributions -
|
|
|
1784
1800
|
'close' to resolve promise
|
|
1785
1801
|
- Maik Marschner :: Contributed fix for connect() not returning sftp object.
|
|
1786
1802
|
Also included test to check for this regression in future.
|
|
1803
|
+
- cakemasher :: Contributed fix for removeTempListeners().
|
|
1804
|
+
|
package/package.json
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ssh2-sftp-client",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "ssh2 sftp client for node",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/theophilusx/ssh2-sftp-client"
|
|
9
9
|
},
|
|
10
|
-
"keywords": [
|
|
11
|
-
"sftp",
|
|
12
|
-
"nodejs",
|
|
13
|
-
"promises"
|
|
14
|
-
],
|
|
10
|
+
"keywords": ["sftp", "nodejs", "promises"],
|
|
15
11
|
"scripts": {
|
|
16
12
|
"test": "mocha",
|
|
17
13
|
"coverage": "nyc npm run test",
|
|
@@ -29,28 +25,28 @@
|
|
|
29
25
|
}
|
|
30
26
|
],
|
|
31
27
|
"license": "Apache-2.0",
|
|
32
|
-
"dependencies": {
|
|
33
|
-
"concat-stream": "^2.0.0",
|
|
34
|
-
"promise-retry": "^2.0.1",
|
|
35
|
-
"ssh2": "^1.5.0"
|
|
36
|
-
},
|
|
37
28
|
"devDependencies": {
|
|
38
|
-
"chai": "^4.3.
|
|
29
|
+
"chai": "^4.3.6",
|
|
39
30
|
"chai-as-promised": "^7.1.1",
|
|
40
31
|
"chai-subset": "^1.6.0",
|
|
41
32
|
"checksum": "^1.0.0",
|
|
42
|
-
"dotenv": "^
|
|
43
|
-
"eslint": "^8.
|
|
44
|
-
"eslint-config-prettier": "^8.
|
|
33
|
+
"dotenv": "^16.0.0",
|
|
34
|
+
"eslint": "^8.12.0",
|
|
35
|
+
"eslint-config-prettier": "^8.5.0",
|
|
45
36
|
"eslint-plugin-mocha": "^10.0.3",
|
|
46
37
|
"eslint-plugin-node": "^11.1.0",
|
|
47
38
|
"eslint-plugin-promise": "^6.0.0",
|
|
48
|
-
"eslint-plugin-unicorn": "^
|
|
49
|
-
"mocha": "^9.
|
|
39
|
+
"eslint-plugin-unicorn": "^42.0.0",
|
|
40
|
+
"mocha": "^9.2.2",
|
|
50
41
|
"moment": "^2.29.1",
|
|
51
42
|
"nyc": "^15.1.0",
|
|
52
|
-
"prettier": "^2.
|
|
43
|
+
"prettier": "^2.6.1",
|
|
53
44
|
"through2": "^4.0.2",
|
|
54
|
-
"winston": "^3.
|
|
45
|
+
"winston": "^3.6.0"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"concat-stream": "^2.0.0",
|
|
49
|
+
"promise-retry": "^2.0.1",
|
|
50
|
+
"ssh2": "^1.9.0"
|
|
55
51
|
}
|
|
56
52
|
}
|