Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ssh2-sftp-client

Package Overview
Dependencies
Maintainers
1
Versions
74
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ssh2-sftp-client - npm Package Compare versions

Comparing version 2.4.3 to 2.5.0

test/append.js

8

package.json
{
"name": "ssh2-sftp-client",
"version": "2.4.3",
"version": "2.5.0",
"description": "ssh2 sftp client for node",

@@ -15,3 +15,3 @@ "main": "src/index.js",

"scripts": {
"test": "mocha test/index.js"
"test": "mocha"
},

@@ -22,3 +22,4 @@ "author": "见见",

"dependencies": {
"ssh2": "^0.6.1"
"concat-stream": "^2.0.0",
"ssh2": "^0.8.2"
},

@@ -29,2 +30,3 @@ "devDependencies": {

"chai-subset": "^1.6.0",
"checksum": "^0.1.1",
"dotenv": "^6.1.0",

@@ -31,0 +33,0 @@ "mocha": "^5.2.0"

## SSH2 SFTP Client
a SFTP client for node.js, a wrapper for [ssh2](https://github.com/mscdex/ssh2)
Additional documentation on the methods and available options can be found in
the [ssh2](https://github.com/mscdex/ssh2) and
[ssh2-streams](https://github.com/mscdex/ssh2-streams) documentation.
### Installation

@@ -27,2 +31,47 @@ ```shell

### Breaking Changes
Due to some incompatibilities with stream handling which breaks this module when
used with Node 10.x, some changes have been implemented that should enhance the
interface, but which also break compatibility with previous versions.
#### Option Changes
- The default encoding is null not utf8 as it was previously. This is consistent
with the defaults for the underlying SSH2 module.
- The usedCompressed option has been removed. None of the shh2-steams methods
actually support this option. The 'compress' option can be set as part of the
connection options. See [ssh2 client event](https://github.com/mscdex/ssh2#user-content-client-methods).
- The separate explicit option arguments for encoding and useCompression for some methods
have been replaced with a single 'options' argument, which is an object that
can have the following properties (defaults shown). See the
[ssh2-streams](https://github.com/mscdex/ssh2-streams) documentation for an
explination of the opt8ons.
```javascript
const defaults = {
highWaterMark: 32 * 1024,
debug: undefined,
concurrency: 64,
chunkSize: 32768,
step: undefined,
mode: 0o666,
autoClose: true,
encoding: null
};
```
#### Method Changes
#### get(srcPath, dst, options)
Used to retrieve a file from a remote SFTP server.
- srcPath: path to the file on the remote server
- dst: Either a string, which will be used as the path to store the file on the
local system or a writable stream, which will be used as the destination for a
stream pipe. If undefined, the remote file will be read into a Buffer and
the buffer returned.
- options: Options for the get operation e.g. encoding.
### Documentation

@@ -33,2 +82,3 @@ the connection to server config pls see [ssh2 client event](https://github.com/mscdex/ssh2#user-content-client-methods).

all the methods will return a Promise;
#### List

@@ -59,6 +109,6 @@ Retrieves a directory listing.

#### Get
Get a `ReadableStream` from remotePath. The encoding is passed to Node Stream (https://nodejs.org/api/stream.html) and it controls how the content is encoded. For example, when downloading binary data, 'null' should be passed (check node stream documentation). Default to 'utf8'.
Get a `ReadableStream` from remotePath. The encoding is passed to Node Stream (https://nodejs.org/api/stream.html) and it controls how the content is encoded. For example, when downloading binary data, 'null' should be passed (check node stream documentation). Default to 'null'.
```javascript
sftp.get(remoteFilePath, [useCompression], [encoding], [addtionalOptions]);
sftp.get(remoteFilePath, [options]);
```

@@ -77,5 +127,5 @@

```javascript
sftp.put(localFilePath, remoteFilePath, [useCompression], [encoding], [addtionalOptions]);
sftp.put(Buffer, remoteFilePath, [useCompression], [encoding], [addtionalOptions]);
sftp.put(Stream, remoteFilePath, [useCompression], [encoding], [addtionalOptions]);
sftp.put(localFilePath, remoteFilePath, [optons]);
sftp.put(Buffer, remoteFilePath, [options]);
sftp.put(Stream, remoteFilePath, [options]);
```

@@ -82,0 +132,0 @@

@@ -10,4 +10,6 @@ /**

const utils = require('./utils');
const fs = require('fs');
const concat = require('concat-stream');
let SftpClient = function(){
let SftpClient = function() {
this.client = new Client();

@@ -47,3 +49,3 @@ };

user: item.longname.substr(1, 3).replace(reg, ''),
group: item.longname.substr(4,3).replace(reg, ''),
group: item.longname.substr(4, 3).replace(reg, ''),
other: item.longname.substr(7, 3).replace(reg, '')

@@ -87,6 +89,10 @@ },

} else {
reject(new Error(`Error listing ${dir}: code: ${err.code} ${err.message}`));
reject(
new Error(`Error listing ${dir}: code: ${err.code} ${err.message}`)
);
}
} else {
let [type] = list.filter(item => item.filename === base).map(item => item.longname.substr(0, 1));
let [type] = list
.filter(item => item.filename === base)
.map(item => item.longname.substr(0, 1));
if (type) {

@@ -114,9 +120,9 @@ resolve(type);

if (!sftp) {
return reject(Error('sftp connect error'));
return reject(Error('sftp connect error'));
}
sftp.stat(remotePath, function (err, stats) {
if (err){
sftp.stat(remotePath, function(err, stats) {
if (err) {
reject(new Error(`Failed to stat ${remotePath}: ${err.message}`));
} else {
// format similarly to sftp.list
// format similarly to sftp.list
resolve({

@@ -126,3 +132,3 @@ mode: stats.mode,

owner: stats.uid,
group: stats.guid,
group: stats.gid,
size: stats.size,

@@ -141,12 +147,14 @@ accessTime: stats.atime * 1000,

*
* @param {String} path, path
* @param {Object} useCompression, config options
* @param {String} encoding. Encoding for the ReadStream, can be any value
* supported by node streams. Use 'null' for binary
* (https://nodejs.org/api/stream.html#stream_readable_setencoding_encoding)
* @return {Promise} stream, readable stream
* If a dst argument is provided, it must be either a string, representing the
* local path to where the data will be put, a stream, in which case data is
* piped into the stream or undefined, in which case the data is returned as
* a Buffer object.
*
* @param {String} path, remote file path
* @param {string|stream|undefined} dst, data destination
* @param {Object} userOptions, options passed to get
*
* @return {Promise}
*/
SftpClient.prototype.get = function(path, useCompression, encoding, otherOptions) {
let options = this.getOptions(useCompression, encoding, otherOptions);
SftpClient.prototype.get = function(path, dst, options) {
return new Promise((resolve, reject) => {

@@ -157,15 +165,32 @@ let sftp = this.sftp;

try {
this.client.on('error', reject);
let stream = sftp.createReadStream(path, options);
stream.on('error', (err) => {
this.client.removeListener('error', reject);
return reject(new Error(`Failed get for ${path}: ${err.message}`));
let rdr = sftp.createReadStream(path, options);
rdr.on('error', err => {
return reject(new Error(`Failed to get ${path}: ${err.message}`));
});
stream.on('readable', () => {
this.client.removeListener('error', reject);
return resolve(stream);
});
} catch(err) {
if (dst === undefined) {
// no dst specified, return buffer of data
let concatStream = concat(buff => {
return resolve(buff);
});
rdr.pipe(concatStream);
} else if (typeof dst === 'string') {
// dst local file path
let wtr = fs.createWriteStream(dst);
wtr.on('error', err => {
return reject(new Error(`Failed get for ${path}: ${err.message}`));
});
wtr.on('finish', () => {
return resolve(dst);
});
rdr.pipe(wtr);
} else {
// assume dst is a writeStream
dst.on('finish', () => {
return resolve(dst);
});
rdr.pipe(dst);
}
} catch (err) {
this.client.removeListener('error', reject);

@@ -190,3 +215,2 @@ return reject(new Error(`Failed get on ${path}: ${err.message}`));

SftpClient.prototype.fastGet = function(remotePath, localPath, options) {
options = options || {concurrency: 64, chunkSize: 32768};
return new Promise((resolve, reject) => {

@@ -196,6 +220,6 @@ let sftp = this.sftp;

if (!sftp) {
return reject(Error('sftp connect error'));
return reject(Error('sftp connect error'));
}
sftp.fastGet(remotePath, localPath, options, function (err) {
if (err){
sftp.fastGet(remotePath, localPath, options, function(err) {
if (err) {
reject(new Error(`Failed to get ${remotePath}: ${err.message}`));

@@ -219,3 +243,2 @@ }

SftpClient.prototype.fastPut = function(localPath, remotePath, options) {
options = options || {};
return new Promise((resolve, reject) => {

@@ -225,7 +248,11 @@ let sftp = this.sftp;

if (!sftp) {
return reject(new Error('sftp connect error'));
return reject(new Error('sftp connect error'));
}
sftp.fastPut(localPath, remotePath, options, function (err) {
sftp.fastPut(localPath, remotePath, options, function(err) {
if (err) {
reject(new Error(`Failed to upload ${localPath} to ${remotePath}: ${err.message}`));
reject(
new Error(
`Failed to upload ${localPath} to ${remotePath}: ${err.message}`
)
);
}

@@ -238,3 +265,2 @@ resolve(`${localPath} was successfully uploaded to ${remotePath}!`);

/**

@@ -249,5 +275,3 @@ * Create file

*/
SftpClient.prototype.put = function(input, remotePath, useCompression, encoding, otherOptions) {
let options = this.getOptions(useCompression, encoding, otherOptions);
SftpClient.prototype.put = function(input, remotePath, options) {
return new Promise((resolve, reject) => {

@@ -258,5 +282,9 @@ let sftp = this.sftp;

if (typeof input === 'string') {
sftp.fastPut(input, remotePath, options, (err) => {
sftp.fastPut(input, remotePath, options, err => {
if (err) {
return reject(new Error(`Failed to upload ${input} to ${remotePath}: ${err.message}`));
return reject(
new Error(
`Failed to upload ${input} to ${remotePath}: ${err.message}`
)
);
}

@@ -270,9 +298,13 @@ return resolve(`Uploaded ${input} to ${remotePath}`);

stream.on('error', err => {
return reject(new Error(`Failed to upload data stream to ${remotePath}: ${err.message}`));
return reject(
new Error(
`Failed to upload data stream to ${remotePath}: ${err.message}`
)
);
});
stream.on('close', () => {
stream.on('finish', () => {
return resolve(`Uploaded data stream to ${remotePath}`);
});
if (input instanceof Buffer) {

@@ -289,2 +321,52 @@ stream.end(input);

/**
* Append to file
*
* @param {Buffer|stream} input
* @param {String} remotePath,
* @param {Object} options
* @return {[type]} [description]
*/
SftpClient.prototype.append = function(input, remotePath, options) {
return new Promise((resolve, reject) => {
let sftp = this.sftp;
if (sftp) {
if (typeof input === 'string') {
throw new Error('Cannot append a file to another');
}
let stream = sftp.createWriteStream(remotePath, options);
stream.on('error', err => {
return reject(
new Error(
`Failed to upload data stream to ${remotePath}: ${err.message}`
)
);
});
stream.on('finish', () => {
return resolve(`Uploaded data stream to ${remotePath}`);
});
if (input instanceof Buffer) {
stream.end(input);
return false;
}
input.pipe(stream);
} else {
return reject(Error('sftp connect error'));
}
});
};
/**
* @async
*
* Make a dirextory on remote server
*
* @param {string} path, remote directory path.
* @param {boolean} recursive, if true, recursively create directories
* @return {Promise}.
*/
SftpClient.prototype.mkdir = function(path, recursive = false) {

@@ -295,4 +377,2 @@ let sftp = this.sftp;

return new Promise((resolve, reject) => {
if (!sftp) {

@@ -315,8 +395,10 @@ return reject(new Error('sftp connect error'));

let mkdir = p => {
let {dir} = osPath.parse(p);
return this.exists(dir).then((type) => {
let {dir} = osPath.parse(p);
return this.exists(dir)
.then(type => {
if (!type) {
return mkdir(dir);
}
}).then(() => {
})
.then(() => {
return doMkdir(p);

@@ -328,2 +410,11 @@ });

/**
* @async
*
* Remove directory on remote server
*
* @param {string} path, path to directory to be removed
* @param {boolean} recursive, if true, remove direcories/files in target
* @return {Promise}..
*/
SftpClient.prototype.rmdir = function(path, recursive = false) {

@@ -334,3 +425,2 @@ let sftp = this.sftp;

return new Promise((resolve, reject) => {
if (!sftp) {

@@ -357,16 +447,19 @@ return reject(new Error('sftp connect error'));

let dirs;
return this.list(p).then((res) => {
list = res;
files = list.filter(item => item.type === '-');
dirs = list.filter(item => item.type === 'd');
return utils.forEachAsync(files, (f) => {
return this.delete(osPath.join(p, f.name));
return this.list(p)
.then(res => {
list = res;
files = list.filter(item => item.type === '-');
dirs = list.filter(item => item.type === 'd');
return utils.forEachAsync(files, f => {
return this.delete(osPath.join(p, f.name));
});
})
.then(() => {
return utils.forEachAsync(dirs, d => {
return rmdir(osPath.join(p, d.name));
});
})
.then(() => {
return doRmdir(p);
});
}).then(() => {
return utils.forEachAsync(dirs, (d) => {
return rmdir(osPath.join(p, d.name));
});
}).then(() => {
return doRmdir(p);
});
};

@@ -383,3 +476,3 @@ return rmdir(path);

* @return {Promise} with string 'Successfully deleeted file' once resolved
*
*
*/

@@ -391,5 +484,5 @@ SftpClient.prototype.delete = function(path) {

if (!sftp) {
return reject(new Error('sftp connect error'));
return reject(new Error('sftp connect error'));
}
sftp.unlink(path, (err) => {
sftp.unlink(path, err => {
if (err) {

@@ -413,3 +506,3 @@ reject(new Error(`Failed to delete file ${path}: ${err.message}`));

* @return {Promise}
*
*
*/

@@ -421,7 +514,11 @@ SftpClient.prototype.rename = function(srcPath, remotePath) {

if (!sftp) {
return reject(new Error('sftp connect error'));
return reject(new Error('sftp connect error'));
}
sftp.rename(srcPath, remotePath, (err) => {
sftp.rename(srcPath, remotePath, err => {
if (err) {
reject(new Error(`Failed to rename file ${srcPath} to ${remotePath}: ${err.message}`));
reject(
new Error(
`Failed to rename file ${srcPath} to ${remotePath}: ${err.message}`
)
);
}

@@ -449,7 +546,9 @@ resolve(`Successfully renamed ${srcPath} to ${remotePath}`);

if (!sftp) {
return reject(new Error('sftp connect error'));
return reject(new Error('sftp connect error'));
}
sftp.chmod(remotePath, mode, (err) => {
sftp.chmod(remotePath, mode, err => {
if (err) {
reject(new Error(`Failed to change mode for ${remotePath}: ${err.message}`));
reject(
new Error(`Failed to change mode for ${remotePath}: ${err.message}`)
);
}

@@ -471,3 +570,3 @@ resolve('Successfully change file mode');

* @return {Promise} which will resolve to an sftp client object
*
*
*/

@@ -499,6 +598,6 @@ SftpClient.prototype.connect = function(config, connectMethod) {

* Close the SFTP connection
*
*
*/
SftpClient.prototype.end = function() {
return new Promise((resolve) => {
return new Promise(resolve => {
this.client.end();

@@ -509,10 +608,2 @@ resolve();

SftpClient.prototype.getOptions = function(useCompression, encoding, otherOptions) {
if(encoding === undefined){
encoding = 'utf8';
}
let options = Object.assign({}, otherOptions || {}, {encoding: encoding}, useCompression);
return options;
};
// add Event type support

@@ -523,9 +614,2 @@ SftpClient.prototype.on = function(eventType, callback) {

module.exports = SftpClient;
// sftp = new SftpClient()
// sftp.client.on('event')
//
// sftp.on('end', ()=>{}) => this.client.on('event', callback)
// sftp.on('error', () => {})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc