phillipgreenii/node-ftp-stream

View on GitHub
src/index.js

Summary

Maintainability
A
1 hr
Test Coverage
'use strict';

var debug = require('debug')('ftp-stream');
var deferred = require('deferred-stream');
var FtpClient = require('ftp');
var File = require('vinyl');
var async = require('async');

function _streamFtpGet(ftpConnectOptions, files, deferredStream) {
      var c = new FtpClient();
      c.on('error', function(e) {
                debug('Connection Error: %s', e);
        deferredStream.emit('error', e);
    });

      c.on('ready', function() {
        debug('ready to download %s', files);

        var getCalls = files.map(function(filePath){
          return function(callback) {
            debug('GETting `%s`', filePath);

            c.get(filePath, function(err, stream) {
              if (err) {
                if(err.code === 550) {
                  debug('File not found: %s', filePath);
                  err = new Error("File Not Found: " + filePath);
                }
                deferredStream.emit('error', err);
                return callback(err);
              }
              debug('got `%s`', filePath);

              stream.on('error',function(e){
                debug('Error transfering `%s`: %s', filePath, e);
                callback(e);
              });
              stream.on('end',function(){
                callback();
              });

              deferredStream.write(new File({
                path: filePath,
                contents: stream
              }));
            });
          };
        });

        //NOTE: as far as I can tell, FTP only supports on GET at a time
        // on a single connection, so this enforces that.
        async.series(getCalls, function(err){
          if(!err) {
            deferredStream.end();
          }
          c.end();
        });

      });

      c.connect(ftpConnectOptions);
}

function ftpStream(ftpConnectOptions, files) {
  //adjust for optional ftpConnectOptions
  if(!files){
    files = ftpConnectOptions;
    ftpConnectOptions = undefined;
  }
  //ensure files specified
  if(!files) {
    throw new Error('`files` must be specified');
  }
  //ensure array
  if(!Array.isArray(files)) {
    files = [files];
  }

  return deferred({objectMode: true},function(deferredStream) {
    _streamFtpGet(ftpConnectOptions, files, deferredStream);
  });
}

module.exports = ftpStream;