Comparing version 1.1.3 to 1.2.0
# Change Log | ||
## 1.2.0 | ||
### Added | ||
- Support for keyboard-interactive. Thanks [janjaali](https://github.com/janjaali) | ||
## 1.1.3 | ||
@@ -4,0 +8,0 @@ ### Changed |
205
index.js
@@ -1,123 +0,134 @@ | ||
var Client = require('ssh2').Client | ||
var debug = require('debug')('whoosh:client') | ||
var ssh2Debug = require('debug')('whoosh:ssh2') | ||
var _ = require('lodash') | ||
var Readable = require('stream').Readable | ||
var format = require('util').format | ||
var Client = require('ssh2').Client; | ||
var debug = require('debug')('whoosh:client'); | ||
var ssh2Debug = require('debug')('whoosh:ssh2'); | ||
var _ = require('lodash'); | ||
var Readable = require('stream').Readable; | ||
var format = require('util').format; | ||
module.exports = { | ||
connect: function(config, next) { | ||
connect: function(config, next) { | ||
var connection = new Client() | ||
var once = _.once(next) | ||
var connectionUrl = format('%s@%s:%s', config.username, config.hostname, config.port) | ||
var disconnected = true | ||
var disconnecting = false | ||
var connection = new Client(); | ||
var once = _.once(next); | ||
var connectionUrl = format('%s@%s:%s', config.username, config.hostname, config.port); | ||
var disconnected = true; | ||
var disconnecting = false; | ||
debug('Connecting to server %s', connectionUrl) | ||
connection.connect(_.defaults(config, { debug: ssh2Debug })) | ||
debug('Connecting to server %s', connectionUrl); | ||
connection.connect(_.defaults(config, { debug: ssh2Debug })); | ||
connection.on('ready', function() { | ||
debug('Connected to server %s', connectionUrl) | ||
disconnected = false | ||
connection.on('ready', function() { | ||
debug('Connected to server %s', connectionUrl); | ||
disconnected = false; | ||
connection.sftp(function(err, sftp) { | ||
connection.sftp(function(err, sftp) { | ||
if (err) { | ||
connection.end() | ||
return next(err) | ||
} | ||
if (err) { | ||
connection.end(); | ||
return next(err); | ||
} | ||
sftp = _.extend(sftp, { | ||
getContent: function(remotePath, options, next) { | ||
if (arguments.length === 2) return sftp.getContent(remotePath, {}, arguments[1]) | ||
sftp = _.extend(sftp, { | ||
getContent: function(remotePath, options, next) { | ||
if (arguments.length === 2) return sftp.getContent(remotePath, {}, arguments[1]); | ||
var once = _.once(next) | ||
var content = '' | ||
var once = _.once(next); | ||
var content = ''; | ||
debug('Creating read stream to %s/%s', connectionUrl, remotePath) | ||
var readStream = sftp.createReadStream(remotePath, options) | ||
var before = new Date().getTime() | ||
debug('Creating read stream to %s/%s', connectionUrl, remotePath); | ||
var readStream = sftp.createReadStream(remotePath, options); | ||
var before = new Date().getTime(); | ||
readStream.on('data', function(chunk) { | ||
content += chunk | ||
}).on('end', function() { | ||
var duration = new Date().getTime() - before | ||
var bytes = countBytes(content) | ||
readStream.on('data', function(chunk) { | ||
content += chunk; | ||
}).on('end', function() { | ||
var duration = new Date().getTime() - before; | ||
var bytes = countBytes(content); | ||
debug('Downloaded %d bytes from %s/%s in %dms', bytes, connectionUrl, remotePath, duration) | ||
once(null, content, { bytes: bytes, duration: duration }) | ||
}).on('error', once) | ||
}, | ||
putContent: function(content, remotePath, options, next) { | ||
if (arguments.length === 3) return sftp.putContent(content, remotePath, {}, arguments[2]) | ||
debug('Downloaded %d bytes from %s/%s in %dms', bytes, connectionUrl, remotePath, duration); | ||
once(null, content, { bytes: bytes, duration: duration }); | ||
}).on('error', once); | ||
}, | ||
putContent: function(content, remotePath, options, next) { | ||
if (arguments.length === 3) return sftp.putContent(content, remotePath, {}, arguments[2]); | ||
var once = _.once(next) | ||
var once = _.once(next); | ||
debug('Creating write stream to %s/%s', connectionUrl, remotePath) | ||
var writeStream = sftp.createWriteStream(remotePath) | ||
var before = new Date().getTime() | ||
debug('Creating write stream to %s/%s', connectionUrl, remotePath); | ||
var writeStream = sftp.createWriteStream(remotePath); | ||
var before = new Date().getTime(); | ||
writeStream.on('close', function() { | ||
var duration = new Date().getTime() - before | ||
var bytes = countBytes(content) | ||
writeStream.on('close', function() { | ||
var duration = new Date().getTime() - before; | ||
var bytes = countBytes(content); | ||
debug('Uploaded %d bytes to %s/%s in %sms', bytes, connectionUrl, remotePath, duration) | ||
once(null, { bytes: bytes, duration: duration }) | ||
}).on('error', once) | ||
debug('Uploaded %d bytes to %s/%s in %sms', bytes, connectionUrl, remotePath, duration); | ||
once(null, { bytes: bytes, duration: duration }); | ||
}).on('error', once); | ||
var readStream = new Readable() | ||
readStream.push(content) | ||
readStream.push(null) | ||
readStream.pipe(writeStream) | ||
}, | ||
exists: function(remotePath, next) { | ||
sftp.stat(remotePath, function(err, stat) { | ||
if (err && err.code !== 2) return next(err) | ||
return next(null, !!stat) | ||
}) | ||
}, | ||
disconnect: function(next) { | ||
next = next || function () {}; | ||
if (!sftp.isConnected()) return next() | ||
disconnecting = true | ||
sftp.end() | ||
connection.end() | ||
connection.once('close', next) | ||
}, | ||
isConnected: function(next) { | ||
var connected = !disconnected && !disconnecting | ||
return next && next(null, connected) || connected | ||
} | ||
}) | ||
var readStream = new Readable(); | ||
readStream.push(content); | ||
readStream.push(null); | ||
readStream.pipe(writeStream); | ||
}, | ||
exists: function(remotePath, next) { | ||
sftp.stat(remotePath, function(err, stat) { | ||
if (err && err.code !== 2) return next(err); | ||
return next(null, !!stat); | ||
}); | ||
}, | ||
disconnect: function(next) { | ||
next = next || function () {}; | ||
if (!sftp.isConnected()) return next(); | ||
disconnecting = true; | ||
sftp.end(); | ||
connection.end(); | ||
connection.once('close', next); | ||
}, | ||
isConnected: function(next) { | ||
var connected = !disconnected && !disconnecting; | ||
return next && next(null, connected) || connected; | ||
}, | ||
}); | ||
once(null, sftp) | ||
}) | ||
}) | ||
once(null, sftp); | ||
}); | ||
}); | ||
connection.on('error', function(err) { | ||
debug('Received error from connection: %s:%s. Original error was: ', config.hostname, config.port, err.message) | ||
once(err) | ||
}) | ||
connection.on('keyboard-interactive', function (name, instructions, lang, prompts, finish) { | ||
var responses = _.map(prompts, function(entry) { | ||
var challenge = _.find(config.challenges, function(challenge) { | ||
return challenge.pattern.test(entry.prompt); | ||
}); | ||
if (challenge) return challenge.response; | ||
debug('No response for challenge: %s', entry.prompt); | ||
return ''; | ||
}); | ||
finish(responses); | ||
}); | ||
connection.on('end', function() { | ||
debug('Connection to %s:%s ended', config.hostname, config.port) | ||
disconnect() | ||
}) | ||
connection.on('error', function(err) { | ||
debug('Received error from connection: %s:%s. Original error was: ', config.hostname, config.port, err.message); | ||
once(err); | ||
}); | ||
connection.on('close', function() { | ||
debug('Connection to %s:%s closed', config.hostname, config.port) | ||
disconnect() | ||
}) | ||
connection.on('end', function() { | ||
debug('Connection to %s:%s ended', config.hostname, config.port); | ||
disconnect(); | ||
}); | ||
function disconnect() { | ||
disconnected = true | ||
disconnecting = false | ||
} | ||
connection.on('close', function() { | ||
debug('Connection to %s:%s closed', config.hostname, config.port); | ||
disconnect(); | ||
}); | ||
function disconnect() { | ||
disconnected = true; | ||
disconnecting = false; | ||
} | ||
} | ||
}, | ||
}; | ||
function countBytes(content) { | ||
return Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content) | ||
return Buffer.isBuffer(content) ? content.length : Buffer.byteLength(content); | ||
} | ||
{ | ||
"name": "whoosh", | ||
"version": "1.1.3", | ||
"version": "1.2.0", | ||
"description": "A streaming sftp client", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -118,3 +118,24 @@ # Whoosh | ||
### keyboard interactive | ||
If the server requires keyboard interactive authentication you can configure this as follows... | ||
```js | ||
Whoosh.connect({ | ||
hostname: 'sftp.example.com', | ||
port: 22, | ||
tryKeyboard: true, | ||
challenges: [ | ||
{ | ||
pattern: /^Username:$/, | ||
response: 'fred' | ||
}, | ||
{ | ||
pattern: /^Password:$/, | ||
response: 'secret' | ||
} | ||
] | ||
}, (err, client) => { | ||
// profit :) | ||
}) | ||
``` | ||
The exact challenge patterns will be server dependent. |
@@ -1,250 +0,250 @@ | ||
var assert = require('assert') | ||
var _ = require('lodash') | ||
var async = require('async') | ||
var fs = require('fs-extra') | ||
var crypto = require('crypto') | ||
var Whoosh = require('..') | ||
var assert = require('assert'); | ||
var _ = require('lodash'); | ||
var async = require('async'); | ||
var fs = require('fs-extra'); | ||
var crypto = require('crypto'); | ||
var Whoosh = require('..'); | ||
describe('whoosh', function() { | ||
this.slow(undefined) | ||
this.timeout(10000) | ||
this.slow(undefined); | ||
this.timeout(10000); | ||
beforeEach(nuke) | ||
beforeEach(nuke); | ||
after(nuke) | ||
after(nuke); | ||
function nuke(next) { | ||
async.series([ | ||
fs.remove.bind(fs, getLocalPath()), | ||
fs.mkdirp.bind(fs, getLocalPath()), | ||
fs.chmod.bind(fs, getLocalPath(), '0777') | ||
], next) | ||
} | ||
function nuke(next) { | ||
async.series([ | ||
fs.remove.bind(fs, getLocalPath()), | ||
fs.mkdirp.bind(fs, getLocalPath()), | ||
fs.chmod.bind(fs, getLocalPath(), '0777'), | ||
], next); | ||
} | ||
var config = { | ||
hostname: 'localhost', | ||
port: 10022, | ||
username: 'fred', | ||
password: 'password' | ||
} | ||
var config = { | ||
hostname: 'localhost', | ||
port: 10022, | ||
username: 'fred', | ||
password: 'password', | ||
}; | ||
it('should report connection errors', function(done) { | ||
Whoosh.connect(_.defaults({ hostname: 'this-server-should-not-resolve-12asdf32'}, config), function(err, whoosh) { | ||
assert.ok(err, 'Connection error was not reported') | ||
assert.ok(/getaddrinfo ENOTFOUND/.test(err.message)) | ||
done() | ||
}) | ||
}) | ||
it('should report connection errors', function(done) { | ||
Whoosh.connect(_.defaults({ hostname: 'this-server-should-not-resolve-12asdf32'}, config), function(err, whoosh) { | ||
assert.ok(err, 'Connection error was not reported'); | ||
assert.ok(/getaddrinfo ENOTFOUND/.test(err.message)); | ||
done(); | ||
}); | ||
}); | ||
it('should report connection errors', function(done) { | ||
Whoosh.connect(_.defaults({ password: 'bad'}, config), function(err, whoosh) { | ||
assert.ok(err, 'Connection error was not reported') | ||
assert.equal(err.message, 'All configured authentication methods failed') | ||
done() | ||
}) | ||
}) | ||
it('should report connection errors', function(done) { | ||
Whoosh.connect(_.defaults({ password: 'bad'}, config), function(err, whoosh) { | ||
assert.ok(err, 'Connection error was not reported'); | ||
assert.equal(err.message, 'All configured authentication methods failed'); | ||
done(); | ||
}); | ||
}); | ||
it('should connect successfully', function(done) { | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
whoosh.stat('.', function(err, stats) { | ||
assert.ifError(err) | ||
assert.ok(stats) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
it('should connect successfully', function(done) { | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
whoosh.stat('.', function(err, stats) { | ||
assert.ifError(err); | ||
assert.ok(stats); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
it('should upload text content', function(done) { | ||
var title = this.test.title | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
whoosh.putContent('test message', getRemotePath(title), function(err, stats) { | ||
assert.ifError(err) | ||
assert.equal('test message', fs.readFileSync(getLocalPath(title)).toString()) | ||
assert.equal(stats.bytes, 12) | ||
assert.ok(stats.duration > 0) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
it('should upload text content', function(done) { | ||
var title = this.test.title; | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
whoosh.putContent('test message', getRemotePath(title), function(err, stats) { | ||
assert.ifError(err); | ||
assert.equal('test message', fs.readFileSync(getLocalPath(title)).toString()); | ||
assert.equal(stats.bytes, 12); | ||
assert.ok(stats.duration > 0); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
it('should download text content', function(done) { | ||
var title = this.test.title | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
fs.writeFileSync(getLocalPath(title), 'test message') | ||
whoosh.getContent(getRemotePath(title), function(err, content, stats) { | ||
assert.ifError(err) | ||
assert.equal('test message', content) | ||
assert.equal(stats.bytes, 12) | ||
assert.ok(stats.duration > 0) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
it('should download text content', function(done) { | ||
var title = this.test.title; | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
fs.writeFileSync(getLocalPath(title), 'test message'); | ||
whoosh.getContent(getRemotePath(title), function(err, content, stats) { | ||
assert.ifError(err); | ||
assert.equal('test message', content); | ||
assert.equal(stats.bytes, 12); | ||
assert.ok(stats.duration > 0); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
it('should upload binary content', function(done) { | ||
var title = this.test.title | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
whoosh.putContent(new Buffer('test message'), getRemotePath(title), function(err, stats) { | ||
assert.ifError(err) | ||
assert.equal('test message', fs.readFileSync(getLocalPath(title)).toString()) | ||
assert.equal(stats.bytes, 12) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
it('should upload binary content', function(done) { | ||
var title = this.test.title; | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
whoosh.putContent(new Buffer('test message'), getRemotePath(title), function(err, stats) { | ||
assert.ifError(err); | ||
assert.equal('test message', fs.readFileSync(getLocalPath(title)).toString()); | ||
assert.equal(stats.bytes, 12); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
it('should download binary content', function(done) { | ||
var title = this.test.title | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
fs.writeFileSync(getLocalPath(title), new Buffer('test message')) | ||
whoosh.getContent(getRemotePath(title), function(err, content) { | ||
assert.ifError(err) | ||
assert.equal('test message', content) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
it('should download binary content', function(done) { | ||
var title = this.test.title; | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
fs.writeFileSync(getLocalPath(title), new Buffer('test message')); | ||
whoosh.getContent(getRemotePath(title), function(err, content) { | ||
assert.ifError(err); | ||
assert.equal('test message', content); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
it('should support multiple serial operations', function(done) { | ||
var title = this.test.title | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
async.series({ | ||
a: whoosh.putContent.bind(whoosh, 'test message 1', getRemotePath(title + '_1')), | ||
b: whoosh.putContent.bind(whoosh, 'test message 2', getRemotePath(title + '_2')), | ||
c: whoosh.putContent.bind(whoosh, 'test message 3', getRemotePath(title + '_3')), | ||
list: whoosh.readdir.bind(whoosh, getRemotePath()) | ||
}, function(err, results) { | ||
assert.ifError(err) | ||
assert.equal(results.list.length, 3) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
it('should support multiple serial operations', function(done) { | ||
var title = this.test.title; | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
async.series({ | ||
a: whoosh.putContent.bind(whoosh, 'test message 1', getRemotePath(title + '_1')), | ||
b: whoosh.putContent.bind(whoosh, 'test message 2', getRemotePath(title + '_2')), | ||
c: whoosh.putContent.bind(whoosh, 'test message 3', getRemotePath(title + '_3')), | ||
list: whoosh.readdir.bind(whoosh, getRemotePath()), | ||
}, function(err, results) { | ||
assert.ifError(err); | ||
assert.equal(results.list.length, 3); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
it('should upload large files', function(done) { | ||
var title = this.test.title | ||
var content = crypto.pseudoRandomBytes(1024 * 1024).toString('hex') | ||
it('should upload large files', function(done) { | ||
var title = this.test.title; | ||
var content = crypto.pseudoRandomBytes(1024 * 1024).toString('hex'); | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
whoosh.putContent(content, getRemotePath(title), function(err) { | ||
assert.ifError(err) | ||
assert.equal(content, fs.readFileSync(getLocalPath(title)).toString()) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
whoosh.putContent(content, getRemotePath(title), function(err) { | ||
assert.ifError(err); | ||
assert.equal(content, fs.readFileSync(getLocalPath(title)).toString()); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
it('should upload a lot of files', function(done) { | ||
var title = this.test.title | ||
var content = crypto.pseudoRandomBytes(1024).toString('hex') | ||
it('should upload a lot of files', function(done) { | ||
var title = this.test.title; | ||
var content = crypto.pseudoRandomBytes(1024).toString('hex'); | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
async.timesLimit(1000, 50, function(index, next) { | ||
whoosh.putContent(content, getRemotePath(title + '_' + index), next) | ||
}, function(err) { | ||
assert.ifError(err) | ||
whoosh.readdir(getRemotePath(), function(err, list) { | ||
assert.ifError(err) | ||
assert.equal(list.length, 1000) | ||
assert.ok(!_.find(list, function(stat) { | ||
return stat.attrs.size !== content.length | ||
}), 'File was corrupted during upload') | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
}) | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
async.timesLimit(1000, 50, function(index, next) { | ||
whoosh.putContent(content, getRemotePath(title + '_' + index), next); | ||
}, function(err) { | ||
assert.ifError(err); | ||
whoosh.readdir(getRemotePath(), function(err, list) { | ||
assert.ifError(err); | ||
assert.equal(list.length, 1000); | ||
assert.ok(!_.find(list, function(stat) { | ||
return stat.attrs.size !== content.length; | ||
}), 'File was corrupted during upload'); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should tolerate repeated disconnects', function(done) { | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
async.times(10, function(index, next) { | ||
whoosh.disconnect(next) | ||
}, done) | ||
}) | ||
}) | ||
it('should tolerate repeated disconnects', function(done) { | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
async.times(10, function(index, next) { | ||
whoosh.disconnect(next); | ||
}, done); | ||
}); | ||
}); | ||
it('should report connection state (sync)', function(done) { | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
assert.ok(whoosh.isConnected()) | ||
whoosh.disconnect(function() { | ||
assert.ok(!whoosh.isConnected()) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('should report connection state (sync)', function(done) { | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
assert.ok(whoosh.isConnected()); | ||
whoosh.disconnect(function() { | ||
assert.ok(!whoosh.isConnected()); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('should report connection state (async)', function(done) { | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
async.series({ | ||
shouldBeConnected: whoosh.isConnected, | ||
meh: whoosh.disconnect, | ||
shouldBeDisconnected: whoosh.isConnected | ||
}, function(err, results) { | ||
assert.ifError(err) | ||
assert.ok(results.shouldBeConnected) | ||
assert.ok(!results.shouldBeDisconnected) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('should report connection state (async)', function(done) { | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
async.series({ | ||
shouldBeConnected: whoosh.isConnected, | ||
meh: whoosh.disconnect, | ||
shouldBeDisconnected: whoosh.isConnected, | ||
}, function(err, results) { | ||
assert.ifError(err); | ||
assert.ok(results.shouldBeConnected); | ||
assert.ok(!results.shouldBeDisconnected); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('should report if a file exists', function(done) { | ||
var title = this.test.title | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
whoosh.putContent('test message', getRemotePath(title), function(err, stats) { | ||
assert.ifError(err) | ||
whoosh.exists(getRemotePath(title), function(err, exists) { | ||
assert.ifError(err) | ||
assert.equal(exists, true) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
}) | ||
it('should report if a file exists', function(done) { | ||
var title = this.test.title; | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
whoosh.putContent('test message', getRemotePath(title), function(err, stats) { | ||
assert.ifError(err); | ||
whoosh.exists(getRemotePath(title), function(err, exists) { | ||
assert.ifError(err); | ||
assert.equal(exists, true); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should report if a file does not exist', function(done) { | ||
var title = this.test.title | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
whoosh.exists(getRemotePath(title), function(err, exists) { | ||
assert.ifError(err) | ||
assert.equal(exists, false) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
it('should report if a file does not exist', function(done) { | ||
var title = this.test.title; | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
whoosh.exists(getRemotePath(title), function(err, exists) { | ||
assert.ifError(err); | ||
assert.equal(exists, false); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
it('should not disconnect after checking if a non existent file exists', function(done) { | ||
var title = this.test.title | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err) | ||
whoosh.exists(getRemotePath(title), function(err, exists) { | ||
assert.ifError(err) | ||
assert.ok(whoosh.isConnected()) | ||
whoosh.disconnect(done) | ||
}) | ||
}) | ||
}) | ||
it('should not disconnect after checking if a non existent file exists', function(done) { | ||
var title = this.test.title; | ||
Whoosh.connect(config, function(err, whoosh) { | ||
assert.ifError(err); | ||
whoosh.exists(getRemotePath(title), function(err, exists) { | ||
assert.ifError(err); | ||
assert.ok(whoosh.isConnected()); | ||
whoosh.disconnect(done); | ||
}); | ||
}); | ||
}); | ||
function getRemotePath(filename) { | ||
return 'files/uploads/' + (filename ? filename.replace(/\W/g, '_') : '') | ||
} | ||
function getRemotePath(filename) { | ||
return 'files/uploads/' + (filename ? filename.replace(/\W/g, '_') : ''); | ||
} | ||
function getLocalPath(filename) { | ||
return __dirname + '/volumes/sftp/home/fred/' + getRemotePath(filename) | ||
} | ||
function getLocalPath(filename) { | ||
return __dirname + '/volumes/sftp/home/fred/' + getRemotePath(filename); | ||
} | ||
}) | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
334
141
21289