text: module.exports =
  /******/ (function(modules, runtime) { // webpackBootstrap
  /******/ 	"use strict";
  /******/ 	// The module cache
  /******/ 	var installedModules = {};
  /******/
  /******/ 	// The require function
  /******/ 	function __webpack_require__(moduleId) {
  /******/
  /******/ 		// Check if module is in cache
  /******/ 		if(installedModules[moduleId]) {
  /******/ 			return installedModules[moduleId].exports;
  /******/ 		}
  /******/ 		// Create a new module (and put it into the cache)
  /******/ 		var module = installedModules[moduleId] = {
  /******/ 			i: moduleId,
  /******/ 			l: false,
  /******/ 			exports: {}
  /******/ 		};
  /******/
  /******/ 		// Execute the module function
  /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  /******/
  /******/ 		// Flag the module as loaded
  /******/ 		module.l = true;
  /******/
  /******/ 		// Return the exports of the module
  /******/ 		return module.exports;
  /******/ 	}
  /******/
  /******/
  /******/ 	__webpack_require__.ab = __dirname + "/";
  /******/
  /******/ 	// the startup function
  /******/ 	function startup() {
  /******/ 		// Load entry module and return exports
  /******/ 		return __webpack_require__(539);
  /******/ 	};
  /******/ 	// initialize runtime
  /******/ 	runtime(__webpack_require__);
  /******/
  /******/ 	// run startup
  /******/ 	return startup();
  /******/ })
  /************************************************************************/
  /******/ ({
  
  /***/ 11:
  /***/ (function(module) {
  
  // Returns a wrapper function that returns a wrapped callback
  // The wrapper function should do some stuff, and return a
  // presumably different callback function.
  // This makes sure that own properties are retained, so that
  // decorations and such are not lost along the way.
  module.exports = wrappy
  function wrappy (fn, cb) {
    if (fn && cb) return wrappy(fn)(cb)
  
    if (typeof fn !== 'function')
      throw new TypeError('need wrapper function')
  
    Object.keys(fn).forEach(function (k) {
      wrapper[k] = fn[k]
    })
  
    return wrapper
  
    function wrapper() {
      var args = new Array(arguments.length)
      for (var i = 0; i < args.length; i++) {
        args[i] = arguments[i]
      }
      var ret = fn.apply(this, args)
      var cb = args[args.length-1]
      if (typeof ret === 'function' && ret !== cb) {
        Object.keys(cb).forEach(function (k) {
          ret[k] = cb[k]
        })
      }
      return ret
    }
  }
  
  
  /***/ }),
  
  /***/ 16:
  /***/ (function(module) {
  
  module.exports = require("tls");
  
  /***/ }),
  
  /***/ 49:
  /***/ (function(module, __unusedexports, __webpack_require__) {
  
  var wrappy = __webpack_require__(11)
  module.exports = wrappy(once)
  module.exports.strict = wrappy(onceStrict)
  
  once.proto = once(function () {
    Object.defineProperty(Function.prototype, 'once', {
      value: function () {
        return once(this)
      },
      configurable: true
    })
  
    Object.defineProperty(Function.prototype, 'onceStrict', {
      value: function () {
        return onceStrict(this)
      },
      configurable: true
    })
  })
  
  function once (fn) {
    var f = function () {
      if (f.called) return f.value
      f.called = true
      return f.value = fn.apply(this, arguments)
    }
    f.called = false
    return f
  }
  
  function onceStrict (fn) {
    var f = function () {
      if (f.called)
        throw new Error(f.onceError)
      f.called = true
      return f.value = fn.apply(this, arguments)
    }
    var name = fn.name || 'Function wrapped with `once`'
    f.onceError = name + " shouldn't be called more than once"
    f.called = false
    return f
  }
  
  
  /***/ }),
  
  /***/ 87:
  /***/ (function(module) {
  
  module.exports = require("os");
  
  /***/ }),
  
  /***/ 93:
  /***/ (function(module, __unusedexports, __webpack_require__) {
  
  module.exports = minimatch
  minimatch.Minimatch = Minimatch
  
  var path = { sep: '/' }
  try {
    path = __webpack_require__(622)
  } catch (er) {}
  
  var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
  var expand = __webpack_require__(306)
  
  var plTypes = {
    '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
    '?': { open: '(?:', close: ')?' },
    '+': { open: '(?:', close: ')+' },
    '*': { open: '(?:', close: ')*' },
    '@': { open: '(?:', close: ')' }
  }
  
  // any single thing other than /
  // don't need to escape / when using new RegExp()
  var qmark = '[^/]'
  
  // * => any number of characters
  var star = qmark + '*?'
  
  // ** when dots are allowed.  Anything goes, except .. and .
  // not (^ or / followed by one or two dots followed by $ or /),
  // followed by anything, any number of times.
  var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
  
  // not a ^ or / followed by a dot,
  // followed by anything, any number of times.
  var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
  
  // characters that need to be escaped in RegExp.
  var reSpecials = charSet('().*{}+?[]^$\\!')
  
  // "abc" -> { a:true, b:true, c:true }
  function charSet (s) {
    return s.split('').reduce(function (set, c) {
      set[c] = true
      return set
    }, {})
  }
  
  // normalizes slashes.
  var slashSplit = /\/+/
  
  minimatch.filter = filter
  function filter (pattern, options) {
    options = options || {}
    return function (p, i, list) {
      return minimatch(p, pattern, options)
    }
  }
  
  function ext (a, b) {
    a = a || {}
    b = b || {}
    var t = {}
    Object.keys(b).forEach(function (k) {
      t[k] = b[k]
    })
    Object.keys(a).forEach(function (k) {
      t[k] = a[k]
    })
    return t
  }
  
  minimatch.defaults = function (def) {
    if (!def || !Object.keys(def).length) return minimatch
  
    var orig = minimatch
  
    var m = function minimatch (p, pattern, options) {
      return orig.minimatch(p, pattern, ext(def, options))
    }
  
    m.Minimatch = function Minimatch (pattern, options) {
      return new orig.Minimatch(pattern, ext(def, options))
    }
  
    return m
  }
  
  Minimatch.defaults = function (def) {
    if (!def || !Object.keys(def).length) return Minimatch
    return minimatch.defaults(def).Minimatch
  }
  
  function minimatch (p, pattern, options) {
    if (typeof pattern !== 'string') {
      throw new TypeError('glob pattern string required')
    }
  
    if (!options) options = {}
  
    // shortcut: comments match nothing.
    if (!options.nocomment && pattern.charAt(0) === '#') {
      return false
    }
  
    // "" only matches ""
    if (pattern.trim() === '') return p === ''
  
    return new Minimatch(pattern, options).match(p)
  }
  
  function Minimatch (pattern, options) {
    if (!(this instanceof Minimatch)) {
      return new Minimatch(pattern, options)
    }
  
    if (typeof pattern !== 'string') {
      throw new TypeError('glob pattern string required')
    }
  
    if (!options) options = {}
    pattern = pattern.trim()
  
    // windows support: need to use /, not \
    if (path.sep !== '/') {
      pattern = pattern.split(path.sep).join('/')
    }
  
    this.options = options
    this.set = []
    this.pattern = pattern
    this.regexp = null
    this.negate = false
    this.comment = false
    this.empty = false
  
    // make the set of regexps etc.
    this.make()
  }
  
  Minimatch.prototype.debug = function () {}
  
  Minimatch.prototype.make = make
  function make () {
    // don't do it more than once.
    if (this._made) return
  
    var pattern = this.pattern
    var options = this.options
  
    // empty patterns and comments match nothing.
    if (!options.nocomment && pattern.charAt(0) === '#') {
      this.comment = true
      return
    }
    if (!pattern) {
      this.empty = true
      return
    }
  
    // step 1: figure out negation, etc.
    this.parseNegate()
  
    // step 2: expand braces
    var set = this.globSet = this.braceExpand()
  
    if (options.debug) this.debug = console.error
  
    this.debug(this.pattern, set)
  
    // step 3: now we have a set, so turn each one into a series of path-portion
    // matching patterns.
    // These will be regexps, except in the case of "**", which is
    // set to the GLOBSTAR object for globstar behavior,
    // and will not contain any / characters
    set = this.globParts = set.map(function (s) {
      return s.split(slashSplit)
    })
  
    this.debug(this.pattern, set)
  
    // glob --> regexps
    set = set.map(function (s, si, set) {
      return s.map(this.parse, this)
    }, this)
  
    this.debug(this.pattern, set)
  
    // filter out everything that didn't compile properly.
    set = set.filter(function (s) {
      return s.indexOf(false) === -1
    })
  
    this.debug(this.pattern, set)
  
    this.set = set
  }
  
  Minimatch.prototype.parseNegate = parseNegate
  function parseNegate () {
    var pattern = this.pattern
    var negate = false
    var options = this.options
    var negateOffset = 0
  
    if (options.nonegate) return
  
    for (var i = 0, l = pattern.length
      ; i < l && pattern.charAt(i) === '!'
      ; i++) {
      negate = !negate
      negateOffset++
    }
  
    if (negateOffset) this.pattern = pattern.substr(negateOffset)
    this.negate = negate
  }
  
  // Brace expansion:
  // a{b,c}d -> abd acd
  // a{b,}c -> abc ac
  // a{0..3}d -> a0d a1d a2d a3d
  // a{b,c{d,e}f}g -> abg acdfg acefg
  // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
  //
  // Invalid sets are not expanded.
  // a{2..}b -> a{2..}b
  // a{b}c -> a{b}c
  minimatch.braceExpand = function (pattern, options) {
    return braceExpand(pattern, options)
  }
  
  Minimatch.prototype.braceExpand = braceExpand
  
  function braceExpand (pattern, options) {
    if (!options) {
      if (this instanceof Minimatch) {
        options = this.options
      } else {
        options = {}
      }
    }
  
    pattern = typeof pattern === 'undefined'
      ? this.pattern : pattern
  
    if (typeof pattern === 'undefined') {
      throw new TypeError('undefined pattern')
    }
  
    if (options.nobrace ||
      !pattern.match(/\{.*\}/)) {
      // shortcut. no need to expand.
      return [pattern]
    }
  
    return expand(pattern)
  }
  
  // parse a component of the expanded set.
  // At this point, no pattern may contain "/" in it
  // so we're going to return a 2d array, where each entry is the full
  // pattern, split on '/', and then turned into a regular expression.
  // A regexp is made at the end which joins each array with an
  // escaped /, and another full one which joins each regexp with |.
  //
  // Following the lead of Bash 4.1, note that "**" only has special meaning
  // when it is the *only* thing in a path portion.  Otherwise, any series
  // of * is equivalent to a single *.  Globstar behavior is enabled by
  // default, and can be disabled by setting options.noglobstar.
  Minimatch.prototype.parse = parse
  var SUBPARSE = {}
  function parse (pattern, isSub) {
    if (pattern.length > 1024 * 64) {
      throw new TypeError('pattern is too long')
    }
  
    var options = this.options
  
    // shortcuts
    if (!options.noglobstar && pattern === '**') return GLOBSTAR
    if (pattern === '') return ''
  
    var re = ''
    var hasMagic = !!options.nocase
    var escaping = false
    // ? => one single character
    var patternListStack = []
    var negativeLists = []
    var stateChar
    var inClass = false
    var reClassStart = -1
    var classStart = -1
    // . and .. never match anything that doesn't start with .,
    // even when options.dot is set.
    var patternStart = pattern.charAt(0) === '.' ? '' // anything
    // not (start or / followed by . or .. followed by / or end)
    : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
    : '(?!\\.)'
    var self = this
  
    function clearStateChar () {
      if (stateChar) {
        // we had some state-tracking character
        // that wasn't consumed by this pass.
        switch (stateChar) {
          case '*':
            re += star
            hasMagic = true
          break
          case '?':
            re += qmark
            hasMagic = true
          break
          default:
            re += '\\' + stateChar
          break
        }
        self.debug('clearStateChar %j %j', stateChar, re)
        stateChar = false
      }
    }
  
    for (var i = 0, len = pattern.length, c
      ; (i < len) && (c = pattern.charAt(i))
      ; i++) {
      this.debug('%s\t%s %s %j', pattern, i, re, c)
  
      // skip over any that are escaped.
      if (escaping && reSpecials[c]) {
        re += '\\' + c
        escaping = false
        continue
      }
  
      switch (c) {
        case '/':
          // completely not allowed, even escaped.
          // Should already be path-split by now.
          return false
  
        case '\\':
          clearStateChar()
          escaping = true
        continue
  
        // the various stateChar values
        // for the "extglob" stuff.
        case '?':
        case '*':
        case '+':
        case '@':
        case '!':
          this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
  
          // all of those are literals inside a class, except that
          // the glob [!a] means [^a] in regexp
          if (inClass) {
            this.debug('  in class')
            if (c === '!' && i === classStart + 1) c = '^'
            re += c
            continue
          }
  
          // if we already have a stateChar, then it means
          // that there was something like ** or +? in there.
          // Handle the stateChar, then proceed with this one.
          self.debug('call clearStateChar %j', stateChar)
          clearStateChar()
          stateChar = c
          // if extglob is disabled, then +(asdf|foo) isn't a thing.
          // just clear the statechar *now*, rather than even diving into
          // the patternList stuff.
          if (options.noext) clearStateChar()
        continue
  
        case '(':
          if (inClass) {
            re += '('
            continue
          }
  
          if (!stateChar) {
            re += '\\('
            continue
          }
  
          patternListStack.push({
            type: stateChar,
            start: i - 1,
            reStart: re.length,
            open: plTypes[stateChar].open,
            close: plTypes[stateChar].close
          })
          // negation is (?:(?!js)[^/]*)
          re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
          this.debug('plType %j %j', stateChar, re)
          stateChar = false
        continue
  
        case ')':
          if (inClass || !patternListStack.length) {
            re += '\\)'
            continue
          }
  
          clearStateChar()
          hasMagic = true
          var pl = patternListStack.pop()
          // negation is (?:(?!js)[^/]*)
          // The others are (?:<pattern>)<type>
          re += pl.close
          if (pl.type === '!') {
            negativeLists.push(pl)
          }
          pl.reEnd = re.length
        continue
  
        case '|':
          if (inClass || !patternListStack.length || escaping) {
            re += '\\|'
            escaping = false
            continue
          }
  
          clearStateChar()
          re += '|'
        continue
  
        // these are mostly the same in regexp and glob
        case '[':
          // swallow any state-tracking char before the [
          clearStateChar()
  
          if (inClass) {
            re += '\\' + c
            continue
          }
  
          inClass = true
          classStart = i
          reClassStart = re.length
          re += c
        continue
  
        case ']':
          //  a right bracket shall lose its special
          //  meaning and represent itself in
          //  a bracket expression if it occurs
          //  first in the list.  -- POSIX.2 2.8.3.2
          if (i === classStart + 1 || !inClass) {
            re += '\\' + c
            escaping = false
            continue
          }
  
          // handle the case where we left a class open.
          // "[z-a]" is valid, equivalent to "\[z-a\]"
          if (inClass) {
            // split where the last [ was, make sure we don't have
            // an invalid re. if so, re-walk the contents of the
            // would-be class to re-translate any characters that
            // were passed through as-is
            // TODO: It would probably be faster to determine this
            // without a try/catch and a new RegExp, but it's tricky
            // to do safely.  For now, this is safe and works.
            var cs = pattern.substring(classStart + 1, i)
            try {
              RegExp('[' + cs + ']')
            } catch (er) {
              // not a valid class!
              var sp = this.parse(cs, SUBPARSE)
              re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
              hasMagic = hasMagic || sp[1]
              inClass = false
              continue
            }
          }
  
          // finish up the class.
          hasMagic = true
          inClass = false
          re += c
        continue
  
        default:
          // swallow any state char that wasn't consumed
          clearStateChar()
  
          if (escaping) {
            // no need
            escaping = false
          } else if (reSpecials[c]
            && !(c === '^' && inClass)) {
            re += '\\'
          }
  
          re += c
  
      } // switch
    } // for
  
    // handle the case where we left a class open.
    // "[abc" is valid, equivalent to "\[abc"
    if (inClass) {
      // split where the last [ was, and escape it
      // this is a huge pita.  We now have to re-walk
      // the contents of the would-be class to re-translate
      // any characters that were passed through as-is
      cs = pattern.substr(classStart + 1)
      sp = this.parse(cs, SUBPARSE)
      re = re.substr(0, reClassStart) + '\\[' + sp[0]
      hasMagic = hasMagic || sp[1]
    }
  
    // handle the case where we had a +( thing at the *end*
    // of the pattern.
    // each pattern list stack adds 3 chars, and we need to go through
    // and escape any | chars that were passed through as-is for the regexp.
    // Go through and escape them, taking care not to double-escape any
    // | chars that were already escaped.
    for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
      var tail = re.slice(pl.reStart + pl.open.length)
      this.debug('setting tail', re, pl)
      // maybe some even number of \, then maybe 1 \, followed by a |
      tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
        if (!$2) {
          // the | isn't already escaped, so escape it.
          $2 = '\\'
        }
  
        // need to escape all those slashes *again*, without escaping the
        // one that we need for escaping the | character.  As it works out,
        // escaping an even number of slashes can be done by simply repeating
        // it exactly after itself.  That's why this trick works.
        //
        // I am sorry that you have to see this.
        return $1 + $1 + $2 + '|'
      })
  
      this.debug('tail=%j\n   %s', tail, tail, pl, re)
      var t = pl.type === '*' ? star
        : pl.type === '?' ? qmark
        : '\\' + pl.type
  
      hasMagic = true
      re = re.slice(0, pl.reStart) + t + '\\(' + tail
    }
  
    // handle trailing things that only matter at the very end.
    clearStateChar()
    if (escaping) {
      // trailing \\
      re += '\\\\'
    }
  
    // only need to apply the nodot start if the re starts with
    // something that could conceivably capture a dot
    var addPatternStart = false
    switch (re.charAt(0)) {
      case '.':
      case '[':
      case '(': addPatternStart = true
    }
  
    // Hack to work around lack of negative lookbehind in JS
    // A pattern like: *.!(x).!(y|z) needs to ensure that a name
    // like 'a.xyz.yz' doesn't match.  So, the first negative
    // lookahead, has to look ALL the way ahead, to the end of
    // the pattern.
    for (var n = negativeLists.length - 1; n > -1; n--) {
      var nl = negativeLists[n]
  
      var nlBefore = re.slice(0, nl.reStart)
      var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
      var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
      var nlAfter = re.slice(nl.reEnd)
  
      nlLast += nlAfter
  
      // Handle nested stuff like *(*.js|!(*.json)), where open parens
      // mean that we should *not* include the ) in the bit that is considered
      // "after" the negated section.
      var openParensBefore = nlBefore.split('(').length - 1
      var cleanAfter = nlAfter
      for (i = 0; i < openParensBefore; i++) {
        cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
      }
      nlAfter = cleanAfter
  
      var dollar = ''
      if (nlAfter === '' && isSub !== SUBPARSE) {
        dollar = '$'
      }
      var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
      re = newRe
    }
  
    // if the re is not "" at this point, then we need to make sure
    // it doesn't match against an empty path part.
    // Otherwise a/* will match a/, which it should not.
    if (re !== '' && hasMagic) {
      re = '(?=.)' + re
    }
  
    if (addPatternStart) {
      re = patternStart + re
    }
  
    // parsing just a piece of a larger pattern.
    if (isSub === SUBPARSE) {
      return [re, hasMagic]
    }
  
    // skip the regexp for non-magical patterns
    // unescape anything in it, though, so that it'll be
    // an exact match against a file etc.
    if (!hasMagic) {
      return globUnescape(pattern)
    }
  
    var flags = options.nocase ? 'i' : ''
    try {
      var regExp = new RegExp('^' + re + '$', flags)
    } catch (er) {
      // If it was an invalid regular expression, then it can't match
      // anything.  This trick looks for a character after the end of
      // the string, which is of course impossible, except in multi-line
      // mode, but it's not a /m regex.
      return new RegExp('$.')
    }
  
    regExp._glob = pattern
    regExp._src = re
  
    return regExp
  }
  
  minimatch.makeRe = function (pattern, options) {
    return new Minimatch(pattern, options || {}).makeRe()
  }
  
  Minimatch.prototype.makeRe = makeRe
  function makeRe () {
    if (this.regexp || this.regexp === false) return this.regexp
  
    // at this point, this.set is a 2d array of partial
    // pattern strings, or "**".
    //
    // It's better to use .match().  This function shouldn't
    // be used, really, but it's pretty convenient sometimes,
    // when you just want to work with a regex.
    var set = this.set
  
    if (!set.length) {
      this.regexp = false
      return this.regexp
    }
    var options = this.options
  
    var twoStar = options.noglobstar ? star
      : options.dot ? twoStarDot
      : twoStarNoDot
    var flags = options.nocase ? 'i' : ''
  
    var re = set.map(function (pattern) {
      return pattern.map(function (p) {
        return (p === GLOBSTAR) ? twoStar
        : (typeof p === 'string') ? regExpEscape(p)
        : p._src
      }).join('\\\/')
    }).join('|')
  
    // must match entire pattern
    // ending in a * or ** will make it less strict.
    re = '^(?:' + re + ')$'
  
    // can match anything, as long as it's not this.
    if (this.negate) re = '^(?!' + re + ').*$'
  
    try {
      this.regexp = new RegExp(re, flags)
    } catch (ex) {
      this.regexp = false
    }
    return this.regexp
  }
  
  minimatch.match = function (list, pattern, options) {
    options = options || {}
    var mm = new Minimatch(pattern, options)
    list = list.filter(function (f) {
      return mm.match(f)
    })
    if (mm.options.nonull && !list.length) {
      list.push(pattern)
    }
    return list
  }
  
  Minimatch.prototype.match = match
  function match (f, partial) {
    this.debug('match', f, this.pattern)
    // short-circuit in the case of busted things.
    // comments, etc.
    if (this.comment) return false
    if (this.empty) return f === ''
  
    if (f === '/' && partial) return true
  
    var options = this.options
  
    // windows: need to use /, not \
    if (path.sep !== '/') {
      f = f.split(path.sep).join('/')
    }
  
    // treat the test path as a set of pathparts.
    f = f.split(slashSplit)
    this.debug(this.pattern, 'split', f)
  
    // just ONE of the pattern sets in this.set needs to match
    // in order for it to be valid.  If negating, then just one
    // match means that we have failed.
    // Either way, return on the first hit.
  
    var set = this.set
    this.debug(this.pattern, 'set', set)
  
    // Find the basename of the path by looking for the last non-empty segment
    var filename
    var i
    for (i = f.length - 1; i >= 0; i--) {
      filename = f[i]
      if (filename) break
    }
  
    for (i = 0; i < set.length; i++) {
      var pattern = set[i]
      var file = f
      if (options.matchBase && pattern.length === 1) {
        file = [filename]
      }
      var hit = this.matchOne(file, pattern, partial)
      if (hit) {
        if (options.flipNegate) return true
        return !this.negate
      }
    }
  
    // didn't get any hits.  this is success if it's a negative
    // pattern, failure otherwise.
    if (options.flipNegate) return false
    return this.negate
  }
  
  // set partial to true to test if, for example,
  // "/a/b" matches the start of "/*/b/*/d"
  // Partial means, if you run out of file before you run
  // out of pattern, then that's fine, as long as all
  // the parts match.
  Minimatch.prototype.matchOne = function (file, pattern, partial) {
    var options = this.options
  
    this.debug('matchOne',
      { 'this': this, file: file, pattern: pattern })
  
    this.debug('matchOne', file.length, pattern.length)
  
    for (var fi = 0,
        pi = 0,
        fl = file.length,
        pl = pattern.length
        ; (fi < fl) && (pi < pl)
        ; fi++, pi++) {
      this.debug('matchOne loop')
      var p = pattern[pi]
      var f = file[fi]
  
      this.debug(pattern, p, f)
  
      // should be impossible.
      // some invalid regexp stuff in the set.
      if (p === false) return false
  
      if (p === GLOBSTAR) {
        this.debug('GLOBSTAR', [pattern, p, f])
  
        // "**"
        // a/**/b/**/c would match the following:
        // a/b/x/y/z/c
        // a/x/y/z/b/c
        // a/b/x/b/x/c
        // a/b/c
        // To do this, take the rest of the pattern after
        // the **, and see if it would match the file remainder.
        // If so, return success.
        // If not, the ** "swallows" a segment, and try again.
        // This is recursively awful.
        //
        // a/**/b/**/c matching a/b/x/y/z/c
        // - a matches a
        // - doublestar
        //   - matchOne(b/x/y/z/c, b/**/c)
        //     - b matches b
        //     - doublestar
        //       - matchOne(x/y/z/c, c) -> no
        //       - matchOne(y/z/c, c) -> no
        //       - matchOne(z/c, c) -> no
        //       - matchOne(c, c) yes, hit
        var fr = fi
        var pr = pi + 1
        if (pr === pl) {
          this.debug('** at the end')
          // a ** at the end will just swallow the rest.
          // We have found a match.
          // however, it will not swallow /.x, unless
          // options.dot is set.
          // . and .. are *never* matched by **, for explosively
          // exponential reasons.
          for (; fi < fl; fi++) {
            if (file[fi] === '.' || file[fi] === '..' ||
              (!options.dot && file[fi].charAt(0) === '.')) return false
          }
          return true
        }
  
        // ok, let's see if we can swallow whatever we can.
        while (fr < fl) {
          var swallowee = file[fr]
  
          this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
  
          // XXX remove this slice.  Just pass the start index.
          if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
            this.debug('globstar found match!', fr, fl, swallowee)
            // found a match.
            return true
          } else {
            // can't swallow "." or ".." ever.
            // can only swallow ".foo" when explicitly asked.
            if (swallowee === '.' || swallowee === '..' ||
              (!options.dot && swallowee.charAt(0) === '.')) {
              this.debug('dot detected!', file, fr, pattern, pr)
              break
            }
  
            // ** swallows a segment, and continue.
            this.debug('globstar swallow a segment, and continue')
            fr++
          }
        }
  
        // no match was found.
        // However, in partial mode, we can't say this is necessarily over.
        // If there's more *pattern* left, then
        if (partial) {
          // ran out of file
          this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
          if (fr === fl) return true
        }
        return false
      }
  
      // something other than **
      // non-magic patterns just have to match exactly
      // patterns with magic have been turned into regexps.
      var hit
      if (typeof p === 'string') {
        if (options.nocase) {
          hit = f.toLowerCase() === p.toLowerCase()
        } else {
          hit = f === p
        }
        this.debug('string match', p, f, hit)
      } else {
        hit = f.match(p)
        this.debug('pattern match', p, f, hit)
      }
  
      if (!hit) return false
    }
  
    // Note: ending in / means that we'll get a final ""
    // at the end of the pattern.  This can only match a
    // corresponding "" at the end of the file.
    // If the file ends in /, then it can only match a
    // a pattern that ends in /, unless the pattern just
    // doesn't have any more for it. But, a/b/ should *not*
    // match "a/b/*", even though "" matches against the
    // [^/]*? pattern, except in partial mode, where it might
    // simply not be reached yet.
    // However, a/b/ should still satisfy a/*
  
    // now either we fell off the end of the pattern, or we're done.
    if (fi === fl && pi === pl) {
      // ran out of pattern and filename at the same time.
      // an exact hit!
      return true
    } else if (fi === fl) {
      // ran out of file, but still had pattern left.
      // this is ok if we're doing the match as part of
      // a glob fs traversal.
      return partial
    } else if (pi === pl) {
      // ran out of pattern, still have file left.
      // this is only acceptable if we're on the very last
      // empty segment of a file with a trailing slash.
      // a/* should match a/b/
      var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
      return emptyFileEnd
    }
  
    // should be unreachable.
    throw new Error('wtf?')
  }
  
  // replace stuff like \* with *
  function globUnescape (s) {
    return s.replace(/\\(.)/g, '$1')
  }
  
  function regExpEscape (s) {
    return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
  }
  
  
  /***/ }),
  
  /***/ 94:
  /***/ (function(__unusedmodule, exports) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  /**
   * Tracks progress of one socket data transfer at a time.
   */
  class ProgressTracker {
      constructor() {
          this.bytesOverall = 0;
          this.intervalMs = 500;
          this.onStop = noop;
          this.onHandle = noop;
      }
      /**
       * Register a new handler for progress info. Use `undefined` to disable reporting.
       */
      reportTo(onHandle = noop) {
          this.onHandle = onHandle;
      }
      /**
       * Start tracking transfer progress of a socket.
       *
       * @param socket  The socket to observe.
       * @param name  A name associated with this progress tracking, e.g. a filename.
       * @param type  The type of the transfer, typically "upload" or "download".
       */
      start(socket, name, type) {
          let lastBytes = 0;
          this.onStop = poll(this.intervalMs, () => {
              const bytes = socket.bytesRead + socket.bytesWritten;
              this.bytesOverall += bytes - lastBytes;
              lastBytes = bytes;
              this.onHandle({
                  name,
                  type,
                  bytes,
                  bytesOverall: this.bytesOverall
              });
          });
      }
      /**
       * Stop tracking transfer progress.
       */
      stop() {
          this.onStop(false);
      }
      /**
       * Call the progress handler one more time, then stop tracking.
       */
      updateAndStop() {
          this.onStop(true);
      }
  }
  exports.ProgressTracker = ProgressTracker;
  /**
   * Starts calling a callback function at a regular interval. The first call will go out
   * immediately. The function returns a function to stop the polling.
   */
  function poll(intervalMs, updateFunc) {
      const id = setInterval(updateFunc, intervalMs);
      const stopFunc = (stopWithUpdate) => {
          clearInterval(id);
          if (stopWithUpdate) {
              updateFunc();
          }
          // Prevent repeated calls to stop calling handler.
          updateFunc = noop;
      };
      updateFunc();
      return stopFunc;
  }
  function noop() { }
  
  
  /***/ }),
  
  /***/ 117:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  var pathModule = __webpack_require__(622);
  var isWindows = process.platform === 'win32';
  var fs = __webpack_require__(747);
  
  // JavaScript implementation of realpath, ported from node pre-v6
  
  var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
  
  function rethrow() {
    // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
    // is fairly slow to generate.
    var callback;
    if (DEBUG) {
      var backtrace = new Error;
      callback = debugCallback;
    } else
      callback = missingCallback;
  
    return callback;
  
    function debugCallback(err) {
      if (err) {
        backtrace.message = err.message;
        err = backtrace;
        missingCallback(err);
      }
    }
  
    function missingCallback(err) {
      if (err) {
        if (process.throwDeprecation)
          throw err;  // Forgot a callback but don't know where? Use NODE_DEBUG=fs
        else if (!process.noDeprecation) {
          var msg = 'fs: missing callback ' + (err.stack || err.message);
          if (process.traceDeprecation)
            console.trace(msg);
          else
            console.error(msg);
        }
      }
    }
  }
  
  function maybeCallback(cb) {
    return typeof cb === 'function' ? cb : rethrow();
  }
  
  var normalize = pathModule.normalize;
  
  // Regexp that finds the next partion of a (partial) path
  // result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
  if (isWindows) {
    var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
  } else {
    var nextPartRe = /(.*?)(?:[\/]+|$)/g;
  }
  
  // Regex to find the device root, including trailing slash. E.g. 'c:\\'.
  if (isWindows) {
    var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
  } else {
    var splitRootRe = /^[\/]*/;
  }
  
  exports.realpathSync = function realpathSync(p, cache) {
    // make p is absolute
    p = pathModule.resolve(p);
  
    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
      return cache[p];
    }
  
    var original = p,
        seenLinks = {},
        knownHard = {};
  
    // current character position in p
    var pos;
    // the partial path so far, including a trailing slash if any
    var current;
    // the partial path without a trailing slash (except when pointing at a root)
    var base;
    // the partial path scanned in the previous round, with slash
    var previous;
  
    start();
  
    function start() {
      // Skip over roots
      var m = splitRootRe.exec(p);
      pos = m[0].length;
      current = m[0];
      base = m[0];
      previous = '';
  
      // On windows, check that the root exists. On unix there is no need.
      if (isWindows && !knownHard[base]) {
        fs.lstatSync(base);
        knownHard[base] = true;
      }
    }
  
    // walk down the path, swapping out linked pathparts for their real
    // values
    // NB: p.length changes.
    while (pos < p.length) {
      // find the next part
      nextPartRe.lastIndex = pos;
      var result = nextPartRe.exec(p);
      previous = current;
      current += result[0];
      base = previous + result[1];
      pos = nextPartRe.lastIndex;
  
      // continue if not a symlink
      if (knownHard[base] || (cache && cache[base] === base)) {
        continue;
      }
  
      var resolvedLink;
      if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
        // some known symbolic link.  no need to stat again.
        resolvedLink = cache[base];
      } else {
        var stat = fs.lstatSync(base);
        if (!stat.isSymbolicLink()) {
          knownHard[base] = true;
          if (cache) cache[base] = base;
          continue;
        }
  
        // read the link if it wasn't read before
        // dev/ino always return 0 on windows, so skip the check.
        var linkTarget = null;
        if (!isWindows) {
          var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
          if (seenLinks.hasOwnProperty(id)) {
            linkTarget = seenLinks[id];
          }
        }
        if (linkTarget === null) {
          fs.statSync(base);
          linkTarget = fs.readlinkSync(base);
        }
        resolvedLink = pathModule.resolve(previous, linkTarget);
        // track this, if given a cache.
        if (cache) cache[base] = resolvedLink;
        if (!isWindows) seenLinks[id] = linkTarget;
      }
  
      // resolve the link, then start over
      p = pathModule.resolve(resolvedLink, p.slice(pos));
      start();
    }
  
    if (cache) cache[original] = p;
  
    return p;
  };
  
  
  exports.realpath = function realpath(p, cache, cb) {
    if (typeof cb !== 'function') {
      cb = maybeCallback(cache);
      cache = null;
    }
  
    // make p is absolute
    p = pathModule.resolve(p);
  
    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
      return process.nextTick(cb.bind(null, null, cache[p]));
    }
  
    var original = p,
        seenLinks = {},
        knownHard = {};
  
    // current character position in p
    var pos;
    // the partial path so far, including a trailing slash if any
    var current;
    // the partial path without a trailing slash (except when pointing at a root)
    var base;
    // the partial path scanned in the previous round, with slash
    var previous;
  
    start();
  
    function start() {
      // Skip over roots
      var m = splitRootRe.exec(p);
      pos = m[0].length;
      current = m[0];
      base = m[0];
      previous = '';
  
      // On windows, check that the root exists. On unix there is no need.
      if (isWindows && !knownHard[base]) {
        fs.lstat(base, function(err) {
          if (err) return cb(err);
          knownHard[base] = true;
          LOOP();
        });
      } else {
        process.nextTick(LOOP);
      }
    }
  
    // walk down the path, swapping out linked pathparts for their real
    // values
    function LOOP() {
      // stop if scanned past end of path
      if (pos >= p.length) {
        if (cache) cache[original] = p;
        return cb(null, p);
      }
  
      // find the next part
      nextPartRe.lastIndex = pos;
      var result = nextPartRe.exec(p);
      previous = current;
      current += result[0];
      base = previous + result[1];
      pos = nextPartRe.lastIndex;
  
      // continue if not a symlink
      if (knownHard[base] || (cache && cache[base] === base)) {
        return process.nextTick(LOOP);
      }
  
      if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
        // known symbolic link.  no need to stat again.
        return gotResolvedLink(cache[base]);
      }
  
      return fs.lstat(base, gotStat);
    }
  
    function gotStat(err, stat) {
      if (err) return cb(err);
  
      // if not a symlink, skip to the next path part
      if (!stat.isSymbolicLink()) {
        knownHard[base] = true;
        if (cache) cache[base] = base;
        return process.nextTick(LOOP);
      }
  
      // stat & read the link if not read before
      // call gotTarget as soon as the link target is known
      // dev/ino always return 0 on windows, so skip the check.
      if (!isWindows) {
        var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
        if (seenLinks.hasOwnProperty(id)) {
          return gotTarget(null, seenLinks[id], base);
        }
      }
      fs.stat(base, function(err) {
        if (err) return cb(err);
  
        fs.readlink(base, function(err, target) {
          if (!isWindows) seenLinks[id] = target;
          gotTarget(err, target);
        });
      });
    }
  
    function gotTarget(err, target, base) {
      if (err) return cb(err);
  
      var resolvedLink = pathModule.resolve(previous, target);
      if (cache) cache[base] = resolvedLink;
      gotResolvedLink(resolvedLink);
    }
  
    function gotResolvedLink(resolvedLink) {
      // resolve the link, then start over
      p = pathModule.resolve(resolvedLink, p.slice(pos));
      start();
    }
  };
  
  
  /***/ }),
  
  /***/ 245:
  /***/ (function(module, __unusedexports, __webpack_require__) {
  
  module.exports = globSync
  globSync.GlobSync = GlobSync
  
  var fs = __webpack_require__(747)
  var rp = __webpack_require__(302)
  var minimatch = __webpack_require__(93)
  var Minimatch = minimatch.Minimatch
  var Glob = __webpack_require__(402).Glob
  var util = __webpack_require__(669)
  var path = __webpack_require__(622)
  var assert = __webpack_require__(357)
  var isAbsolute = __webpack_require__(681)
  var common = __webpack_require__(856)
  var alphasort = common.alphasort
  var alphasorti = common.alphasorti
  var setopts = common.setopts
  var ownProp = common.ownProp
  var childrenIgnored = common.childrenIgnored
  var isIgnored = common.isIgnored
  
  function globSync (pattern, options) {
    if (typeof options === 'function' || arguments.length === 3)
      throw new TypeError('callback provided to sync glob\n'+
                          'See: https://github.com/isaacs/node-glob/issues/167')
  
    return new GlobSync(pattern, options).found
  }
  
  function GlobSync (pattern, options) {
    if (!pattern)
      throw new Error('must provide pattern')
  
    if (typeof options === 'function' || arguments.length === 3)
      throw new TypeError('callback provided to sync glob\n'+
                          'See: https://github.com/isaacs/node-glob/issues/167')
  
    if (!(this instanceof GlobSync))
      return new GlobSync(pattern, options)
  
    setopts(this, pattern, options)
  
    if (this.noprocess)
      return this
  
    var n = this.minimatch.set.length
    this.matches = new Array(n)
    for (var i = 0; i < n; i ++) {
      this._process(this.minimatch.set[i], i, false)
    }
    this._finish()
  }
  
  GlobSync.prototype._finish = function () {
    assert(this instanceof GlobSync)
    if (this.realpath) {
      var self = this
      this.matches.forEach(function (matchset, index) {
        var set = self.matches[index] = Object.create(null)
        for (var p in matchset) {
          try {
            p = self._makeAbs(p)
            var real = rp.realpathSync(p, self.realpathCache)
            set[real] = true
          } catch (er) {
            if (er.syscall === 'stat')
              set[self._makeAbs(p)] = true
            else
              throw er
          }
        }
      })
    }
    common.finish(this)
  }
  
  
  GlobSync.prototype._process = function (pattern, index, inGlobStar) {
    assert(this instanceof GlobSync)
  
    // Get the first [n] parts of pattern that are all strings.
    var n = 0
    while (typeof pattern[n] === 'string') {
      n ++
    }
    // now n is the index of the first one that is *not* a string.
  
    // See if there's anything else
    var prefix
    switch (n) {
      // if not, then this is rather simple
      case pattern.length:
        this._processSimple(pattern.join('/'), index)
        return
  
      case 0:
        // pattern *starts* with some non-trivial item.
        // going to readdir(cwd), but not include the prefix in matches.
        prefix = null
        break
  
      default:
        // pattern has some string bits in the front.
        // whatever it starts with, whether that's 'absolute' like /foo/bar,
        // or 'relative' like '../baz'
        prefix = pattern.slice(0, n).join('/')
        break
    }
  
    var remain = pattern.slice(n)
  
    // get the list of entries.
    var read
    if (prefix === null)
      read = '.'
    else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
      if (!prefix || !isAbsolute(prefix))
        prefix = '/' + prefix
      read = prefix
    } else
      read = prefix
  
    var abs = this._makeAbs(read)
  
    //if ignored, skip processing
    if (childrenIgnored(this, read))
      return
  
    var isGlobStar = remain[0] === minimatch.GLOBSTAR
    if (isGlobStar)
      this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
    else
      this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
  }
  
  
  GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
    var entries = this._readdir(abs, inGlobStar)
  
    // if the abs isn't a dir, then nothing can match!
    if (!entries)
      return
  
    // It will only match dot entries if it starts with a dot, or if
    // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
    var pn = remain[0]
    var negate = !!this.minimatch.negate
    var rawGlob = pn._glob
    var dotOk = this.dot || rawGlob.charAt(0) === '.'
  
    var matchedEntries = []
    for (var i = 0; i < entries.length; i++) {
      var e = entries[i]
      if (e.charAt(0) !== '.' || dotOk) {
        var m
        if (negate && !prefix) {
          m = !e.match(pn)
        } else {
          m = e.match(pn)
        }
        if (m)
          matchedEntries.push(e)
      }
    }
  
    var len = matchedEntries.length
    // If there are no matched entries, then nothing matches.
    if (len === 0)
      return
  
    // if this is the last remaining pattern bit, then no need for
    // an additional stat *unless* the user has specified mark or
    // stat explicitly.  We know they exist, since readdir returned
    // them.
  
    if (remain.length === 1 && !this.mark && !this.stat) {
      if (!this.matches[index])
        this.matches[index] = Object.create(null)
  
      for (var i = 0; i < len; i ++) {
        var e = matchedEntries[i]
        if (prefix) {
          if (prefix.slice(-1) !== '/')
            e = prefix + '/' + e
          else
            e = prefix + e
        }
  
        if (e.charAt(0) === '/' && !this.nomount) {
          e = path.join(this.root, e)
        }
        this._emitMatch(index, e)
      }
      // This was the last one, and no stats were needed
      return
    }
  
    // now test all matched entries as stand-ins for that part
    // of the pattern.
    remain.shift()
    for (var i = 0; i < len; i ++) {
      var e = matchedEntries[i]
      var newPattern
      if (prefix)
        newPattern = [prefix, e]
      else
        newPattern = [e]
      this._process(newPattern.concat(remain), index, inGlobStar)
    }
  }
  
  
  GlobSync.prototype._emitMatch = function (index, e) {
    if (isIgnored(this, e))
      return
  
    var abs = this._makeAbs(e)
  
    if (this.mark)
      e = this._mark(e)
  
    if (this.absolute) {
      e = abs
    }
  
    if (this.matches[index][e])
      return
  
    if (this.nodir) {
      var c = this.cache[abs]
      if (c === 'DIR' || Array.isArray(c))
        return
    }
  
    this.matches[index][e] = true
  
    if (this.stat)
      this._stat(e)
  }
  
  
  GlobSync.prototype._readdirInGlobStar = function (abs) {
    // follow all symlinked directories forever
    // just proceed as if this is a non-globstar situation
    if (this.follow)
      return this._readdir(abs, false)
  
    var entries
    var lstat
    var stat
    try {
      lstat = fs.lstatSync(abs)
    } catch (er) {
      if (er.code === 'ENOENT') {
        // lstat failed, doesn't exist
        return null
      }
    }
  
    var isSym = lstat && lstat.isSymbolicLink()
    this.symlinks[abs] = isSym
  
    // If it's not a symlink or a dir, then it's definitely a regular file.
    // don't bother doing a readdir in that case.
    if (!isSym && lstat && !lstat.isDirectory())
      this.cache[abs] = 'FILE'
    else
      entries = this._readdir(abs, false)
  
    return entries
  }
  
  GlobSync.prototype._readdir = function (abs, inGlobStar) {
    var entries
  
    if (inGlobStar && !ownProp(this.symlinks, abs))
      return this._readdirInGlobStar(abs)
  
    if (ownProp(this.cache, abs)) {
      var c = this.cache[abs]
      if (!c || c === 'FILE')
        return null
  
      if (Array.isArray(c))
        return c
    }
  
    try {
      return this._readdirEntries(abs, fs.readdirSync(abs))
    } catch (er) {
      this._readdirError(abs, er)
      return null
    }
  }
  
  GlobSync.prototype._readdirEntries = function (abs, entries) {
    // if we haven't asked to stat everything, then just
    // assume that everything in there exists, so we can avoid
    // having to stat it a second time.
    if (!this.mark && !this.stat) {
      for (var i = 0; i < entries.length; i ++) {
        var e = entries[i]
        if (abs === '/')
          e = abs + e
        else
          e = abs + '/' + e
        this.cache[e] = true
      }
    }
  
    this.cache[abs] = entries
  
    // mark and cache dir-ness
    return entries
  }
  
  GlobSync.prototype._readdirError = function (f, er) {
    // handle errors, and cache the information
    switch (er.code) {
      case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
      case 'ENOTDIR': // totally normal. means it *does* exist.
        var abs = this._makeAbs(f)
        this.cache[abs] = 'FILE'
        if (abs === this.cwdAbs) {
          var error = new Error(er.code + ' invalid cwd ' + this.cwd)
          error.path = this.cwd
          error.code = er.code
          throw error
        }
        break
  
      case 'ENOENT': // not terribly unusual
      case 'ELOOP':
      case 'ENAMETOOLONG':
      case 'UNKNOWN':
        this.cache[this._makeAbs(f)] = false
        break
  
      default: // some unusual error.  Treat as failure.
        this.cache[this._makeAbs(f)] = false
        if (this.strict)
          throw er
        if (!this.silent)
          console.error('glob error', er)
        break
    }
  }
  
  GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
  
    var entries = this._readdir(abs, inGlobStar)
  
    // no entries means not a dir, so it can never have matches
    // foo.txt/** doesn't match foo.txt
    if (!entries)
      return
  
    // test without the globstar, and with every child both below
    // and replacing the globstar.
    var remainWithoutGlobStar = remain.slice(1)
    var gspref = prefix ? [ prefix ] : []
    var noGlobStar = gspref.concat(remainWithoutGlobStar)
  
    // the noGlobStar pattern exits the inGlobStar state
    this._process(noGlobStar, index, false)
  
    var len = entries.length
    var isSym = this.symlinks[abs]
  
    // If it's a symlink, and we're in a globstar, then stop
    if (isSym && inGlobStar)
      return
  
    for (var i = 0; i < len; i++) {
      var e = entries[i]
      if (e.charAt(0) === '.' && !this.dot)
        continue
  
      // these two cases enter the inGlobStar state
      var instead = gspref.concat(entries[i], remainWithoutGlobStar)
      this._process(instead, index, true)
  
      var below = gspref.concat(entries[i], remain)
      this._process(below, index, true)
    }
  }
  
  GlobSync.prototype._processSimple = function (prefix, index) {
    // XXX review this.  Shouldn't it be doing the mounting etc
    // before doing stat?  kinda weird?
    var exists = this._stat(prefix)
  
    if (!this.matches[index])
      this.matches[index] = Object.create(null)
  
    // If it doesn't exist, then just mark the lack of results
    if (!exists)
      return
  
    if (prefix && isAbsolute(prefix) && !this.nomount) {
      var trail = /[\/\\]$/.test(prefix)
      if (prefix.charAt(0) === '/') {
        prefix = path.join(this.root, prefix)
      } else {
        prefix = path.resolve(this.root, prefix)
        if (trail)
          prefix += '/'
      }
    }
  
    if (process.platform === 'win32')
      prefix = prefix.replace(/\\/g, '/')
  
    // Mark this as a match
    this._emitMatch(index, prefix)
  }
  
  // Returns either 'DIR', 'FILE', or false
  GlobSync.prototype._stat = function (f) {
    var abs = this._makeAbs(f)
    var needDir = f.slice(-1) === '/'
  
    if (f.length > this.maxLength)
      return false
  
    if (!this.stat && ownProp(this.cache, abs)) {
      var c = this.cache[abs]
  
      if (Array.isArray(c))
        c = 'DIR'
  
      // It exists, but maybe not how we need it
      if (!needDir || c === 'DIR')
        return c
  
      if (needDir && c === 'FILE')
        return false
  
      // otherwise we have to stat, because maybe c=true
      // if we know it exists, but not what it is.
    }
  
    var exists
    var stat = this.statCache[abs]
    if (!stat) {
      var lstat
      try {
        lstat = fs.lstatSync(abs)
      } catch (er) {
        if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
          this.statCache[abs] = false
          return false
        }
      }
  
      if (lstat && lstat.isSymbolicLink()) {
        try {
          stat = fs.statSync(abs)
        } catch (er) {
          stat = lstat
        }
      } else {
        stat = lstat
      }
    }
  
    this.statCache[abs] = stat
  
    var c = true
    if (stat)
      c = stat.isDirectory() ? 'DIR' : 'FILE'
  
    this.cache[abs] = this.cache[abs] || c
  
    if (needDir && c === 'FILE')
      return false
  
    return c
  }
  
  GlobSync.prototype._mark = function (p) {
    return common.mark(this, p)
  }
  
  GlobSync.prototype._makeAbs = function (f) {
    return common.makeAbs(this, f)
  }
  
  
  /***/ }),
  
  /***/ 262:
  /***/ (function(__unusedmodule, exports) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const LF = "\n";
  /**
   * Parse an FTP control response as a collection of messages. A message is a complete
   * single- or multiline response. A response can also contain multiple multiline responses
   * that will each be represented by a message. A response can also be incomplete
   * and be completed on the next incoming data chunk for which case this function also
   * describes a `rest`. This function converts all CRLF to LF.
   */
  function parseControlResponse(text) {
      const lines = text.split(/\r?\n/);
      const messages = [];
      let startAt = 0;
      let tokenRegex;
      for (let i = 0; i < lines.length; i++) {
          const line = lines[i];
          // No group has been opened.
          if (!tokenRegex) {
              if (isMultiline(line)) {
                  // Open a group by setting an expected token.
                  const token = line.substr(0, 3);
                  tokenRegex = new RegExp(`^${token}(?:$| )`);
                  startAt = i;
              }
              else if (isSingleLine(line)) {
                  // Single lines can be grouped immediately.
                  messages.push(line);
              }
          }
          // Group has been opened, expect closing token.
          else if (tokenRegex.test(line)) {
              tokenRegex = undefined;
              messages.push(lines.slice(startAt, i + 1).join(LF));
          }
      }
      // The last group might not have been closed, report it as a rest.
      const rest = tokenRegex ? lines.slice(startAt).join(LF) + LF : "";
      return { messages, rest };
  }
  exports.parseControlResponse = parseControlResponse;
  function isSingleLine(line) {
      return /^\d\d\d(?:$| )/.test(line);
  }
  exports.isSingleLine = isSingleLine;
  function isMultiline(line) {
      return /^\d\d\d-/.test(line);
  }
  exports.isMultiline = isMultiline;
  /**
   * Return true if an FTP return code describes a positive completion.
   */
  function positiveCompletion(code) {
      return code >= 200 && code < 300;
  }
  exports.positiveCompletion = positiveCompletion;
  /**
   * Return true if an FTP return code describes a positive intermediate response.
   */
  function positiveIntermediate(code) {
      return code >= 300 && code < 400;
  }
  exports.positiveIntermediate = positiveIntermediate;
  
  
  /***/ }),
  
  /***/ 281:
  /***/ (function(__unusedmodule, exports) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  var FileType;
  (function (FileType) {
      FileType[FileType["Unknown"] = 0] = "Unknown";
      FileType[FileType["File"] = 1] = "File";
      FileType[FileType["Directory"] = 2] = "Directory";
      FileType[FileType["SymbolicLink"] = 3] = "SymbolicLink";
  })(FileType = exports.FileType || (exports.FileType = {}));
  /**
   * Describes a file, directory or symbolic link.
   */
  class FileInfo {
      constructor(name) {
          this.name = name;
          this.type = FileType.Unknown;
          this.size = 0;
          /**
           * Unparsed, raw modification date as a string.
           *
           * If `modifiedAt` is undefined, the FTP server you're connected to doesn't support the more modern
           * MLSD command for machine-readable directory listings. The older command LIST is then used returning
           * results that vary a lot between servers as the format hasn't been standardized. Here, directory listings
           * and especially modification dates were meant to be human-readable first.
           *
           * Be careful when still trying to parse this by yourself. Parsing dates from listings using LIST is
           * unreliable. This library decides to offer parsed dates only when they're absolutely reliable and safe to
           * use e.g. for comparisons.
           */
          this.rawModifiedAt = "";
          /**
           * Parsed modification date.
           *
           * Available if the FTP server supports the MLSD command. Only MLSD guarantees dates than can be reliably
           * parsed with the correct timezone and a resolution down to seconds. See `rawModifiedAt` property for the unparsed
           * date that is always available.
           */
          this.modifiedAt = undefined;
          /**
           * Unix permissions if present. If the underlying FTP server is not running on Unix this will be undefined.
           * If set, you might be able to edit permissions with the FTP command `SITE CHMOD`.
           */
          this.permissions = undefined;
          /**
           * Hard link count if available.
           */
          this.hardLinkCount = undefined;
          /**
           * Link name for symbolic links if available.
           */
          this.link = undefined;
          /**
           * Unix group if available.
           */
          this.group = undefined;
          /**
           * Unix user if available.
           */
          this.user = undefined;
          /**
           * Unique ID if available.
           */
          this.uniqueID = undefined;
          this.name = name;
      }
      get isDirectory() {
          return this.type === FileType.Directory;
      }
      get isSymbolicLink() {
          return this.type === FileType.SymbolicLink;
      }
      get isFile() {
          return this.type === FileType.File;
      }
      /**
       * Deprecated, legacy API. Use `rawModifiedAt` instead.
       * @deprecated
       */
      get date() {
          return this.rawModifiedAt;
      }
      set date(rawModifiedAt) {
          this.rawModifiedAt = rawModifiedAt;
      }
  }
  exports.FileInfo = FileInfo;
  FileInfo.UnixPermission = {
      Read: 4,
      Write: 2,
      Execute: 1
  };
  
  
  /***/ }),
  
  /***/ 302:
  /***/ (function(module, __unusedexports, __webpack_require__) {
  
  module.exports = realpath
  realpath.realpath = realpath
  realpath.sync = realpathSync
  realpath.realpathSync = realpathSync
  realpath.monkeypatch = monkeypatch
  realpath.unmonkeypatch = unmonkeypatch
  
  var fs = __webpack_require__(747)
  var origRealpath = fs.realpath
  var origRealpathSync = fs.realpathSync
  
  var version = process.version
  var ok = /^v[0-5]\./.test(version)
  var old = __webpack_require__(117)
  
  function newError (er) {
    return er && er.syscall === 'realpath' && (
      er.code === 'ELOOP' ||
      er.code === 'ENOMEM' ||
      er.code === 'ENAMETOOLONG'
    )
  }
  
  function realpath (p, cache, cb) {
    if (ok) {
      return origRealpath(p, cache, cb)
    }
  
    if (typeof cache === 'function') {
      cb = cache
      cache = null
    }
    origRealpath(p, cache, function (er, result) {
      if (newError(er)) {
        old.realpath(p, cache, cb)
      } else {
        cb(er, result)
      }
    })
  }
  
  function realpathSync (p, cache) {
    if (ok) {
      return origRealpathSync(p, cache)
    }
  
    try {
      return origRealpathSync(p, cache)
    } catch (er) {
      if (newError(er)) {
        return old.realpathSync(p, cache)
      } else {
        throw er
      }
    }
  }
  
  function monkeypatch () {
    fs.realpath = realpath
    fs.realpathSync = realpathSync
  }
  
  function unmonkeypatch () {
    fs.realpath = origRealpath
    fs.realpathSync = origRealpathSync
  }
  
  
  /***/ }),
  
  /***/ 305:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const fs_1 = __webpack_require__(747);
  const path_1 = __webpack_require__(622);
  const util_1 = __webpack_require__(669);
  const FtpContext_1 = __webpack_require__(973);
  const parseList_1 = __webpack_require__(932);
  const ProgressTracker_1 = __webpack_require__(94);
  const StringWriter_1 = __webpack_require__(845);
  const parseListMLSD_1 = __webpack_require__(628);
  const netUtils_1 = __webpack_require__(864);
  const transfer_1 = __webpack_require__(368);
  const parseControlResponse_1 = __webpack_require__(262);
  // Use promisify to keep the library compatible with Node 8.
  const fsReadDir = util_1.promisify(fs_1.readdir);
  const fsMkDir = util_1.promisify(fs_1.mkdir);
  const fsStat = util_1.promisify(fs_1.stat);
  const fsOpen = util_1.promisify(fs_1.open);
  const fsClose = util_1.promisify(fs_1.close);
  const fsUnlink = util_1.promisify(fs_1.unlink);
  /**
   * High-level API to interact with an FTP server.
   */
  class Client {
      /**
       * Instantiate an FTP client.
       *
       * @param timeout  Timeout in milliseconds, use 0 for no timeout. Optional, default is 30 seconds.
       */
      constructor(timeout = 30000) {
          /**
           * Multiple commands to retrieve a directory listing are possible. This instance
           * will try all of them in the order presented the first time a directory listing
           * is requested. After that, `availableListCommands` will  hold only the first
           * entry that worked.
           */
          this.availableListCommands = ["MLSD", "LIST -a", "LIST"];
          this.ftp = new FtpContext_1.FTPContext(timeout);
          this.prepareTransfer = this._enterFirstCompatibleMode([transfer_1.enterPassiveModeIPv6, transfer_1.enterPassiveModeIPv4]);
          this.parseList = parseList_1.parseList;
          this._progressTracker = new ProgressTracker_1.ProgressTracker();
      }
      /**
       * Close the client and all open socket connections.
       *
       * Close the client and all open socket connections. The client can’t be used anymore after calling this method,
       * you have to either reconnect with `access` or `connect` or instantiate a new instance to continue any work.
       * A client is also closed automatically if any timeout or connection error occurs.
       */
      close() {
          this.ftp.close();
          this._progressTracker.stop();
      }
      /**
       * Returns true if the client is closed and can't be used anymore.
       */
      get closed() {
          return this.ftp.closed;
      }
      /**
       * Connect (or reconnect) to an FTP server.
       *
       * This is an instance method and thus can be called multiple times during the lifecycle of a `Client`
       * instance. Whenever you do, the client is reset with a new control connection. This also implies that
       * you can reopen a `Client` instance that has been closed due to an error when reconnecting with this
       * method. In fact, reconnecting is the only way to continue using a closed `Client`.
       *
       * @param host  Host the client should connect to. Optional, default is "localhost".
       * @param port  Port the client should connect to. Optional, default is 21.
       */
      connect(host = "localhost", port = 21) {
          this.ftp.reset();
          this.ftp.socket.connect({
              host,
              port,
              family: this.ftp.ipFamily
          }, () => this.ftp.log(`Connected to ${netUtils_1.describeAddress(this.ftp.socket)}`));
          return this.ftp.handle(undefined, (res, task) => {
              if (res instanceof Error) {
                  // The connection has been destroyed by the FTPContext at this point.
                  task.reject(res);
              }
              else if (parseControlResponse_1.positiveCompletion(res.code)) {
                  task.resolve(res);
              }
              // Reject all other codes, including 120 "Service ready in nnn minutes".
              else {
                  // Don't stay connected but don't replace the socket yet by using reset()
                  // so the user can inspect properties of this instance.
                  this.ftp.socket.destroy();
                  task.reject(new FtpContext_1.FTPError(res));
              }
          });
      }
      /**
       * Send an FTP command and handle the first response.
       */
      send(command, ignoreErrorCodesDEPRECATED = false) {
          if (ignoreErrorCodesDEPRECATED) { // Deprecated starting from 3.9.0
              this.ftp.log("Deprecated call using send(command, flag) with boolean flag to ignore errors. Use sendIgnoringError(command).");
              return this.sendIgnoringError(command);
          }
          return this.ftp.request(command);
      }
      /**
       * Send an FTP command and ignore an FTP error response. Any other kind of error or timeout will still reject the Promise.
       *
       * @param command
       */
      sendIgnoringError(command) {
          return this.ftp.handle(command, (res, task) => {
              if (res instanceof FtpContext_1.FTPError) {
                  task.resolve({ code: res.code, message: res.message });
              }
              else if (res instanceof Error) {
                  task.reject(res);
              }
              else {
                  task.resolve(res);
              }
          });
      }
      /**
       * Upgrade the current socket connection to TLS.
       *
       * @param options  TLS options as in `tls.connect(options)`, optional.
       * @param command  Set the authentication command. Optional, default is "AUTH TLS".
       */
      async useTLS(options = {}, command = "AUTH TLS") {
          const ret = await this.send(command);
          this.ftp.socket = await netUtils_1.upgradeSocket(this.ftp.socket, options);
          this.ftp.tlsOptions = options; // Keep the TLS options for later data connections that should use the same options.
          this.ftp.log(`Control socket is using: ${netUtils_1.describeTLS(this.ftp.socket)}`);
          return ret;
      }
      /**
       * Login a user with a password.
       *
       * @param user  Username to use for login. Optional, default is "anonymous".
       * @param password  Password to use for login. Optional, default is "guest".
       */
      login(user = "anonymous", password = "guest") {
          this.ftp.log(`Login security: ${netUtils_1.describeTLS(this.ftp.socket)}`);
          return this.ftp.handle("USER " + user, (res, task) => {
              if (res instanceof Error) {
                  task.reject(res);
              }
              else if (parseControlResponse_1.positiveCompletion(res.code)) { // User logged in proceed OR Command superfluous
                  task.resolve(res);
              }
              else if (res.code === 331) { // User name okay, need password
                  this.ftp.send("PASS " + password);
              }
              else { // Also report error on 332 (Need account)
                  task.reject(new FtpContext_1.FTPError(res));
              }
          });
      }
      /**
       * Set the usual default settings.
       *
       * Settings used:
       * * Binary mode (TYPE I)
       * * File structure (STRU F)
       * * Additional settings for FTPS (PBSZ 0, PROT P)
       */
      async useDefaultSettings() {
          await this.send("TYPE I"); // Binary mode
          await this.sendIgnoringError("STRU F"); // Use file structure
          await this.sendIgnoringError("OPTS UTF8 ON"); // Some servers expect UTF-8 to be enabled explicitly
          await this.sendIgnoringError("OPTS MLST type;size;modify;unique;unix.mode;unix.owner;unix.group;unix.ownername;unix.groupname;"); // Make sure MLSD listings include all we can parse
          if (this.ftp.hasTLS) {
              await this.sendIgnoringError("PBSZ 0"); // Set to 0 for TLS
              await this.sendIgnoringError("PROT P"); // Protect channel (also for data connections)
          }
      }
      /**
       * Convenience method that calls `connect`, `useTLS`, `login` and `useDefaultSettings`.
       *
       * This is an instance method and thus can be called multiple times during the lifecycle of a `Client`
       * instance. Whenever you do, the client is reset with a new control connection. This also implies that
       * you can reopen a `Client` instance that has been closed due to an error when reconnecting with this
       * method. In fact, reconnecting is the only way to continue using a closed `Client`.
       */
      async access(options = {}) {
          const welcome = await this.connect(options.host, options.port);
          if (options.secure === true) {
              await this.useTLS(options.secureOptions);
          }
          await this.login(options.user, options.password);
          await this.useDefaultSettings();
          return welcome;
      }
      /**
       * Get the current working directory.
       */
      async pwd() {
          const res = await this.send("PWD");
          // The directory is part of the return message, for example:
          // 257 "/this/that" is current directory.
          const parsed = res.message.match(/"(.+)"/);
          if (parsed === null || parsed[1] === undefined) {
              throw new Error(`Can't parse response to command 'PWD': ${res.message}`);
          }
          return parsed[1];
      }
      /**
       * Get a description of supported features.
       *
       * This sends the FEAT command and parses the result into a Map where keys correspond to available commands
       * and values hold further information. Be aware that your FTP servers might not support this
       * command in which case this method will not throw an exception but just return an empty Map.
       */
      async features() {
          const res = await this.sendIgnoringError("FEAT");
          const features = new Map();
          // Not supporting any special features will be reported with a single line.
          if (res.code < 400 && parseControlResponse_1.isMultiline(res.message)) {
              // The first and last line wrap the multiline response, ignore them.
              res.message.split("\n").slice(1, -1).forEach(line => {
                  // A typical lines looks like: " REST STREAM" or " MDTM".
                  // Servers might not use an indentation though.
                  const entry = line.trim().split(" ");
                  features.set(entry[0], entry[1] || "");
              });
          }
          return features;
      }
      /**
       * Set the working directory.
       */
      async cd(path) {
          const validPath = await this.protectWhitespace(path);
          return this.send("CWD " + validPath);
      }
      /**
       * Switch to the parent directory of the working directory.
       */
      async cdup() {
          return this.send("CDUP");
      }
      /**
       * Get the last modified time of a file. This is not supported by every FTP server, in which case
       * calling this method will throw an exception.
       */
      async lastMod(path) {
          const validPath = await this.protectWhitespace(path);
          const res = await this.send(`MDTM ${validPath}`);
          const date = res.message.slice(4);
          return parseListMLSD_1.parseMLSxDate(date);
      }
      /**
       * Get the size of a file.
       */
      async size(path) {
          const validPath = await this.protectWhitespace(path);
          const command = `SIZE ${validPath}`;
          const res = await this.send(command);
          // The size is part of the response message, for example: "213 555555". It's
          // possible that there is a commmentary appended like "213 5555, some commentary".
          const size = parseInt(res.message.slice(4), 10);
          if (Number.isNaN(size)) {
              throw new Error(`Can't parse response to command '${command}' as a numerical value: ${res.message}`);
          }
          return size;
      }
      /**
       * Rename a file.
       *
       * Depending on the FTP server this might also be used to move a file from one
       * directory to another by providing full paths.
       */
      async rename(srcPath, destPath) {
          const validSrc = await this.protectWhitespace(srcPath);
          const validDest = await this.protectWhitespace(destPath);
          await this.send("RNFR " + validSrc);
          return this.send("RNTO " + validDest);
      }
      /**
       * Remove a file from the current working directory.
       *
       * You can ignore FTP error return codes which won't throw an exception if e.g.
       * the file doesn't exist.
       */
      async remove(path, ignoreErrorCodes = false) {
          const validPath = await this.protectWhitespace(path);
          return this.send(`DELE ${validPath}`, ignoreErrorCodes);
      }
      /**
       * Report transfer progress for any upload or download to a given handler.
       *
       * This will also reset the overall transfer counter that can be used for multiple transfers. You can
       * also call the function without a handler to stop reporting to an earlier one.
       *
       * @param handler  Handler function to call on transfer progress.
       */
      trackProgress(handler) {
          this._progressTracker.bytesOverall = 0;
          this._progressTracker.reportTo(handler);
      }
      /**
       * Upload data from a readable stream or a local file to a remote file.
       *
       * @param source  Readable stream or path to a local file.
       * @param toRemotePath  Path to a remote file to write to.
       */
      async uploadFrom(source, toRemotePath, options = {}) {
          return this._uploadWithCommand(source, toRemotePath, "STOR", options);
      }
      /**
       * Upload data from a readable stream or a local file by appending it to an existing file. If the file doesn't
       * exist the FTP server should create it.
       *
       * @param source  Readable stream or path to a local file.
       * @param toRemotePath  Path to a remote file to write to.
       */
      async appendFrom(source, toRemotePath, options = {}) {
          return this._uploadWithCommand(source, toRemotePath, "APPE", options);
      }
      /**
       * @protected
       */
      async _uploadWithCommand(source, remotePath, command, options) {
          if (typeof source === "string") {
              return this._uploadLocalFile(source, remotePath, command, options);
          }
          return this._uploadFromStream(source, remotePath, command);
      }
      /**
       * @protected
       */
      async _uploadLocalFile(localPath, remotePath, command, options) {
          const fd = await fsOpen(localPath, "r");
          const source = fs_1.createReadStream("", {
              fd,
              start: options.localStart,
              end: options.localEndInclusive,
              autoClose: false
          });
          try {
              return await this._uploadFromStream(source, remotePath, command);
          }
          finally {
              await ignoreError(() => fsClose(fd));
          }
      }
      /**
       * @protected
       */
      async _uploadFromStream(source, remotePath, command) {
          const onError = (err) => this.ftp.closeWithError(err);
          source.once("error", onError);
          try {
              const validPath = await this.protectWhitespace(remotePath);
              await this.prepareTransfer(this.ftp);
              // Keep the keyword `await` or the `finally` clause below runs too early
              // and removes the event listener for the source stream too early.
              return await transfer_1.uploadFrom(source, {
                  ftp: this.ftp,
                  tracker: this._progressTracker,
                  command,
                  remotePath: validPath,
                  type: "upload"
              });
          }
          finally {
              source.removeListener("error", onError);
          }
      }
      /**
       * Download a remote file and pipe its data to a writable stream or to a local file.
       *
       * You can optionally define at which position of the remote file you'd like to start
       * downloading. If the destination you provide is a file, the offset will be applied
       * to it as well. For example: To resume a failed download, you'd request the size of
       * the local, partially downloaded file and use that as the offset. Assuming the size
       * is 23, you'd download the rest using `downloadTo("local.txt", "remote.txt", 23)`.
       *
       * @param destination  Stream or path for a local file to write to.
       * @param fromRemotePath  Path of the remote file to read from.
       * @param startAt  Position within the remote file to start downloading at. If the destination is a file, this offset is also applied to it.
       */
      async downloadTo(destination, fromRemotePath, startAt = 0) {
          if (typeof destination === "string") {
              return this._downloadToFile(destination, fromRemotePath, startAt);
          }
          return this._downloadToStream(destination, fromRemotePath, startAt);
      }
      /**
       * @protected
       */
      async _downloadToFile(localPath, remotePath, startAt) {
          const appendingToLocalFile = startAt > 0;
          const fileSystemFlags = appendingToLocalFile ? "r+" : "w";
          const fd = await fsOpen(localPath, fileSystemFlags);
          const destination = fs_1.createWriteStream("", {
              fd,
              start: startAt,
              autoClose: false
          });
          try {
              return await this._downloadToStream(destination, remotePath, startAt);
          }
          catch (err) {
              const localFileStats = await ignoreError(() => fsStat(localPath));
              const hasDownloadedData = localFileStats && localFileStats.size > 0;
              const shouldRemoveLocalFile = !appendingToLocalFile && !hasDownloadedData;
              if (shouldRemoveLocalFile) {
                  await ignoreError(() => fsUnlink(localPath));
              }
              throw err;
          }
          finally {
              await ignoreError(() => fsClose(fd));
          }
      }
      /**
       * @protected
       */
      async _downloadToStream(destination, remotePath, startAt) {
          const onError = (err) => this.ftp.closeWithError(err);
          destination.once("error", onError);
          try {
              const validPath = await this.protectWhitespace(remotePath);
              await this.prepareTransfer(this.ftp);
              // Keep the keyword `await` or the `finally` clause below runs too early
              // and removes the event listener for the source stream too early.
              return await transfer_1.downloadTo(destination, {
                  ftp: this.ftp,
                  tracker: this._progressTracker,
                  command: startAt > 0 ? `REST ${startAt}` : `RETR ${validPath}`,
                  remotePath: validPath,
                  type: "download"
              });
          }
          finally {
              destination.removeListener("error", onError);
              destination.end();
          }
      }
      /**
       * List files and directories in the current working directory, or from `path` if specified.
       *
       * @param [path]  Path to remote file or directory.
       */
      async list(path = "") {
          const validPath = await this.protectWhitespace(path);
          let lastError;
          for (const candidate of this.availableListCommands) {
              const command = `${candidate} ${validPath}`.trim();
              await this.prepareTransfer(this.ftp);
              try {
                  const parsedList = await this._requestListWithCommand(command);
                  // Use successful candidate for all subsequent requests.
                  this.availableListCommands = [candidate];
                  return parsedList;
              }
              catch (err) {
                  const shouldTryNext = err instanceof FtpContext_1.FTPError;
                  if (!shouldTryNext) {
                      throw err;
                  }
                  lastError = err;
              }
          }
          throw lastError;
      }
      /**
       * @protected
       */
      async _requestListWithCommand(command) {
          const buffer = new StringWriter_1.StringWriter();
          await transfer_1.downloadTo(buffer, {
              ftp: this.ftp,
              tracker: this._progressTracker,
              command,
              remotePath: "",
              type: "list"
          });
          const text = buffer.getText(this.ftp.encoding);
          this.ftp.log(text);
          return this.parseList(text);
      }
      /**
       * Remove a directory and all of its content.
       *
       * @param remoteDirPath  The path of the remote directory to delete.
       * @example client.removeDir("foo") // Remove directory 'foo' using a relative path.
       * @example client.removeDir("foo/bar") // Remove directory 'bar' using a relative path.
       * @example client.removeDir("/foo/bar") // Remove directory 'bar' using an absolute path.
       * @example client.removeDir("/") // Remove everything.
       */
      async removeDir(remoteDirPath) {
          return this._exitAtCurrentDirectory(async () => {
              await this.cd(remoteDirPath);
              await this.clearWorkingDir();
              if (remoteDirPath !== "/") {
                  await this.cdup();
                  await this.removeEmptyDir(remoteDirPath);
              }
          });
      }
      /**
       * Remove all files and directories in the working directory without removing
       * the working directory itself.
       */
      async clearWorkingDir() {
          for (const file of await this.list()) {
              if (file.isDirectory) {
                  await this.cd(file.name);
                  await this.clearWorkingDir();
                  await this.cdup();
                  await this.removeEmptyDir(file.name);
              }
              else {
                  await this.remove(file.name);
              }
          }
      }
      /**
       * Upload the contents of a local directory to the remote working directory.
       *
       * This will overwrite existing files with the same names and reuse existing directories.
       * Unrelated files and directories will remain untouched. You can optionally provide a `remoteDirPath`
       * to put the contents inside a directory which will be created if necessary including all
       * intermediate directories. If you did provide a remoteDirPath the working directory will stay
       * the same as before calling this method.
       *
       * @param localDirPath  Local path, e.g. "foo/bar" or "../test"
       * @param [remoteDirPath]  Remote path of a directory to upload to. Working directory if undefined.
       */
      async uploadFromDir(localDirPath, remoteDirPath) {
          return this._exitAtCurrentDirectory(async () => {
              if (remoteDirPath) {
                  await this.ensureDir(remoteDirPath);
              }
              return await this._uploadToWorkingDir(localDirPath);
          });
      }
      /**
       * @protected
       */
      async _uploadToWorkingDir(localDirPath) {
          const files = await fsReadDir(localDirPath);
          for (const file of files) {
              const fullPath = path_1.join(localDirPath, file);
              const stats = await fsStat(fullPath);
              if (stats.isFile()) {
                  await this.uploadFrom(fullPath, file);
              }
              else if (stats.isDirectory()) {
                  await this._openDir(file);
                  await this._uploadToWorkingDir(fullPath);
                  await this.cdup();
              }
          }
      }
      /**
       * Download all files and directories of the working directory to a local directory.
       *
       * @param localDirPath  The local directory to download to.
       * @param remoteDirPath  Remote directory to download. Current working directory if not specified.
       */
      async downloadToDir(localDirPath, remoteDirPath) {
          return this._exitAtCurrentDirectory(async () => {
              if (remoteDirPath) {
                  await this.cd(remoteDirPath);
              }
              return await this._downloadFromWorkingDir(localDirPath);
          });
      }
      /**
       * @protected
       */
      async _downloadFromWorkingDir(localDirPath) {
          await ensureLocalDirectory(localDirPath);
          for (const file of await this.list()) {
              const localPath = path_1.join(localDirPath, file.name);
              if (file.isDirectory) {
                  await this.cd(file.name);
                  await this._downloadFromWorkingDir(localPath);
                  await this.cdup();
              }
              else if (file.isFile) {
                  await this.downloadTo(localPath, file.name);
              }
          }
      }
      /**
       * Make sure a given remote path exists, creating all directories as necessary.
       * This function also changes the current working directory to the given path.
       */
      async ensureDir(remoteDirPath) {
          // If the remoteDirPath was absolute go to root directory.
          if (remoteDirPath.startsWith("/")) {
              await this.cd("/");
          }
          const names = remoteDirPath.split("/").filter(name => name !== "");
          for (const name of names) {
              await this._openDir(name);
          }
      }
      /**
       * Try to create a directory and enter it. This will not raise an exception if the directory
       * couldn't be created if for example it already exists.
       * @protected
       */
      async _openDir(dirName) {
          await this.sendIgnoringError("MKD " + dirName);
          await this.cd(dirName);
      }
      /**
       * Remove an empty directory, will fail if not empty.
       */
      async removeEmptyDir(path) {
          const validPath = await this.protectWhitespace(path);
          return this.send(`RMD ${validPath}`);
      }
      /**
       * FTP servers can't handle filenames that have leading whitespace. This method transforms
       * a given path to fix that issue for most cases.
       */
      async protectWhitespace(path) {
          if (!path.startsWith(" ")) {
              return path;
          }
          // Handle leading whitespace by prepending the absolute path:
          // " test.txt" while being in the root directory becomes "/ test.txt".
          const pwd = await this.pwd();
          const absolutePathPrefix = pwd.endsWith("/") ? pwd : pwd + "/";
          return absolutePathPrefix + path;
      }
      async _exitAtCurrentDirectory(func) {
          const userDir = await this.pwd();
          try {
              return await func();
          }
          finally {
              if (!this.closed) {
                  await ignoreError(() => this.cd(userDir));
              }
          }
      }
      /**
       * Try all available transfer strategies and pick the first one that works. Update `client` to
       * use the working strategy for all successive transfer requests.
       *
       * @param strategies
       * @returns a function that will try the provided strategies.
       */
      _enterFirstCompatibleMode(strategies) {
          return async (ftp) => {
              ftp.log("Trying to find optimal transfer strategy...");
              for (const strategy of strategies) {
                  try {
                      const res = await strategy(ftp);
                      ftp.log("Optimal transfer strategy found.");
                      this.prepareTransfer = strategy; // eslint-disable-line require-atomic-updates
                      return res;
                  }
                  catch (err) {
                      // Receiving an FTPError means that the last transfer strategy failed and we should
                      // try the next one. Any other exception should stop the evaluation of strategies because
                      // something else went wrong.
                      if (!(err instanceof FtpContext_1.FTPError)) {
                          throw err;
                      }
                  }
              }
              throw new Error("None of the available transfer strategies work.");
          };
      }
      /**
       * DEPRECATED, use `uploadFrom`.
       * @deprecated
       */
      async upload(source, toRemotePath, options = {}) {
          this.ftp.log("Warning: upload() has been deprecated, use uploadFrom().");
          return this.uploadFrom(source, toRemotePath, options);
      }
      /**
       * DEPRECATED, use `appendFrom`.
       * @deprecated
       */
      async append(source, toRemotePath, options = {}) {
          this.ftp.log("Warning: append() has been deprecated, use appendFrom().");
          return this.appendFrom(source, toRemotePath, options);
      }
      /**
       * DEPRECATED, use `downloadTo`.
       * @deprecated
       */
      async download(destination, fromRemotePath, startAt = 0) {
          this.ftp.log("Warning: download() has been deprecated, use downloadTo().");
          return this.downloadTo(destination, fromRemotePath, startAt);
      }
      /**
       * DEPRECATED, use `uploadFromDir`.
       * @deprecated
       */
      async uploadDir(localDirPath, remoteDirPath) {
          this.ftp.log("Warning: uploadDir() has been deprecated, use uploadFromDir().");
          return this.uploadFromDir(localDirPath, remoteDirPath);
      }
      /**
       * DEPRECATED, use `downloadToDir`.
       * @deprecated
       */
      async downloadDir(localDirPath) {
          this.ftp.log("Warning: downloadDir() has been deprecated, use downloadToDir().");
          return this.downloadToDir(localDirPath);
      }
  }
  exports.Client = Client;
  async function ensureLocalDirectory(path) {
      try {
          await fsStat(path);
      }
      catch (err) {
          await fsMkDir(path, { recursive: true });
      }
  }
  async function ignoreError(func) {
      try {
          return await func();
      }
      catch (err) {
          // Ignore
          return undefined;
      }
  }
  
  
  /***/ }),
  
  /***/ 306:
  /***/ (function(module, __unusedexports, __webpack_require__) {
  
  var concatMap = __webpack_require__(896);
  var balanced = __webpack_require__(621);
  
  module.exports = expandTop;
  
  var escSlash = '\0SLASH'+Math.random()+'\0';
  var escOpen = '\0OPEN'+Math.random()+'\0';
  var escClose = '\0CLOSE'+Math.random()+'\0';
  var escComma = '\0COMMA'+Math.random()+'\0';
  var escPeriod = '\0PERIOD'+Math.random()+'\0';
  
  function numeric(str) {
    return parseInt(str, 10) == str
      ? parseInt(str, 10)
      : str.charCodeAt(0);
  }
  
  function escapeBraces(str) {
    return str.split('\\\\').join(escSlash)
              .split('\\{').join(escOpen)
              .split('\\}').join(escClose)
              .split('\\,').join(escComma)
              .split('\\.').join(escPeriod);
  }
  
  function unescapeBraces(str) {
    return str.split(escSlash).join('\\')
              .split(escOpen).join('{')
              .split(escClose).join('}')
              .split(escComma).join(',')
              .split(escPeriod).join('.');
  }
  
  
  // Basically just str.split(","), but handling cases
  // where we have nested braced sections, which should be
  // treated as individual members, like {a,{b,c},d}
  function parseCommaParts(str) {
    if (!str)
      return [''];
  
    var parts = [];
    var m = balanced('{', '}', str);
  
    if (!m)
      return str.split(',');
  
    var pre = m.pre;
    var body = m.body;
    var post = m.post;
    var p = pre.split(',');
  
    p[p.length-1] += '{' + body + '}';
    var postParts = parseCommaParts(post);
    if (post.length) {
      p[p.length-1] += postParts.shift();
      p.push.apply(p, postParts);
    }
  
    parts.push.apply(parts, p);
  
    return parts;
  }
  
  function expandTop(str) {
    if (!str)
      return [];
  
    // I don't know why Bash 4.3 does this, but it does.
    // Anything starting with {} will have the first two bytes preserved
    // but *only* at the top level, so {},a}b will not expand to anything,
    // but a{},b}c will be expanded to [a}c,abc].
    // One could argue that this is a bug in Bash, but since the goal of
    // this module is to match Bash's rules, we escape a leading {}
    if (str.substr(0, 2) === '{}') {
      str = '\\{\\}' + str.substr(2);
    }
  
    return expand(escapeBraces(str), true).map(unescapeBraces);
  }
  
  function identity(e) {
    return e;
  }
  
  function embrace(str) {
    return '{' + str + '}';
  }
  function isPadded(el) {
    return /^-?0\d/.test(el);
  }
  
  function lte(i, y) {
    return i <= y;
  }
  function gte(i, y) {
    return i >= y;
  }
  
  function expand(str, isTop) {
    var expansions = [];
  
    var m = balanced('{', '}', str);
    if (!m || /\$$/.test(m.pre)) return [str];
  
    var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
    var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
    var isSequence = isNumericSequence || isAlphaSequence;
    var isOptions = m.body.indexOf(',') >= 0;
    if (!isSequence && !isOptions) {
      // {a},b}
      if (m.post.match(/,.*\}/)) {
        str = m.pre + '{' + m.body + escClose + m.post;
        return expand(str);
      }
      return [str];
    }
  
    var n;
    if (isSequence) {
      n = m.body.split(/\.\./);
    } else {
      n = parseCommaParts(m.body);
      if (n.length === 1) {
        // x{{a,b}}y ==> x{a}y x{b}y
        n = expand(n[0], false).map(embrace);
        if (n.length === 1) {
          var post = m.post.length
            ? expand(m.post, false)
            : [''];
          return post.map(function(p) {
            return m.pre + n[0] + p;
          });
        }
      }
    }
  
    // at this point, n is the parts, and we know it's not a comma set
    // with a single entry.
  
    // no need to expand pre, since it is guaranteed to be free of brace-sets
    var pre = m.pre;
    var post = m.post.length
      ? expand(m.post, false)
      : [''];
  
    var N;
  
    if (isSequence) {
      var x = numeric(n[0]);
      var y = numeric(n[1]);
      var width = Math.max(n[0].length, n[1].length)
      var incr = n.length == 3
        ? Math.abs(numeric(n[2]))
        : 1;
      var test = lte;
      var reverse = y < x;
      if (reverse) {
        incr *= -1;
        test = gte;
      }
      var pad = n.some(isPadded);
  
      N = [];
  
      for (var i = x; test(i, y); i += incr) {
        var c;
        if (isAlphaSequence) {
          c = String.fromCharCode(i);
          if (c === '\\')
            c = '';
        } else {
          c = String(i);
          if (pad) {
            var need = width - c.length;
            if (need > 0) {
              var z = new Array(need + 1).join('0');
              if (i < 0)
                c = '-' + z + c.slice(1);
              else
                c = z + c;
            }
          }
        }
        N.push(c);
      }
    } else {
      N = concatMap(n, function(el) { return expand(el, false) });
    }
  
    for (var j = 0; j < N.length; j++) {
      for (var k = 0; k < post.length; k++) {
        var expansion = pre + N[j] + post[k];
        if (!isTop || isSequence || expansion)
          expansions.push(expansion);
      }
    }
  
    return expansions;
  }
  
  
  
  /***/ }),
  
  /***/ 315:
  /***/ (function(module) {
  
  if (typeof Object.create === 'function') {
    // implementation from standard node.js 'util' module
    module.exports = function inherits(ctor, superCtor) {
      if (superCtor) {
        ctor.super_ = superCtor
        ctor.prototype = Object.create(superCtor.prototype, {
          constructor: {
            value: ctor,
            enumerable: false,
            writable: true,
            configurable: true
          }
        })
      }
    };
  } else {
    // old school shim for old browsers
    module.exports = function inherits(ctor, superCtor) {
      if (superCtor) {
        ctor.super_ = superCtor
        var TempCtor = function () {}
        TempCtor.prototype = superCtor.prototype
        ctor.prototype = new TempCtor()
        ctor.prototype.constructor = ctor
      }
    }
  }
  
  
  /***/ }),
  
  /***/ 357:
  /***/ (function(module) {
  
  module.exports = require("assert");
  
  /***/ }),
  
  /***/ 368:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const netUtils_1 = __webpack_require__(864);
  const tls_1 = __webpack_require__(16);
  const parseControlResponse_1 = __webpack_require__(262);
  /**
   * Prepare a data socket using passive mode over IPv6.
   */
  async function enterPassiveModeIPv6(ftp) {
      const res = await ftp.request("EPSV");
      const port = parseEpsvResponse(res.message);
      if (!port) {
          throw new Error("Can't parse EPSV response: " + res.message);
      }
      const controlHost = ftp.socket.remoteAddress;
      if (controlHost === undefined) {
          throw new Error("Control socket is disconnected, can't get remote address.");
      }
      await connectForPassiveTransfer(controlHost, port, ftp);
      return res;
  }
  exports.enterPassiveModeIPv6 = enterPassiveModeIPv6;
  /**
   * Parse an EPSV response. Returns only the port as in EPSV the host of the control connection is used.
   */
  function parseEpsvResponse(message) {
      // Get port from EPSV response, e.g. "229 Entering Extended Passive Mode (|||6446|)"
      // Some FTP Servers such as the one on IBM i (OS/400) use ! instead of | in their EPSV response.
      const groups = message.match(/[|!]{3}(.+)[|!]/);
      if (groups === null || groups[1] === undefined) {
          throw new Error(`Can't parse response to 'EPSV': ${message}`);
      }
      const port = parseInt(groups[1], 10);
      if (Number.isNaN(port)) {
          throw new Error(`Can't parse response to 'EPSV', port is not a number: ${message}`);
      }
      return port;
  }
  exports.parseEpsvResponse = parseEpsvResponse;
  /**
   * Prepare a data socket using passive mode over IPv4.
   */
  async function enterPassiveModeIPv4(ftp) {
      const res = await ftp.request("PASV");
      const target = parsePasvResponse(res.message);
      if (!target) {
          throw new Error("Can't parse PASV response: " + res.message);
      }
      // If the host in the PASV response has a local address while the control connection hasn't,
      // we assume a NAT issue and use the IP of the control connection as the target for the data connection.
      // We can't always perform this replacement because it's possible (although unlikely) that the FTP server
      // indeed uses a different host for data connections.
      const controlHost = ftp.socket.remoteAddress;
      if (netUtils_1.ipIsPrivateV4Address(target.host) && controlHost && !netUtils_1.ipIsPrivateV4Address(controlHost)) {
          target.host = controlHost;
      }
      await connectForPassiveTransfer(target.host, target.port, ftp);
      return res;
  }
  exports.enterPassiveModeIPv4 = enterPassiveModeIPv4;
  /**
   * Parse a PASV response.
   */
  function parsePasvResponse(message) {
      // Get host and port from PASV response, e.g. "227 Entering Passive Mode (192,168,1,100,10,229)"
      const groups = message.match(/([-\d]+,[-\d]+,[-\d]+,[-\d]+),([-\d]+),([-\d]+)/);
      if (groups === null || groups.length !== 4) {
          throw new Error(`Can't parse response to 'PASV': ${message}`);
      }
      return {
          host: groups[1].replace(/,/g, "."),
          port: (parseInt(groups[2], 10) & 255) * 256 + (parseInt(groups[3], 10) & 255)
      };
  }
  exports.parsePasvResponse = parsePasvResponse;
  function connectForPassiveTransfer(host, port, ftp) {
      return new Promise((resolve, reject) => {
          const handleConnErr = function (err) {
              err.message = "Can't open data connection in passive mode: " + err.message;
              reject(err);
          };
          let socket = ftp._newSocket();
          socket.on("error", handleConnErr);
          socket.connect({ port, host, family: ftp.ipFamily }, () => {
              if (ftp.socket instanceof tls_1.TLSSocket) {
                  socket = tls_1.connect(Object.assign({}, ftp.tlsOptions, {
                      socket,
                      // Reuse the TLS session negotiated earlier when the control connection
                      // was upgraded. Servers expect this because it provides additional
                      // security: If a completely new session would be negotiated, a hacker
                      // could guess the port and connect to the new data connection before we do
                      // by just starting his/her own TLS session.
                      session: ftp.socket.getSession()
                  }));
                  // It's the responsibility of the transfer task to wait until the
                  // TLS socket issued the event 'secureConnect'. We can't do this
                  // here because some servers will start upgrading after the
                  // specific transfer request has been made. List and download don't
                  // have to wait for this event because the server sends whenever it
                  // is ready. But for upload this has to be taken into account,
                  // see the details in the upload() function below.
              }
              // Let the FTPContext listen to errors from now on, remove local handler.
              socket.removeListener("error", handleConnErr);
              ftp.dataSocket = socket;
              resolve();
          });
      });
  }
  exports.connectForPassiveTransfer = connectForPassiveTransfer;
  /**
   * Helps resolving/rejecting transfers.
   *
   * This is used internally for all FTP transfers. For example when downloading, the server might confirm
   * with "226 Transfer complete" when in fact the download on the data connection has not finished
   * yet. With all transfers we make sure that a) the result arrived and b) has been confirmed by
   * e.g. the control connection. We just don't know in which order this will happen.
   */
  class TransferResolver {
      /**
       * Instantiate a TransferResolver
       */
      constructor(ftp, progress) {
          this.ftp = ftp;
          this.progress = progress;
          this.response = undefined;
          this.dataTransferDone = false;
      }
      /**
       * Mark the beginning of a transfer.
       *
       * @param name - Name of the transfer, usually the filename.
       * @param type - Type of transfer, usually "upload" or "download".
       */
      onDataStart(name, type) {
          // Let the data socket be in charge of tracking timeouts during transfer.
          // The control socket sits idle during this time anyway and might provoke
          // a timeout unnecessarily. The control connection will take care
          // of timeouts again once data transfer is complete or failed.
          if (this.ftp.dataSocket === undefined) {
              throw new Error("Data transfer should start but there is no data connection.");
          }
          this.ftp.socket.setTimeout(0);
          this.ftp.dataSocket.setTimeout(this.ftp.timeout);
          this.progress.start(this.ftp.dataSocket, name, type);
      }
      /**
       * The data connection has finished the transfer.
       */
      onDataDone(task) {
          this.progress.updateAndStop();
          // Hand-over timeout tracking back to the control connection. It's possible that
          // we don't receive the response over the control connection that the transfer is
          // done. In this case, we want to correctly associate the resulting timeout with
          // the control connection.
          this.ftp.socket.setTimeout(this.ftp.timeout);
          if (this.ftp.dataSocket) {
              this.ftp.dataSocket.setTimeout(0);
          }
          this.dataTransferDone = true;
          this.tryResolve(task);
      }
      /**
       * The control connection reports the transfer as finished.
       */
      onControlDone(task, response) {
          this.response = response;
          this.tryResolve(task);
      }
      /**
       * An error has been reported and the task should be rejected.
       */
      onError(task, err) {
          this.progress.updateAndStop();
          this.ftp.socket.setTimeout(this.ftp.timeout);
          this.ftp.dataSocket = undefined;
          task.reject(err);
      }
      /**
       * Control connection sent an unexpected request requiring a response from our part. We
       * can't provide that (because unknown) and have to close the contrext with an error because
       * the FTP server is now caught up in a state we can't resolve.
       */
      onUnexpectedRequest(response) {
          const err = new Error(`Unexpected FTP response is requesting an answer: ${response.message}`);
          this.ftp.closeWithError(err);
      }
      tryResolve(task) {
          // To resolve, we need both control and data connection to report that the transfer is done.
          const canResolve = this.dataTransferDone && this.response !== undefined;
          if (canResolve) {
              this.ftp.dataSocket = undefined;
              task.resolve(this.response);
          }
      }
  }
  function uploadFrom(source, config) {
      const resolver = new TransferResolver(config.ftp, config.tracker);
      const fullCommand = `${config.command} ${config.remotePath}`;
      return config.ftp.handle(fullCommand, (res, task) => {
          if (res instanceof Error) {
              resolver.onError(task, res);
          }
          else if (res.code === 150 || res.code === 125) { // Ready to upload
              const dataSocket = config.ftp.dataSocket;
              if (!dataSocket) {
                  resolver.onError(task, new Error("Upload should begin but no data connection is available."));
                  return;
              }
              // If we are using TLS, we have to wait until the dataSocket issued
              // 'secureConnect'. If this hasn't happened yet, getCipher() returns undefined.
              const canUpload = "getCipher" in dataSocket ? dataSocket.getCipher() !== undefined : true;
              onConditionOrEvent(canUpload, dataSocket, "secureConnect", () => {
                  config.ftp.log(`Uploading to ${netUtils_1.describeAddress(dataSocket)} (${netUtils_1.describeTLS(dataSocket)})`);
                  resolver.onDataStart(config.remotePath, config.type);
                  source.pipe(dataSocket).once("finish", () => {
                      dataSocket.destroy(); // Explicitly close/destroy the socket to signal the end.
                      resolver.onDataDone(task);
                  });
              });
          }
          else if (parseControlResponse_1.positiveCompletion(res.code)) { // Transfer complete
              resolver.onControlDone(task, res);
          }
          else if (parseControlResponse_1.positiveIntermediate(res.code)) {
              resolver.onUnexpectedRequest(res);
          }
          // Ignore all other positive preliminary response codes (< 200)
      });
  }
  exports.uploadFrom = uploadFrom;
  function downloadTo(destination, config) {
      if (!config.ftp.dataSocket) {
          throw new Error("Download will be initiated but no data connection is available.");
      }
      // It's possible that data transmission begins before the control socket
      // receives the announcement. Start listening for data immediately.
      config.ftp.dataSocket.pipe(destination);
      const resolver = new TransferResolver(config.ftp, config.tracker);
      return config.ftp.handle(config.command, (res, task) => {
          if (res instanceof Error) {
              resolver.onError(task, res);
          }
          else if (res.code === 150 || res.code === 125) { // Ready to download
              const dataSocket = config.ftp.dataSocket;
              if (!dataSocket) {
                  resolver.onError(task, new Error("Download should begin but no data connection is available."));
                  return;
              }
              config.ftp.log(`Downloading from ${netUtils_1.describeAddress(dataSocket)} (${netUtils_1.describeTLS(dataSocket)})`);
              resolver.onDataStart(config.remotePath, config.type);
              onConditionOrEvent(destination.destroyed || destination.writableFinished, destination, "finish", () => resolver.onDataDone(task));
          }
          else if (res.code === 350) { // Restarting at startAt.
              config.ftp.send("RETR " + config.remotePath);
          }
          else if (parseControlResponse_1.positiveCompletion(res.code)) { // Transfer complete
              resolver.onControlDone(task, res);
          }
          else if (parseControlResponse_1.positiveIntermediate(res.code)) {
              resolver.onUnexpectedRequest(res);
          }
          // Ignore all other positive preliminary response codes (< 200)
      });
  }
  exports.downloadTo = downloadTo;
  /**
   * Calls a function immediately if a condition is met or subscribes to an event and calls
   * it once the event is emitted.
   *
   * @param condition  The condition to test.
   * @param emitter  The emitter to use if the condition is not met.
   * @param eventName  The event to subscribe to if the condition is not met.
   * @param action  The function to call.
   */
  function onConditionOrEvent(condition, emitter, eventName, action) {
      if (condition === true) {
          action();
      }
      else {
          emitter.once(eventName, () => action());
      }
  }
  
  
  /***/ }),
  
  /***/ 402:
  /***/ (function(module, __unusedexports, __webpack_require__) {
  
  // Approach:
  //
  // 1. Get the minimatch set
  // 2. For each pattern in the set, PROCESS(pattern, false)
  // 3. Store matches per-set, then uniq them
  //
  // PROCESS(pattern, inGlobStar)
  // Get the first [n] items from pattern that are all strings
  // Join these together.  This is PREFIX.
  //   If there is no more remaining, then stat(PREFIX) and
  //   add to matches if it succeeds.  END.
  //
  // If inGlobStar and PREFIX is symlink and points to dir
  //   set ENTRIES = []
  // else readdir(PREFIX) as ENTRIES
  //   If fail, END
  //
  // with ENTRIES
  //   If pattern[n] is GLOBSTAR
  //     // handle the case where the globstar match is empty
  //     // by pruning it out, and testing the resulting pattern
  //     PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
  //     // handle other cases.
  //     for ENTRY in ENTRIES (not dotfiles)
  //       // attach globstar + tail onto the entry
  //       // Mark that this entry is a globstar match
  //       PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
  //
  //   else // not globstar
  //     for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
  //       Test ENTRY against pattern[n]
  //       If fails, continue
  //       If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
  //
  // Caveat:
  //   Cache all stats and readdirs results to minimize syscall.  Since all
  //   we ever care about is existence and directory-ness, we can just keep
  //   `true` for files, and [children,...] for directories, or `false` for
  //   things that don't exist.
  
  module.exports = glob
  
  var fs = __webpack_require__(747)
  var rp = __webpack_require__(302)
  var minimatch = __webpack_require__(93)
  var Minimatch = minimatch.Minimatch
  var inherits = __webpack_require__(689)
  var EE = __webpack_require__(614).EventEmitter
  var path = __webpack_require__(622)
  var assert = __webpack_require__(357)
  var isAbsolute = __webpack_require__(681)
  var globSync = __webpack_require__(245)
  var common = __webpack_require__(856)
  var alphasort = common.alphasort
  var alphasorti = common.alphasorti
  var setopts = common.setopts
  var ownProp = common.ownProp
  var inflight = __webpack_require__(674)
  var util = __webpack_require__(669)
  var childrenIgnored = common.childrenIgnored
  var isIgnored = common.isIgnored
  
  var once = __webpack_require__(49)
  
  function glob (pattern, options, cb) {
    if (typeof options === 'function') cb = options, options = {}
    if (!options) options = {}
  
    if (options.sync) {
      if (cb)
        throw new TypeError('callback provided to sync glob')
      return globSync(pattern, options)
    }
  
    return new Glob(pattern, options, cb)
  }
  
  glob.sync = globSync
  var GlobSync = glob.GlobSync = globSync.GlobSync
  
  // old api surface
  glob.glob = glob
  
  function extend (origin, add) {
    if (add === null || typeof add !== 'object') {
      return origin
    }
  
    var keys = Object.keys(add)
    var i = keys.length
    while (i--) {
      origin[keys[i]] = add[keys[i]]
    }
    return origin
  }
  
  glob.hasMagic = function (pattern, options_) {
    var options = extend({}, options_)
    options.noprocess = true
  
    var g = new Glob(pattern, options)
    var set = g.minimatch.set
  
    if (!pattern)
      return false
  
    if (set.length > 1)
      return true
  
    for (var j = 0; j < set[0].length; j++) {
      if (typeof set[0][j] !== 'string')
        return true
    }
  
    return false
  }
  
  glob.Glob = Glob
  inherits(Glob, EE)
  function Glob (pattern, options, cb) {
    if (typeof options === 'function') {
      cb = options
      options = null
    }
  
    if (options && options.sync) {
      if (cb)
        throw new TypeError('callback provided to sync glob')
      return new GlobSync(pattern, options)
    }
  
    if (!(this instanceof Glob))
      return new Glob(pattern, options, cb)
  
    setopts(this, pattern, options)
    this._didRealPath = false
  
    // process each pattern in the minimatch set
    var n = this.minimatch.set.length
  
    // The matches are stored as {<filename>: true,...} so that
    // duplicates are automagically pruned.
    // Later, we do an Object.keys() on these.
    // Keep them as a list so we can fill in when nonull is set.
    this.matches = new Array(n)
  
    if (typeof cb === 'function') {
      cb = once(cb)
      this.on('error', cb)
      this.on('end', function (matches) {
        cb(null, matches)
      })
    }
  
    var self = this
    this._processing = 0
  
    this._emitQueue = []
    this._processQueue = []
    this.paused = false
  
    if (this.noprocess)
      return this
  
    if (n === 0)
      return done()
  
    var sync = true
    for (var i = 0; i < n; i ++) {
      this._process(this.minimatch.set[i], i, false, done)
    }
    sync = false
  
    function done () {
      --self._processing
      if (self._processing <= 0) {
        if (sync) {
          process.nextTick(function () {
            self._finish()
          })
        } else {
          self._finish()
        }
      }
    }
  }
  
  Glob.prototype._finish = function () {
    assert(this instanceof Glob)
    if (this.aborted)
      return
  
    if (this.realpath && !this._didRealpath)
      return this._realpath()
  
    common.finish(this)
    this.emit('end', this.found)
  }
  
  Glob.prototype._realpath = function () {
    if (this._didRealpath)
      return
  
    this._didRealpath = true
  
    var n = this.matches.length
    if (n === 0)
      return this._finish()
  
    var self = this
    for (var i = 0; i < this.matches.length; i++)
      this._realpathSet(i, next)
  
    function next () {
      if (--n === 0)
        self._finish()
    }
  }
  
  Glob.prototype._realpathSet = function (index, cb) {
    var matchset = this.matches[index]
    if (!matchset)
      return cb()
  
    var found = Object.keys(matchset)
    var self = this
    var n = found.length
  
    if (n === 0)
      return cb()
  
    var set = this.matches[index] = Object.create(null)
    found.forEach(function (p, i) {
      // If there's a problem with the stat, then it means that
      // one or more of the links in the realpath couldn't be
      // resolved.  just return the abs value in that case.
      p = self._makeAbs(p)
      rp.realpath(p, self.realpathCache, function (er, real) {
        if (!er)
          set[real] = true
        else if (er.syscall === 'stat')
          set[p] = true
        else
          self.emit('error', er) // srsly wtf right here
  
        if (--n === 0) {
          self.matches[index] = set
          cb()
        }
      })
    })
  }
  
  Glob.prototype._mark = function (p) {
    return common.mark(this, p)
  }
  
  Glob.prototype._makeAbs = function (f) {
    return common.makeAbs(this, f)
  }
  
  Glob.prototype.abort = function () {
    this.aborted = true
    this.emit('abort')
  }
  
  Glob.prototype.pause = function () {
    if (!this.paused) {
      this.paused = true
      this.emit('pause')
    }
  }
  
  Glob.prototype.resume = function () {
    if (this.paused) {
      this.emit('resume')
      this.paused = false
      if (this._emitQueue.length) {
        var eq = this._emitQueue.slice(0)
        this._emitQueue.length = 0
        for (var i = 0; i < eq.length; i ++) {
          var e = eq[i]
          this._emitMatch(e[0], e[1])
        }
      }
      if (this._processQueue.length) {
        var pq = this._processQueue.slice(0)
        this._processQueue.length = 0
        for (var i = 0; i < pq.length; i ++) {
          var p = pq[i]
          this._processing--
          this._process(p[0], p[1], p[2], p[3])
        }
      }
    }
  }
  
  Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
    assert(this instanceof Glob)
    assert(typeof cb === 'function')
  
    if (this.aborted)
      return
  
    this._processing++
    if (this.paused) {
      this._processQueue.push([pattern, index, inGlobStar, cb])
      return
    }
  
    //console.error('PROCESS %d', this._processing, pattern)
  
    // Get the first [n] parts of pattern that are all strings.
    var n = 0
    while (typeof pattern[n] === 'string') {
      n ++
    }
    // now n is the index of the first one that is *not* a string.
  
    // see if there's anything else
    var prefix
    switch (n) {
      // if not, then this is rather simple
      case pattern.length:
        this._processSimple(pattern.join('/'), index, cb)
        return
  
      case 0:
        // pattern *starts* with some non-trivial item.
        // going to readdir(cwd), but not include the prefix in matches.
        prefix = null
        break
  
      default:
        // pattern has some string bits in the front.
        // whatever it starts with, whether that's 'absolute' like /foo/bar,
        // or 'relative' like '../baz'
        prefix = pattern.slice(0, n).join('/')
        break
    }
  
    var remain = pattern.slice(n)
  
    // get the list of entries.
    var read
    if (prefix === null)
      read = '.'
    else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
      if (!prefix || !isAbsolute(prefix))
        prefix = '/' + prefix
      read = prefix
    } else
      read = prefix
  
    var abs = this._makeAbs(read)
  
    //if ignored, skip _processing
    if (childrenIgnored(this, read))
      return cb()
  
    var isGlobStar = remain[0] === minimatch.GLOBSTAR
    if (isGlobStar)
      this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
    else
      this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
  }
  
  Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
    var self = this
    this._readdir(abs, inGlobStar, function (er, entries) {
      return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
    })
  }
  
  Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
  
    // if the abs isn't a dir, then nothing can match!
    if (!entries)
      return cb()
  
    // It will only match dot entries if it starts with a dot, or if
    // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
    var pn = remain[0]
    var negate = !!this.minimatch.negate
    var rawGlob = pn._glob
    var dotOk = this.dot || rawGlob.charAt(0) === '.'
  
    var matchedEntries = []
    for (var i = 0; i < entries.length; i++) {
      var e = entries[i]
      if (e.charAt(0) !== '.' || dotOk) {
        var m
        if (negate && !prefix) {
          m = !e.match(pn)
        } else {
          m = e.match(pn)
        }
        if (m)
          matchedEntries.push(e)
      }
    }
  
    //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
  
    var len = matchedEntries.length
    // If there are no matched entries, then nothing matches.
    if (len === 0)
      return cb()
  
    // if this is the last remaining pattern bit, then no need for
    // an additional stat *unless* the user has specified mark or
    // stat explicitly.  We know they exist, since readdir returned
    // them.
  
    if (remain.length === 1 && !this.mark && !this.stat) {
      if (!this.matches[index])
        this.matches[index] = Object.create(null)
  
      for (var i = 0; i < len; i ++) {
        var e = matchedEntries[i]
        if (prefix) {
          if (prefix !== '/')
            e = prefix + '/' + e
          else
            e = prefix + e
        }
  
        if (e.charAt(0) === '/' && !this.nomount) {
          e = path.join(this.root, e)
        }
        this._emitMatch(index, e)
      }
      // This was the last one, and no stats were needed
      return cb()
    }
  
    // now test all matched entries as stand-ins for that part
    // of the pattern.
    remain.shift()
    for (var i = 0; i < len; i ++) {
      var e = matchedEntries[i]
      var newPattern
      if (prefix) {
        if (prefix !== '/')
          e = prefix + '/' + e
        else
          e = prefix + e
      }
      this._process([e].concat(remain), index, inGlobStar, cb)
    }
    cb()
  }
  
  Glob.prototype._emitMatch = function (index, e) {
    if (this.aborted)
      return
  
    if (isIgnored(this, e))
      return
  
    if (this.paused) {
      this._emitQueue.push([index, e])
      return
    }
  
    var abs = isAbsolute(e) ? e : this._makeAbs(e)
  
    if (this.mark)
      e = this._mark(e)
  
    if (this.absolute)
      e = abs
  
    if (this.matches[index][e])
      return
  
    if (this.nodir) {
      var c = this.cache[abs]
      if (c === 'DIR' || Array.isArray(c))
        return
    }
  
    this.matches[index][e] = true
  
    var st = this.statCache[abs]
    if (st)
      this.emit('stat', e, st)
  
    this.emit('match', e)
  }
  
  Glob.prototype._readdirInGlobStar = function (abs, cb) {
    if (this.aborted)
      return
  
    // follow all symlinked directories forever
    // just proceed as if this is a non-globstar situation
    if (this.follow)
      return this._readdir(abs, false, cb)
  
    var lstatkey = 'lstat\0' + abs
    var self = this
    var lstatcb = inflight(lstatkey, lstatcb_)
  
    if (lstatcb)
      fs.lstat(abs, lstatcb)
  
    function lstatcb_ (er, lstat) {
      if (er && er.code === 'ENOENT')
        return cb()
  
      var isSym = lstat && lstat.isSymbolicLink()
      self.symlinks[abs] = isSym
  
      // If it's not a symlink or a dir, then it's definitely a regular file.
      // don't bother doing a readdir in that case.
      if (!isSym && lstat && !lstat.isDirectory()) {
        self.cache[abs] = 'FILE'
        cb()
      } else
        self._readdir(abs, false, cb)
    }
  }
  
  Glob.prototype._readdir = function (abs, inGlobStar, cb) {
    if (this.aborted)
      return
  
    cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
    if (!cb)
      return
  
    //console.error('RD %j %j', +inGlobStar, abs)
    if (inGlobStar && !ownProp(this.symlinks, abs))
      return this._readdirInGlobStar(abs, cb)
  
    if (ownProp(this.cache, abs)) {
      var c = this.cache[abs]
      if (!c || c === 'FILE')
        return cb()
  
      if (Array.isArray(c))
        return cb(null, c)
    }
  
    var self = this
    fs.readdir(abs, readdirCb(this, abs, cb))
  }
  
  function readdirCb (self, abs, cb) {
    return function (er, entries) {
      if (er)
        self._readdirError(abs, er, cb)
      else
        self._readdirEntries(abs, entries, cb)
    }
  }
  
  Glob.prototype._readdirEntries = function (abs, entries, cb) {
    if (this.aborted)
      return
  
    // if we haven't asked to stat everything, then just
    // assume that everything in there exists, so we can avoid
    // having to stat it a second time.
    if (!this.mark && !this.stat) {
      for (var i = 0; i < entries.length; i ++) {
        var e = entries[i]
        if (abs === '/')
          e = abs + e
        else
          e = abs + '/' + e
        this.cache[e] = true
      }
    }
  
    this.cache[abs] = entries
    return cb(null, entries)
  }
  
  Glob.prototype._readdirError = function (f, er, cb) {
    if (this.aborted)
      return
  
    // handle errors, and cache the information
    switch (er.code) {
      case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
      case 'ENOTDIR': // totally normal. means it *does* exist.
        var abs = this._makeAbs(f)
        this.cache[abs] = 'FILE'
        if (abs === this.cwdAbs) {
          var error = new Error(er.code + ' invalid cwd ' + this.cwd)
          error.path = this.cwd
          error.code = er.code
          this.emit('error', error)
          this.abort()
        }
        break
  
      case 'ENOENT': // not terribly unusual
      case 'ELOOP':
      case 'ENAMETOOLONG':
      case 'UNKNOWN':
        this.cache[this._makeAbs(f)] = false
        break
  
      default: // some unusual error.  Treat as failure.
        this.cache[this._makeAbs(f)] = false
        if (this.strict) {
          this.emit('error', er)
          // If the error is handled, then we abort
          // if not, we threw out of here
          this.abort()
        }
        if (!this.silent)
          console.error('glob error', er)
        break
    }
  
    return cb()
  }
  
  Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
    var self = this
    this._readdir(abs, inGlobStar, function (er, entries) {
      self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
    })
  }
  
  
  Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
    //console.error('pgs2', prefix, remain[0], entries)
  
    // no entries means not a dir, so it can never have matches
    // foo.txt/** doesn't match foo.txt
    if (!entries)
      return cb()
  
    // test without the globstar, and with every child both below
    // and replacing the globstar.
    var remainWithoutGlobStar = remain.slice(1)
    var gspref = prefix ? [ prefix ] : []
    var noGlobStar = gspref.concat(remainWithoutGlobStar)
  
    // the noGlobStar pattern exits the inGlobStar state
    this._process(noGlobStar, index, false, cb)
  
    var isSym = this.symlinks[abs]
    var len = entries.length
  
    // If it's a symlink, and we're in a globstar, then stop
    if (isSym && inGlobStar)
      return cb()
  
    for (var i = 0; i < len; i++) {
      var e = entries[i]
      if (e.charAt(0) === '.' && !this.dot)
        continue
  
      // these two cases enter the inGlobStar state
      var instead = gspref.concat(entries[i], remainWithoutGlobStar)
      this._process(instead, index, true, cb)
  
      var below = gspref.concat(entries[i], remain)
      this._process(below, index, true, cb)
    }
  
    cb()
  }
  
  Glob.prototype._processSimple = function (prefix, index, cb) {
    // XXX review this.  Shouldn't it be doing the mounting etc
    // before doing stat?  kinda weird?
    var self = this
    this._stat(prefix, function (er, exists) {
      self._processSimple2(prefix, index, er, exists, cb)
    })
  }
  Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
  
    //console.error('ps2', prefix, exists)
  
    if (!this.matches[index])
      this.matches[index] = Object.create(null)
  
    // If it doesn't exist, then just mark the lack of results
    if (!exists)
      return cb()
  
    if (prefix && isAbsolute(prefix) && !this.nomount) {
      var trail = /[\/\\]$/.test(prefix)
      if (prefix.charAt(0) === '/') {
        prefix = path.join(this.root, prefix)
      } else {
        prefix = path.resolve(this.root, prefix)
        if (trail)
          prefix += '/'
      }
    }
  
    if (process.platform === 'win32')
      prefix = prefix.replace(/\\/g, '/')
  
    // Mark this as a match
    this._emitMatch(index, prefix)
    cb()
  }
  
  // Returns either 'DIR', 'FILE', or false
  Glob.prototype._stat = function (f, cb) {
    var abs = this._makeAbs(f)
    var needDir = f.slice(-1) === '/'
  
    if (f.length > this.maxLength)
      return cb()
  
    if (!this.stat && ownProp(this.cache, abs)) {
      var c = this.cache[abs]
  
      if (Array.isArray(c))
        c = 'DIR'
  
      // It exists, but maybe not how we need it
      if (!needDir || c === 'DIR')
        return cb(null, c)
  
      if (needDir && c === 'FILE')
        return cb()
  
      // otherwise we have to stat, because maybe c=true
      // if we know it exists, but not what it is.
    }
  
    var exists
    var stat = this.statCache[abs]
    if (stat !== undefined) {
      if (stat === false)
        return cb(null, stat)
      else {
        var type = stat.isDirectory() ? 'DIR' : 'FILE'
        if (needDir && type === 'FILE')
          return cb()
        else
          return cb(null, type, stat)
      }
    }
  
    var self = this
    var statcb = inflight('stat\0' + abs, lstatcb_)
    if (statcb)
      fs.lstat(abs, statcb)
  
    function lstatcb_ (er, lstat) {
      if (lstat && lstat.isSymbolicLink()) {
        // If it's a symlink, then treat it as the target, unless
        // the target does not exist, then treat it as a file.
        return fs.stat(abs, function (er, stat) {
          if (er)
            self._stat2(f, abs, null, lstat, cb)
          else
            self._stat2(f, abs, er, stat, cb)
        })
      } else {
        self._stat2(f, abs, er, lstat, cb)
      }
    }
  }
  
  Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
    if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
      this.statCache[abs] = false
      return cb()
    }
  
    var needDir = f.slice(-1) === '/'
    this.statCache[abs] = stat
  
    if (abs.slice(-1) === '/' && stat && !stat.isDirectory())
      return cb(null, false, stat)
  
    var c = true
    if (stat)
      c = stat.isDirectory() ? 'DIR' : 'FILE'
    this.cache[abs] = this.cache[abs] || c
  
    if (needDir && c === 'FILE')
      return cb()
  
    return cb(null, c, stat)
  }
  
  
  /***/ }),
  
  /***/ 413:
  /***/ (function(module) {
  
  module.exports = require("stream");
  
  /***/ }),
  
  /***/ 431:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  var __importStar = (this && this.__importStar) || function (mod) {
      if (mod && mod.__esModule) return mod;
      var result = {};
      if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
      result["default"] = mod;
      return result;
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  const os = __importStar(__webpack_require__(87));
  /**
   * Commands
   *
   * Command Format:
   *   ::name key=value,key=value::message
   *
   * Examples:
   *   ::warning::This is the message
   *   ::set-env name=MY_VAR::some value
   */
  function issueCommand(command, properties, message) {
      const cmd = new Command(command, properties, message);
      process.stdout.write(cmd.toString() + os.EOL);
  }
  exports.issueCommand = issueCommand;
  function issue(name, message = '') {
      issueCommand(name, {}, message);
  }
  exports.issue = issue;
  const CMD_STRING = '::';
  class Command {
      constructor(command, properties, message) {
          if (!command) {
              command = 'missing.command';
          }
          this.command = command;
          this.properties = properties;
          this.message = message;
      }
      toString() {
          let cmdStr = CMD_STRING + this.command;
          if (this.properties && Object.keys(this.properties).length > 0) {
              cmdStr += ' ';
              let first = true;
              for (const key in this.properties) {
                  if (this.properties.hasOwnProperty(key)) {
                      const val = this.properties[key];
                      if (val) {
                          if (first) {
                              first = false;
                          }
                          else {
                              cmdStr += ',';
                          }
                          cmdStr += `${key}=${escapeProperty(val)}`;
                      }
                  }
              }
          }
          cmdStr += `${CMD_STRING}${escapeData(this.message)}`;
          return cmdStr;
      }
  }
  function escapeData(s) {
      return (s || '')
          .replace(/%/g, '%25')
          .replace(/\r/g, '%0D')
          .replace(/\n/g, '%0A');
  }
  function escapeProperty(s) {
      return (s || '')
          .replace(/%/g, '%25')
          .replace(/\r/g, '%0D')
          .replace(/\n/g, '%0A')
          .replace(/:/g, '%3A')
          .replace(/,/g, '%2C');
  }
  //# sourceMappingURL=command.js.map
  
  /***/ }),
  
  /***/ 470:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
      function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
      return new (P || (P = Promise))(function (resolve, reject) {
          function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
          function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
          function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
          step((generator = generator.apply(thisArg, _arguments || [])).next());
      });
  };
  var __importStar = (this && this.__importStar) || function (mod) {
      if (mod && mod.__esModule) return mod;
      var result = {};
      if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
      result["default"] = mod;
      return result;
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  const command_1 = __webpack_require__(431);
  const os = __importStar(__webpack_require__(87));
  const path = __importStar(__webpack_require__(622));
  /**
   * The code to exit an action
   */
  var ExitCode;
  (function (ExitCode) {
      /**
       * A code indicating that the action was successful
       */
      ExitCode[ExitCode["Success"] = 0] = "Success";
      /**
       * A code indicating that the action was a failure
       */
      ExitCode[ExitCode["Failure"] = 1] = "Failure";
  })(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
  //-----------------------------------------------------------------------
  // Variables
  //-----------------------------------------------------------------------
  /**
   * Sets env variable for this action and future actions in the job
   * @param name the name of the variable to set
   * @param val the value of the variable
   */
  function exportVariable(name, val) {
      process.env[name] = val;
      command_1.issueCommand('set-env', { name }, val);
  }
  exports.exportVariable = exportVariable;
  /**
   * Registers a secret which will get masked from logs
   * @param secret value of the secret
   */
  function setSecret(secret) {
      command_1.issueCommand('add-mask', {}, secret);
  }
  exports.setSecret = setSecret;
  /**
   * Prepends inputPath to the PATH (for this action and future actions)
   * @param inputPath
   */
  function addPath(inputPath) {
      command_1.issueCommand('add-path', {}, inputPath);
      process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
  }
  exports.addPath = addPath;
  /**
   * Gets the value of an input.  The value is also trimmed.
   *
   * @param     name     name of the input to get
   * @param     options  optional. See InputOptions.
   * @returns   string
   */
  function getInput(name, options) {
      const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
      if (options && options.required && !val) {
          throw new Error(`Input required and not supplied: ${name}`);
      }
      return val.trim();
  }
  exports.getInput = getInput;
  /**
   * Sets the value of an output.
   *
   * @param     name     name of the output to set
   * @param     value    value to store
   */
  function setOutput(name, value) {
      command_1.issueCommand('set-output', { name }, value);
  }
  exports.setOutput = setOutput;
  //-----------------------------------------------------------------------
  // Results
  //-----------------------------------------------------------------------
  /**
   * Sets the action status to failed.
   * When the action exits it will be with an exit code of 1
   * @param message add error issue message
   */
  function setFailed(message) {
      process.exitCode = ExitCode.Failure;
      error(message);
  }
  exports.setFailed = setFailed;
  //-----------------------------------------------------------------------
  // Logging Commands
  //-----------------------------------------------------------------------
  /**
   * Gets whether Actions Step Debug is on or not
   */
  function isDebug() {
      return process.env['RUNNER_DEBUG'] === '1';
  }
  exports.isDebug = isDebug;
  /**
   * Writes debug message to user log
   * @param message debug message
   */
  function debug(message) {
      command_1.issueCommand('debug', {}, message);
  }
  exports.debug = debug;
  /**
   * Adds an error issue
   * @param message error issue message
   */
  function error(message) {
      command_1.issue('error', message);
  }
  exports.error = error;
  /**
   * Adds an warning issue
   * @param message warning issue message
   */
  function warning(message) {
      command_1.issue('warning', message);
  }
  exports.warning = warning;
  /**
   * Writes info to log with console.log.
   * @param message info message
   */
  function info(message) {
      process.stdout.write(message + os.EOL);
  }
  exports.info = info;
  /**
   * Begin an output group.
   *
   * Output until the next `groupEnd` will be foldable in this group
   *
   * @param name The name of the output group
   */
  function startGroup(name) {
      command_1.issue('group', name);
  }
  exports.startGroup = startGroup;
  /**
   * End an output group.
   */
  function endGroup() {
      command_1.issue('endgroup');
  }
  exports.endGroup = endGroup;
  /**
   * Wrap an asynchronous function call in a group.
   *
   * Returns the same type as the function itself.
   *
   * @param name The name of the group
   * @param fn The function to wrap in the group
   */
  function group(name, fn) {
      return __awaiter(this, void 0, void 0, function* () {
          startGroup(name);
          let result;
          try {
              result = yield fn();
          }
          finally {
              endGroup();
          }
          return result;
      });
  }
  exports.group = group;
  //-----------------------------------------------------------------------
  // Wrapper action state
  //-----------------------------------------------------------------------
  /**
   * Saves state for current action, the state can only be retrieved by this action's post job execution.
   *
   * @param     name     name of the state to store
   * @param     value    value to store
   */
  function saveState(name, value) {
      command_1.issueCommand('save-state', { name }, value);
  }
  exports.saveState = saveState;
  /**
   * Gets the value of an state set by this action's main execution.
   *
   * @param     name     name of the state to get
   * @returns   string
   */
  function getState(name) {
      return process.env[`STATE_${name}`] || '';
  }
  exports.getState = getState;
  //# sourceMappingURL=core.js.map
  
  /***/ }),
  
  /***/ 539:
  /***/ (function(__unusedmodule, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  
  // EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js
  var core = __webpack_require__(470);
  
  // EXTERNAL MODULE: external "path"
  var external_path_ = __webpack_require__(622);
  var external_path_default = /*#__PURE__*/__webpack_require__.n(external_path_);
  
  // EXTERNAL MODULE: ./node_modules/basic-ftp/dist/index.js
  var dist = __webpack_require__(728);
  
  // EXTERNAL MODULE: ./node_modules/glob/glob.js
  var glob = __webpack_require__(402);
  
  // EXTERNAL MODULE: external "fs"
  var external_fs_ = __webpack_require__(747);
  
  // CONCATENATED MODULE: ./src/utils.js
  
  
  
  const paths = ( patterns ) => {
      return patterns.reduce( ( acc, pattern ) => {
          return acc.concat(
              Object(glob.sync)( pattern ).filter( path => Object(external_fs_.lstatSync)( path ).isFile() )
          );
      }, []);
  };
  
  // CONCATENATED MODULE: ./src/index.js
  
  
  
  
  
  // most @actions toolkit packages have async methods
  async function run() {
      try {
          const SERVER = 'ftp.marketplace.envato.com';
          const ENVATO_USERNAME = Object(core.getInput)('ENVATO_USERNAME');
          const ENVATO_PERSONAL_TOKEN = Object(core.getInput)('ENVATO_PERSONAL_TOKEN');
          const ZIP_FILES = Object(core.getInput)('ZIP_FILES');
          let skip = false;
  
          if ( ! ENVATO_USERNAME ) {
              Object(core.setFailed)('⚠️ ENVATO_USERNAME variable is required');
              skip = true;
          }
          if ( ! ENVATO_PERSONAL_TOKEN ) {
              Object(core.setFailed)('⚠️ ENVATO_PERSONAL_TOKEN variable is required');
              skip = true;
          }
          if ( ! ZIP_FILES ) {
              Object(core.setFailed)('⚠️ ZIP_FILES variable is required');
              skip = true;
          }
  
          if ( skip ) {
              return;
          }
  
          const ZIP_FILES_ARRAY = ZIP_FILES.split( '\n' );
  
          // Upload ZIPs.
          if ( ZIP_FILES_ARRAY && ZIP_FILES_ARRAY.length ) {
              const files = paths( ZIP_FILES_ARRAY );
  
              if ( files.length ) {
                  const client = new dist.Client();
                  client.ftp.verbose = true;
  
                  try {
                      await Object(core.group)( 'Uploading Files', async () => {
                          await client.access( {
                              host: SERVER,
                              user: ENVATO_USERNAME,
                              password: ENVATO_PERSONAL_TOKEN,
                              secure: true,
                          } );
  
                          for ( const file of files ) {
                              await client.uploadFrom( file, external_path_default().parse( file ).base );
                          }
                      } );
                  } catch (error) {
                      console.error('⚠️ Failed to upload files');
                      Object(core.setFailed)(error.message);
                      throw error;
                  }
  
                  client.close();
              } else {
                  console.warn(`🤔 valid files not found.`);
              }
          }
      }
      catch (error) {
          Object(core.setFailed)(error.message);
      }
  }
  
  run()
  
  
  /***/ }),
  
  /***/ 614:
  /***/ (function(module) {
  
  module.exports = require("events");
  
  /***/ }),
  
  /***/ 621:
  /***/ (function(module) {
  
  "use strict";
  
  module.exports = balanced;
  function balanced(a, b, str) {
    if (a instanceof RegExp) a = maybeMatch(a, str);
    if (b instanceof RegExp) b = maybeMatch(b, str);
  
    var r = range(a, b, str);
  
    return r && {
      start: r[0],
      end: r[1],
      pre: str.slice(0, r[0]),
      body: str.slice(r[0] + a.length, r[1]),
      post: str.slice(r[1] + b.length)
    };
  }
  
  function maybeMatch(reg, str) {
    var m = str.match(reg);
    return m ? m[0] : null;
  }
  
  balanced.range = range;
  function range(a, b, str) {
    var begs, beg, left, right, result;
    var ai = str.indexOf(a);
    var bi = str.indexOf(b, ai + 1);
    var i = ai;
  
    if (ai >= 0 && bi > 0) {
      begs = [];
      left = str.length;
  
      while (i >= 0 && !result) {
        if (i == ai) {
          begs.push(i);
          ai = str.indexOf(a, i + 1);
        } else if (begs.length == 1) {
          result = [ begs.pop(), bi ];
        } else {
          beg = begs.pop();
          if (beg < left) {
            left = beg;
            right = bi;
          }
  
          bi = str.indexOf(b, i + 1);
        }
  
        i = ai < bi && ai >= 0 ? ai : bi;
      }
  
      if (begs.length) {
        result = [ left, right ];
      }
    }
  
    return result;
  }
  
  
  /***/ }),
  
  /***/ 622:
  /***/ (function(module) {
  
  module.exports = require("path");
  
  /***/ }),
  
  /***/ 628:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const FileInfo_1 = __webpack_require__(281);
  function parseSize(value, info) {
      info.size = parseInt(value, 10);
  }
  /**
   * Parsers for MLSD facts.
   */
  const factHandlersByName = {
      "size": parseSize,
      "sizd": parseSize,
      "unique": (value, info) => {
          info.uniqueID = value;
      },
      "modify": (value, info) => {
          info.modifiedAt = parseMLSxDate(value);
          info.rawModifiedAt = info.modifiedAt.toISOString();
      },
      "type": (value, info) => {
          // There seems to be confusion on how to handle symbolic links for Unix. RFC 3659 doesn't describe
          // this but mentions some examples using the syntax `type=OS.unix=slink:<target>`. But according to
          // an entry in the Errata (https://www.rfc-editor.org/errata/eid1500) this syntax can't be valid.
          // Instead it proposes to use `type=OS.unix=symlink` and to then list the actual target of the
          // symbolic link as another entry in the directory listing. The unique identifiers can then be used
          // to derive the connection between link(s) and target. We'll have to handle both cases as there
          // are differing opinions on how to deal with this. Here are some links on this topic:
          // - ProFTPD source: https://github.com/proftpd/proftpd/blob/56e6dfa598cbd4ef5c6cba439bcbcd53a63e3b21/modules/mod_facts.c#L531
          // - ProFTPD bug: http://bugs.proftpd.org/show_bug.cgi?id=3318
          // - ProFTPD statement: http://www.proftpd.org/docs/modules/mod_facts.html
          // – FileZilla bug: https://trac.filezilla-project.org/ticket/9310
          if (value.startsWith("OS.unix=slink")) {
              info.type = FileInfo_1.FileType.SymbolicLink;
              info.link = value.substr(value.indexOf(":") + 1);
              return 1 /* Continue */;
          }
          switch (value) {
              case "file":
                  info.type = FileInfo_1.FileType.File;
                  break;
              case "dir":
                  info.type = FileInfo_1.FileType.Directory;
                  break;
              case "OS.unix=symlink":
                  info.type = FileInfo_1.FileType.SymbolicLink;
                  // The target of the symbolic link might be defined in another line in the directory listing.
                  // We'll handle this in `transformList()` below.
                  break;
              case "cdir": // Current directory being listed
              case "pdir": // Parent directory
                  return 2 /* IgnoreFile */; // Don't include these entries in the listing
              default:
                  info.type = FileInfo_1.FileType.Unknown;
          }
          return 1 /* Continue */;
      },
      "unix.mode": (value, info) => {
          const digits = value.substr(-3);
          info.permissions = {
              user: parseInt(digits[0], 10),
              group: parseInt(digits[1], 10),
              world: parseInt(digits[2], 10)
          };
      },
      "unix.ownername": (value, info) => {
          info.user = value;
      },
      "unix.owner": (value, info) => {
          if (info.user === undefined)
              info.user = value;
      },
      get "unix.uid"() {
          return this["unix.owner"];
      },
      "unix.groupname": (value, info) => {
          info.group = value;
      },
      "unix.group": (value, info) => {
          if (info.group === undefined)
              info.group = value;
      },
      get "unix.gid"() {
          return this["unix.group"];
      }
      // Regarding the fact "perm":
      // We don't handle permission information stored in "perm" because its information is conceptually
      // different from what users of FTP clients usually associate with "permissions". Those that have
      // some expectations (and probably want to edit them with a SITE command) often unknowingly expect
      // the Unix permission system. The information passed by "perm" describes what FTP commands can be
      // executed with a file/directory. But even this can be either incomplete or just meant as a "guide"
      // as the spec mentions. From https://tools.ietf.org/html/rfc3659#section-7.5.5: "The permissions are
      // described here as they apply to FTP commands. They may not map easily into particular permissions
      // available on the server's operating system." The parser by Apache Commons tries to translate these
      // to Unix permissions – this is misleading users and might not even be correct.
  };
  /**
   * Split a string once at the first position of a delimiter. For example
   * `splitStringOnce("a b c d", " ")` returns `["a", "b c d"]`.
   */
  function splitStringOnce(str, delimiter) {
      const pos = str.indexOf(delimiter);
      const a = str.substr(0, pos);
      const b = str.substr(pos + delimiter.length);
      return [a, b];
  }
  /**
   * Returns true if a given line might be part of an MLSD listing.
   *
   * - Example 1: `size=15227;type=dir;perm=el;modify=20190419065730; test one`
   * - Example 2: ` file name` (leading space)
   */
  function testLine(line) {
      return /^\S+=\S+;/.test(line) || line.startsWith(" ");
  }
  exports.testLine = testLine;
  /**
   * Parse single line as MLSD listing, see specification at https://tools.ietf.org/html/rfc3659#section-7.
   */
  function parseLine(line) {
      const [packedFacts, name] = splitStringOnce(line, " ");
      if (name === "" || name === "." || name === "..") {
          return undefined;
      }
      const info = new FileInfo_1.FileInfo(name);
      const facts = packedFacts.split(";");
      for (const fact of facts) {
          const [factName, factValue] = splitStringOnce(fact, "=");
          if (!factValue) {
              continue;
          }
          const factHandler = factHandlersByName[factName.toLowerCase()];
          if (!factHandler) {
              continue;
          }
          const result = factHandler(factValue, info);
          if (result === 2 /* IgnoreFile */) {
              return undefined;
          }
      }
      return info;
  }
  exports.parseLine = parseLine;
  function transformList(files) {
      // Create a map of all files that are not symbolic links by their unique ID
      const nonLinksByID = new Map();
      for (const file of files) {
          if (!file.isSymbolicLink && file.uniqueID !== undefined) {
              nonLinksByID.set(file.uniqueID, file);
          }
      }
      const resolvedFiles = [];
      for (const file of files) {
          // Try to associate unresolved symbolic links with a target file/directory.
          if (file.isSymbolicLink && file.uniqueID !== undefined && file.link === undefined) {
              const target = nonLinksByID.get(file.uniqueID);
              if (target !== undefined) {
                  file.link = target.name;
              }
          }
          // The target of a symbolic link is listed as an entry in the directory listing but might
          // have a path pointing outside of this directory. In that case we don't want this entry
          // to be part of the listing. We generally don't want these kind of entries at all.
          const isPartOfDirectory = !file.name.includes("/");
          if (isPartOfDirectory) {
              resolvedFiles.push(file);
          }
      }
      return resolvedFiles;
  }
  exports.transformList = transformList;
  /**
   * Parse date as specified in https://tools.ietf.org/html/rfc3659#section-2.3.
   *
   * Message contains response code and modified time in the format: YYYYMMDDHHMMSS[.sss]
   * For example `19991005213102` or `19980615100045.014`.
   */
  function parseMLSxDate(fact) {
      return new Date(Date.UTC(+fact.slice(0, 4), // Year
      +fact.slice(4, 6) - 1, // Month
      +fact.slice(6, 8), // Date
      +fact.slice(8, 10), // Hours
      +fact.slice(10, 12), // Minutes
      +fact.slice(12, 14), // Seconds
      +fact.slice(15, 18) // Milliseconds
      ));
  }
  exports.parseMLSxDate = parseMLSxDate;
  
  
  /***/ }),
  
  /***/ 631:
  /***/ (function(module) {
  
  module.exports = require("net");
  
  /***/ }),
  
  /***/ 669:
  /***/ (function(module) {
  
  module.exports = require("util");
  
  /***/ }),
  
  /***/ 674:
  /***/ (function(module, __unusedexports, __webpack_require__) {
  
  var wrappy = __webpack_require__(11)
  var reqs = Object.create(null)
  var once = __webpack_require__(49)
  
  module.exports = wrappy(inflight)
  
  function inflight (key, cb) {
    if (reqs[key]) {
      reqs[key].push(cb)
      return null
    } else {
      reqs[key] = [cb]
      return makeres(key)
    }
  }
  
  function makeres (key) {
    return once(function RES () {
      var cbs = reqs[key]
      var len = cbs.length
      var args = slice(arguments)
  
      // XXX It's somewhat ambiguous whether a new callback added in this
      // pass should be queued for later execution if something in the
      // list of callbacks throws, or if it should just be discarded.
      // However, it's such an edge case that it hardly matters, and either
      // choice is likely as surprising as the other.
      // As it happens, we do go ahead and schedule it for later execution.
      try {
        for (var i = 0; i < len; i++) {
          cbs[i].apply(null, args)
        }
      } finally {
        if (cbs.length > len) {
          // added more in the interim.
          // de-zalgo, just in case, but don't call again.
          cbs.splice(0, len)
          process.nextTick(function () {
            RES.apply(null, args)
          })
        } else {
          delete reqs[key]
        }
      }
    })
  }
  
  function slice (args) {
    var length = args.length
    var array = []
  
    for (var i = 0; i < length; i++) array[i] = args[i]
    return array
  }
  
  
  /***/ }),
  
  /***/ 681:
  /***/ (function(module) {
  
  "use strict";
  
  
  function posix(path) {
  	return path.charAt(0) === '/';
  }
  
  function win32(path) {
  	// https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
  	var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
  	var result = splitDeviceRe.exec(path);
  	var device = result[1] || '';
  	var isUnc = Boolean(device && device.charAt(1) !== ':');
  
  	// UNC paths are always absolute
  	return Boolean(result[2] || isUnc);
  }
  
  module.exports = process.platform === 'win32' ? win32 : posix;
  module.exports.posix = posix;
  module.exports.win32 = win32;
  
  
  /***/ }),
  
  /***/ 689:
  /***/ (function(module, __unusedexports, __webpack_require__) {
  
  try {
    var util = __webpack_require__(669);
    /* istanbul ignore next */
    if (typeof util.inherits !== 'function') throw '';
    module.exports = util.inherits;
  } catch (e) {
    /* istanbul ignore next */
    module.exports = __webpack_require__(315);
  }
  
  
  /***/ }),
  
  /***/ 728:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  function __export(m) {
      for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
  }
  Object.defineProperty(exports, "__esModule", { value: true });
  /**
   * Public API
   */
  __export(__webpack_require__(305));
  __export(__webpack_require__(973));
  __export(__webpack_require__(281));
  __export(__webpack_require__(932));
  var transfer_1 = __webpack_require__(368);
  exports.enterPassiveModeIPv4 = transfer_1.enterPassiveModeIPv4;
  exports.enterPassiveModeIPv6 = transfer_1.enterPassiveModeIPv6;
  
  
  /***/ }),
  
  /***/ 744:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const FileInfo_1 = __webpack_require__(281);
  const JA_MONTH = "\u6708";
  const JA_DAY = "\u65e5";
  const JA_YEAR = "\u5e74";
  /**
   * This parser is based on the FTP client library source code in Apache Commons Net provided
   * under the Apache 2.0 license. It has been simplified and rewritten to better fit the Javascript language.
   *
   * https://github.com/apache/commons-net/blob/master/src/main/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
   *
   * Below is the regular expression used by this parser.
   *
   * Permissions:
   *    r   the file is readable
   *    w   the file is writable
   *    x   the file is executable
   *    -   the indicated permission is not granted
   *    L   mandatory locking occurs during access (the set-group-ID bit is
   *        on and the group execution bit is off)
   *    s   the set-user-ID or set-group-ID bit is on, and the corresponding
   *        user or group execution bit is also on
   *    S   undefined bit-state (the set-user-ID bit is on and the user
   *        execution bit is off)
   *    t   the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and
   *        execution is on
   *    T   the 1000 bit is turned on, and execution is off (undefined bit-
   *        state)
   *    e   z/OS external link bit
   *    Final letter may be appended:
   *    +   file has extended security attributes (e.g. ACL)
   *    Note: local listings on MacOSX also use '@'
   *    this is not allowed for here as does not appear to be shown by FTP servers
   *    {@code @}   file has extended attributes
   */
  const RE_LINE = new RegExp("([bcdelfmpSs-])" // file type
      + "(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))\\+?" // permissions
      + "\\s*" // separator TODO why allow it to be omitted??
      + "(\\d+)" // link count
      + "\\s+" // separator
      + "(?:(\\S+(?:\\s\\S+)*?)\\s+)?" // owner name (optional spaces)
      + "(?:(\\S+(?:\\s\\S+)*)\\s+)?" // group name (optional spaces)
      + "(\\d+(?:,\\s*\\d+)?)" // size or n,m
      + "\\s+" // separator
      /**
       * numeric or standard format date:
       *   yyyy-mm-dd (expecting hh:mm to follow)
       *   MMM [d]d
       *   [d]d MMM
       *   N.B. use non-space for MMM to allow for languages such as German which use
       *   diacritics (e.g. umlaut) in some abbreviations.
       *   Japanese uses numeric day and month with suffixes to distinguish them
       *   [d]dXX [d]dZZ
       */
      + "(" +
      "(?:\\d+[-/]\\d+[-/]\\d+)" + // yyyy-mm-dd
      "|(?:\\S{3}\\s+\\d{1,2})" + // MMM [d]d
      "|(?:\\d{1,2}\\s+\\S{3})" + // [d]d MMM
      "|(?:\\d{1,2}" + JA_MONTH + "\\s+\\d{1,2}" + JA_DAY + ")" +
      ")"
      + "\\s+" // separator
      /**
       * year (for non-recent standard format) - yyyy
       * or time (for numeric or recent standard format) [h]h:mm
       * or Japanese year - yyyyXX
       */
      + "((?:\\d+(?::\\d+)?)|(?:\\d{4}" + JA_YEAR + "))" // (20)
      + "\\s" // separator
      + "(.*)"); // the rest (21)
  /**
   * Returns true if a given line might be a Unix-style listing.
   *
   * - Example: `-rw-r--r--+   1 patrick  staff   1057 Dec 11 14:35 test.txt`
   */
  function testLine(line) {
      return RE_LINE.test(line);
  }
  exports.testLine = testLine;
  /**
   * Parse a single line of a Unix-style directory listing.
   */
  function parseLine(line) {
      const groups = line.match(RE_LINE);
      if (groups === null) {
          return undefined;
      }
      const name = groups[21];
      if (name === "." || name === "..") { // Ignore parent directory links
          return undefined;
      }
      const file = new FileInfo_1.FileInfo(name);
      file.size = parseInt(groups[18], 10);
      file.user = groups[16];
      file.group = groups[17];
      file.hardLinkCount = parseInt(groups[15], 10);
      file.rawModifiedAt = groups[19] + " " + groups[20];
      file.permissions = {
          user: parseMode(groups[4], groups[5], groups[6]),
          group: parseMode(groups[8], groups[9], groups[10]),
          world: parseMode(groups[12], groups[13], groups[14]),
      };
      // Set file type
      switch (groups[1].charAt(0)) {
          case "d":
              file.type = FileInfo_1.FileType.Directory;
              break;
          case "e": // NET-39 => z/OS external link
              file.type = FileInfo_1.FileType.SymbolicLink;
              break;
          case "l":
              file.type = FileInfo_1.FileType.SymbolicLink;
              break;
          case "b":
          case "c":
              file.type = FileInfo_1.FileType.File; // TODO change this if DEVICE_TYPE implemented
              break;
          case "f":
          case "-":
              file.type = FileInfo_1.FileType.File;
              break;
          default:
              // A 'whiteout' file is an ARTIFICIAL entry in any of several types of
              // 'translucent' filesystems, of which a 'union' filesystem is one.
              file.type = FileInfo_1.FileType.Unknown;
      }
      // Separate out the link name for symbolic links
      if (file.isSymbolicLink) {
          const end = name.indexOf(" -> ");
          if (end !== -1) {
              file.name = name.substring(0, end);
              file.link = name.substring(end + 4);
          }
      }
      return file;
  }
  exports.parseLine = parseLine;
  function transformList(files) {
      return files;
  }
  exports.transformList = transformList;
  function parseMode(r, w, x) {
      let value = 0;
      if (r !== "-") {
          value += FileInfo_1.FileInfo.UnixPermission.Read;
      }
      if (w !== "-") {
          value += FileInfo_1.FileInfo.UnixPermission.Write;
      }
      const execToken = x.charAt(0);
      if (execToken !== "-" && execToken.toUpperCase() !== execToken) {
          value += FileInfo_1.FileInfo.UnixPermission.Execute;
      }
      return value;
  }
  
  
  /***/ }),
  
  /***/ 747:
  /***/ (function(module) {
  
  module.exports = require("fs");
  
  /***/ }),
  
  /***/ 843:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const FileInfo_1 = __webpack_require__(281);
  /**
   * This parser is based on the FTP client library source code in Apache Commons Net provided
   * under the Apache 2.0 license. It has been simplified and rewritten to better fit the Javascript language.
   *
   * https://github.com/apache/commons-net/blob/master/src/main/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java
   */
  const RE_LINE = new RegExp("(\\S+)\\s+(\\S+)\\s+" // MM-dd-yy whitespace hh:mma|kk:mm swallow trailing spaces
      + "(?:(<DIR>)|([0-9]+))\\s+" // <DIR> or ddddd swallow trailing spaces
      + "(\\S.*)" // First non-space followed by rest of line (name)
  );
  /**
   * Returns true if a given line might be a DOS-style listing.
   *
   * - Example: `12-05-96  05:03PM       <DIR>          myDir`
   */
  function testLine(line) {
      return /^\d{2}/.test(line) && RE_LINE.test(line);
  }
  exports.testLine = testLine;
  /**
   * Parse a single line of a DOS-style directory listing.
   */
  function parseLine(line) {
      const groups = line.match(RE_LINE);
      if (groups === null) {
          return undefined;
      }
      const name = groups[5];
      if (name === "." || name === "..") { // Ignore parent directory links
          return undefined;
      }
      const file = new FileInfo_1.FileInfo(name);
      const fileType = groups[3];
      if (fileType === "<DIR>") {
          file.type = FileInfo_1.FileType.Directory;
          file.size = 0;
      }
      else {
          file.type = FileInfo_1.FileType.File;
          file.size = parseInt(groups[4], 10);
      }
      file.rawModifiedAt = groups[1] + " " + groups[2];
      return file;
  }
  exports.parseLine = parseLine;
  function transformList(files) {
      return files;
  }
  exports.transformList = transformList;
  
  
  /***/ }),
  
  /***/ 845:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const stream_1 = __webpack_require__(413);
  class StringWriter extends stream_1.Writable {
      constructor() {
          super(...arguments);
          this.buf = Buffer.alloc(0);
      }
      _write(chunk, _, callback) {
          if (chunk instanceof Buffer) {
              this.buf = Buffer.concat([this.buf, chunk]);
              callback(null);
          }
          else {
              callback(new Error("StringWriter expects chunks of type 'Buffer'."));
          }
      }
      getText(encoding) {
          return this.buf.toString(encoding);
      }
  }
  exports.StringWriter = StringWriter;
  
  
  /***/ }),
  
  /***/ 856:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  exports.alphasort = alphasort
  exports.alphasorti = alphasorti
  exports.setopts = setopts
  exports.ownProp = ownProp
  exports.makeAbs = makeAbs
  exports.finish = finish
  exports.mark = mark
  exports.isIgnored = isIgnored
  exports.childrenIgnored = childrenIgnored
  
  function ownProp (obj, field) {
    return Object.prototype.hasOwnProperty.call(obj, field)
  }
  
  var path = __webpack_require__(622)
  var minimatch = __webpack_require__(93)
  var isAbsolute = __webpack_require__(681)
  var Minimatch = minimatch.Minimatch
  
  function alphasorti (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase())
  }
  
  function alphasort (a, b) {
    return a.localeCompare(b)
  }
  
  function setupIgnores (self, options) {
    self.ignore = options.ignore || []
  
    if (!Array.isArray(self.ignore))
      self.ignore = [self.ignore]
  
    if (self.ignore.length) {
      self.ignore = self.ignore.map(ignoreMap)
    }
  }
  
  // ignore patterns are always in dot:true mode.
  function ignoreMap (pattern) {
    var gmatcher = null
    if (pattern.slice(-3) === '/**') {
      var gpattern = pattern.replace(/(\/\*\*)+$/, '')
      gmatcher = new Minimatch(gpattern, { dot: true })
    }
  
    return {
      matcher: new Minimatch(pattern, { dot: true }),
      gmatcher: gmatcher
    }
  }
  
  function setopts (self, pattern, options) {
    if (!options)
      options = {}
  
    // base-matching: just use globstar for that.
    if (options.matchBase && -1 === pattern.indexOf("/")) {
      if (options.noglobstar) {
        throw new Error("base matching requires globstar")
      }
      pattern = "**/" + pattern
    }
  
    self.silent = !!options.silent
    self.pattern = pattern
    self.strict = options.strict !== false
    self.realpath = !!options.realpath
    self.realpathCache = options.realpathCache || Object.create(null)
    self.follow = !!options.follow
    self.dot = !!options.dot
    self.mark = !!options.mark
    self.nodir = !!options.nodir
    if (self.nodir)
      self.mark = true
    self.sync = !!options.sync
    self.nounique = !!options.nounique
    self.nonull = !!options.nonull
    self.nosort = !!options.nosort
    self.nocase = !!options.nocase
    self.stat = !!options.stat
    self.noprocess = !!options.noprocess
    self.absolute = !!options.absolute
  
    self.maxLength = options.maxLength || Infinity
    self.cache = options.cache || Object.create(null)
    self.statCache = options.statCache || Object.create(null)
    self.symlinks = options.symlinks || Object.create(null)
  
    setupIgnores(self, options)
  
    self.changedCwd = false
    var cwd = process.cwd()
    if (!ownProp(options, "cwd"))
      self.cwd = cwd
    else {
      self.cwd = path.resolve(options.cwd)
      self.changedCwd = self.cwd !== cwd
    }
  
    self.root = options.root || path.resolve(self.cwd, "/")
    self.root = path.resolve(self.root)
    if (process.platform === "win32")
      self.root = self.root.replace(/\\/g, "/")
  
    // TODO: is an absolute `cwd` supposed to be resolved against `root`?
    // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
    self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd)
    if (process.platform === "win32")
      self.cwdAbs = self.cwdAbs.replace(/\\/g, "/")
    self.nomount = !!options.nomount
  
    // disable comments and negation in Minimatch.
    // Note that they are not supported in Glob itself anyway.
    options.nonegate = true
    options.nocomment = true
  
    self.minimatch = new Minimatch(pattern, options)
    self.options = self.minimatch.options
  }
  
  function finish (self) {
    var nou = self.nounique
    var all = nou ? [] : Object.create(null)
  
    for (var i = 0, l = self.matches.length; i < l; i ++) {
      var matches = self.matches[i]
      if (!matches || Object.keys(matches).length === 0) {
        if (self.nonull) {
          // do like the shell, and spit out the literal glob
          var literal = self.minimatch.globSet[i]
          if (nou)
            all.push(literal)
          else
            all[literal] = true
        }
      } else {
        // had matches
        var m = Object.keys(matches)
        if (nou)
          all.push.apply(all, m)
        else
          m.forEach(function (m) {
            all[m] = true
          })
      }
    }
  
    if (!nou)
      all = Object.keys(all)
  
    if (!self.nosort)
      all = all.sort(self.nocase ? alphasorti : alphasort)
  
    // at *some* point we statted all of these
    if (self.mark) {
      for (var i = 0; i < all.length; i++) {
        all[i] = self._mark(all[i])
      }
      if (self.nodir) {
        all = all.filter(function (e) {
          var notDir = !(/\/$/.test(e))
          var c = self.cache[e] || self.cache[makeAbs(self, e)]
          if (notDir && c)
            notDir = c !== 'DIR' && !Array.isArray(c)
          return notDir
        })
      }
    }
  
    if (self.ignore.length)
      all = all.filter(function(m) {
        return !isIgnored(self, m)
      })
  
    self.found = all
  }
  
  function mark (self, p) {
    var abs = makeAbs(self, p)
    var c = self.cache[abs]
    var m = p
    if (c) {
      var isDir = c === 'DIR' || Array.isArray(c)
      var slash = p.slice(-1) === '/'
  
      if (isDir && !slash)
        m += '/'
      else if (!isDir && slash)
        m = m.slice(0, -1)
  
      if (m !== p) {
        var mabs = makeAbs(self, m)
        self.statCache[mabs] = self.statCache[abs]
        self.cache[mabs] = self.cache[abs]
      }
    }
  
    return m
  }
  
  // lotta situps...
  function makeAbs (self, f) {
    var abs = f
    if (f.charAt(0) === '/') {
      abs = path.join(self.root, f)
    } else if (isAbsolute(f) || f === '') {
      abs = f
    } else if (self.changedCwd) {
      abs = path.resolve(self.cwd, f)
    } else {
      abs = path.resolve(f)
    }
  
    if (process.platform === 'win32')
      abs = abs.replace(/\\/g, '/')
  
    return abs
  }
  
  
  // Return true, if pattern ends with globstar '**', for the accompanying parent directory.
  // Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
  function isIgnored (self, path) {
    if (!self.ignore.length)
      return false
  
    return self.ignore.some(function(item) {
      return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
    })
  }
  
  function childrenIgnored (self, path) {
    if (!self.ignore.length)
      return false
  
    return self.ignore.some(function(item) {
      return !!(item.gmatcher && item.gmatcher.match(path))
    })
  }
  
  
  /***/ }),
  
  /***/ 864:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const tls_1 = __webpack_require__(16);
  /**
   * Returns a string describing the encryption on a given socket instance.
   */
  function describeTLS(socket) {
      if (socket instanceof tls_1.TLSSocket) {
          const protocol = socket.getProtocol();
          return protocol ? protocol : "Server socket or disconnected client socket";
      }
      return "No encryption";
  }
  exports.describeTLS = describeTLS;
  /**
   * Returns a string describing the remote address of a socket.
   */
  function describeAddress(socket) {
      if (socket.remoteFamily === "IPv6") {
          return `[${socket.remoteAddress}]:${socket.remotePort}`;
      }
      return `${socket.remoteAddress}:${socket.remotePort}`;
  }
  exports.describeAddress = describeAddress;
  /**
   * Upgrade a socket connection with TLS.
   */
  function upgradeSocket(socket, options) {
      return new Promise((resolve, reject) => {
          const tlsOptions = Object.assign({}, options, {
              socket
          });
          const tlsSocket = tls_1.connect(tlsOptions, () => {
              const expectCertificate = tlsOptions.rejectUnauthorized !== false;
              if (expectCertificate && !tlsSocket.authorized) {
                  reject(tlsSocket.authorizationError);
              }
              else {
                  // Remove error listener added below.
                  tlsSocket.removeAllListeners("error");
                  resolve(tlsSocket);
              }
          }).once("error", error => {
              reject(error);
          });
      });
  }
  exports.upgradeSocket = upgradeSocket;
  /**
   * Returns true if an IP is a private address according to https://tools.ietf.org/html/rfc1918#section-3.
   * This will handle IPv4-mapped IPv6 addresses correctly but return false for all other IPv6 addresses.
   *
   * @param ip  The IP as a string, e.g. "192.168.0.1"
   */
  function ipIsPrivateV4Address(ip = "") {
      // Handle IPv4-mapped IPv6 addresses like ::ffff:192.168.0.1
      if (ip.startsWith("::ffff:")) {
          ip = ip.substr(7); // Strip ::ffff: prefix
      }
      const octets = ip.split(".").map(o => parseInt(o, 10));
      return octets[0] === 10 // 10.0.0.0 - 10.255.255.255
          || (octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31) // 172.16.0.0 - 172.31.255.255
          || (octets[0] === 192 && octets[1] === 168); // 192.168.0.0 - 192.168.255.255
  }
  exports.ipIsPrivateV4Address = ipIsPrivateV4Address;
  
  
  /***/ }),
  
  /***/ 896:
  /***/ (function(module) {
  
  module.exports = function (xs, fn) {
      var res = [];
      for (var i = 0; i < xs.length; i++) {
          var x = fn(xs[i], i);
          if (isArray(x)) res.push.apply(res, x);
          else res.push(x);
      }
      return res;
  };
  
  var isArray = Array.isArray || function (xs) {
      return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  
  /***/ }),
  
  /***/ 932:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  var __importStar = (this && this.__importStar) || function (mod) {
      if (mod && mod.__esModule) return mod;
      var result = {};
      if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
      result["default"] = mod;
      return result;
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  const dosParser = __importStar(__webpack_require__(843));
  const unixParser = __importStar(__webpack_require__(744));
  const mlsdParser = __importStar(__webpack_require__(628));
  /**
   * Available directory listing parsers. These are candidates that will be tested
   * in the order presented. The first candidate will be used to parse the whole list.
   */
  const availableParsers = [
      dosParser,
      unixParser,
      mlsdParser // Keep MLSD last, may accept filename only
  ];
  function firstCompatibleParser(line, parsers) {
      return parsers.find(parser => parser.testLine(line) === true);
  }
  function stringIsNotBlank(str) {
      return str.trim() !== "";
  }
  const REGEX_NEWLINE = /\r?\n/;
  /**
   * Parse raw directory listing.
   */
  function parseList(rawList) {
      const lines = rawList
          .split(REGEX_NEWLINE)
          .filter(stringIsNotBlank);
      if (lines.length === 0) {
          return [];
      }
      const testLine = lines[lines.length - 1];
      const parser = firstCompatibleParser(testLine, availableParsers);
      if (!parser) {
          throw new Error("This library only supports MLSD, Unix- or DOS-style directory listing. Your FTP server seems to be using another format. You can see the transmitted listing when setting `client.ftp.verbose = true`. You can then provide a custom parser to `client.parseList`, see the documentation for details.");
      }
      const files = lines
          .map(parser.parseLine)
          .filter((info) => info !== undefined);
      return parser.transformList(files);
  }
  exports.parseList = parseList;
  
  
  /***/ }),
  
  /***/ 973:
  /***/ (function(__unusedmodule, exports, __webpack_require__) {
  
  "use strict";
  
  Object.defineProperty(exports, "__esModule", { value: true });
  const net_1 = __webpack_require__(631);
  const parseControlResponse_1 = __webpack_require__(262);
  /**
   * Describes an FTP server error response including the FTP response code.
   */
  class FTPError extends Error {
      constructor(res) {
          super(res.message);
          this.name = this.constructor.name;
          this.code = res.code;
      }
  }
  exports.FTPError = FTPError;
  /**
   * FTPContext holds the control and data sockets of an FTP connection and provides a
   * simplified way to interact with an FTP server, handle responses, errors and timeouts.
   *
   * It doesn't implement or use any FTP commands. It's only a foundation to make writing an FTP
   * client as easy as possible. You won't usually instantiate this, but use `Client`.
   */
  class FTPContext {
      /**
       * Instantiate an FTP context.
       *
       * @param timeout - Timeout in milliseconds to apply to control and data connections. Use 0 for no timeout.
       * @param encoding - Encoding to use for control connection. UTF-8 by default. Use "latin1" for older servers.
       */
      constructor(timeout = 0, encoding = "utf8") {
          this.timeout = timeout;
          /** Debug-level logging of all socket communication. */
          this.verbose = false;
          /** IP version to prefer (4: IPv4, 6: IPv6, undefined: automatic). */
          this.ipFamily = undefined;
          /** Options for TLS connections. */
          this.tlsOptions = {};
          /** A multiline response might be received as multiple chunks. */
          this._partialResponse = "";
          this._encoding = encoding;
          // Help Typescript understand that we do indeed set _socket in the constructor but use the setter method to do so.
          this._socket = this.socket = this._newSocket();
          this._dataSocket = undefined;
      }
      /**
       * Close the context.
       */
      close() {
          // Internally, closing a context is always described with an error. If there is still a task running, it will
          // abort with an exception that the user closed the client during a task. If no task is running, no exception is
          // thrown but all newly submitted tasks after that will abort the exception that the client has been closed.
          // In addition the user will get a stack trace pointing to where exactly the client has been closed. So in any
          // case use _closingError to determine whether a context is closed. This also allows us to have a single code-path
          // for closing a context making the implementation easier.
          const message = this._task ? "User closed client during task" : "User closed client";
          const err = new Error(message);
          this.closeWithError(err);
      }
      /**
       * Close the context with an error.
       */
      closeWithError(err) {
          // If this context already has been closed, don't overwrite the reason.
          if (this._closingError) {
              return;
          }
          this._closingError = err;
          // Before giving the user's task a chance to react, make sure we won't be bothered with any inputs.
          this._closeSocket(this._socket);
          this._closeSocket(this._dataSocket);
          // Give the user's task a chance to react, maybe cleanup resources.
          this._passToHandler(err);
          // The task might not have been rejected by the user after receiving the error.
          this._stopTrackingTask();
      }
      /**
       * Returns true if this context has been closed or hasn't been connected yet. You can reopen it with `access`.
       */
      get closed() {
          return this.socket.remoteAddress === undefined || this._closingError !== undefined;
      }
      /**
       * Reset this contex and all of its state.
       */
      reset() {
          this.socket = this._newSocket();
      }
      /**
       * Get the FTP control socket.
       */
      get socket() {
          return this._socket;
      }
      /**
       * Set the socket for the control connection. This will only close the current control socket
       * if the new one is not an upgrade to the current one.
       */
      set socket(socket) {
          // No data socket should be open in any case where the control socket is set or upgraded.
          this.dataSocket = undefined;
          // This being a soft reset, remove any remaining partial response.
          this._partialResponse = "";
          if (this._socket) {
              // Only close the current connection if the new is not an upgrade.
              const isUpgrade = socket.localPort === this._socket.localPort;
              if (!isUpgrade) {
                  this._socket.destroy();
              }
              this._removeSocketListeners(this._socket);
          }
          if (socket) {
              // Setting a completely new control socket is in essence something like a reset. That's
              // why we also close any open data connection above. We can go one step further and reset
              // a possible closing error. That means that a closed FTPContext can be "reopened" by
              // setting a new control socket.
              this._closingError = undefined;
              // Don't set a timeout yet. Timeout for control sockets is only active during a task, see handle() below.
              socket.setTimeout(0);
              socket.setEncoding(this._encoding);
              socket.setKeepAlive(true);
              socket.on("data", data => this._onControlSocketData(data));
              // Server sending a FIN packet is treated as an error.
              socket.on("end", () => this.closeWithError(new Error("Server closed connection.")));
              // Control being closed without error by server is treated as an error.
              socket.on("close", hadError => { if (!hadError)
                  this.closeWithError(new Error("Server closed connection.")); });
              this._setupErrorHandlers(socket, "control socket");
          }
          this._socket = socket;
      }
      /**
       * Get the current FTP data connection if present.
       */
      get dataSocket() {
          return this._dataSocket;
      }
      /**
       * Set the socket for the data connection. This will automatically close the former data socket.
       */
      set dataSocket(socket) {
          this._closeSocket(this._dataSocket);
          if (socket) {
              // Don't set a timeout yet. Timeout data socket should be activated when data transmission starts
              // and timeout on control socket is deactivated.
              socket.setTimeout(0);
              this._setupErrorHandlers(socket, "data socket");
          }
          this._dataSocket = socket;
      }
      /**
       * Get the currently used encoding.
       */
      get encoding() {
          return this._encoding;
      }
      /**
       * Set the encoding used for the control socket.
       *
       * See https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings for what encodings
       * are supported by Node.
       */
      set encoding(encoding) {
          this._encoding = encoding;
          if (this.socket) {
              this.socket.setEncoding(encoding);
          }
      }
      /**
       * Send an FTP command without waiting for or handling the result.
       */
      send(command) {
          const containsPassword = command.startsWith("PASS");
          const message = containsPassword ? "> PASS ###" : `> ${command}`;
          this.log(message);
          this._socket.write(command + "\r\n", this.encoding);
      }
      /**
       * Send an FTP command and handle the first response. Use this if you have a simple
       * request-response situation.
       */
      request(command) {
          return this.handle(command, (res, task) => {
              if (res instanceof Error) {
                  task.reject(res);
              }
              else {
                  task.resolve(res);
              }
          });
      }
      /**
       * Send an FTP command and handle any response until you resolve/reject. Use this if you expect multiple responses
       * to a request. This returns a Promise that will hold whatever the response handler passed on when resolving/rejecting its task.
       */
      handle(command, responseHandler) {
          if (this._task) {
              // The user or client instance called `handle()` while a task is still running.
              const err = new Error("User launched a task while another one is still running. Forgot to use 'await' or '.then()'?");
              err.stack += `\nRunning task launched at: ${this._task.stack}`;
              this.closeWithError(err);
              // Don't return here, continue with returning the Promise that will then be rejected
              // because the context closed already. That way, users will receive an exception where
              // they called this method by mistake.
          }
          return new Promise((resolvePromise, rejectPromise) => {
              const stack = new Error().stack || "Unknown call stack";
              const resolver = {
                  resolve: (...args) => {
                      this._stopTrackingTask();
                      resolvePromise(...args);
                  },
                  reject: err => {
                      this._stopTrackingTask();
                      rejectPromise(err);
                  }
              };
              this._task = {
                  stack,
                  resolver,
                  responseHandler
              };
              if (this._closingError) {
                  // This client has been closed. Provide an error that describes this one as being caused
                  // by `_closingError`, include stack traces for both.
                  const err = new Error("Client is closed"); // Type 'Error' is not correctly defined, doesn't have 'code'.
                  err.stack += `\nClosing reason: ${this._closingError.stack}`;
                  err.code = this._closingError.code !== undefined ? this._closingError.code : "0";
                  this._passToHandler(err);
                  return;
              }
              // Only track control socket timeout during the lifecycle of a task. This avoids timeouts on idle sockets,
              // the default socket behaviour which is not expected by most users.
              this.socket.setTimeout(this.timeout);
              if (command) {
                  this.send(command);
              }
          });
      }
      /**
       * Log message if set to be verbose.
       */
      log(message) {
          if (this.verbose) {
              // tslint:disable-next-line no-console
              console.log(message);
          }
      }
      /**
       * Return true if the control socket is using TLS. This does not mean that a session
       * has already been negotiated.
       */
      get hasTLS() {
          return "encrypted" in this._socket;
      }
      /**
       * Removes reference to current task and handler. This won't resolve or reject the task.
       * @protected
       */
      _stopTrackingTask() {
          // Disable timeout on control socket if there is no task active.
          this.socket.setTimeout(0);
          this._task = undefined;
      }
      /**
       * Handle incoming data on the control socket. The chunk is going to be of type `string`
       * because we let `socket` handle encoding with `setEncoding`.
       * @protected
       */
      _onControlSocketData(chunk) {
          const trimmedChunk = chunk.trim();
          this.log(`< ${trimmedChunk}`);
          // This chunk might complete an earlier partial response.
          const completeResponse = this._partialResponse + trimmedChunk;
          const parsed = parseControlResponse_1.parseControlResponse(completeResponse);
          // Remember any incomplete remainder.
          this._partialResponse = parsed.rest;
          // Each response group is passed along individually.
          for (const message of parsed.messages) {
              const code = parseInt(message.substr(0, 3), 10);
              const response = { code, message };
              const err = code >= 400 ? new FTPError(response) : undefined;
              this._passToHandler(err ? err : response);
          }
      }
      /**
       * Send the current handler a response. This is usually a control socket response
       * or a socket event, like an error or timeout.
       * @protected
       */
      _passToHandler(response) {
          if (this._task) {
              this._task.responseHandler(response, this._task.resolver);
          }
          // Errors other than FTPError always close the client. If there isn't an active task to handle the error,
          // the next one submitted will receive it using `_closingError`.
          // There is only one edge-case: If there is an FTPError while no task is active, the error will be dropped.
          // But that means that the user sent an FTP command with no intention of handling the result. So why should the
          // error be handled? Maybe log it at least? Debug logging will already do that and the client stays useable after
          // FTPError. So maybe no need to do anything here.
      }
      /**
       * Setup all error handlers for a socket.
       * @protected
       */
      _setupErrorHandlers(socket, identifier) {
          socket.once("error", error => {
              error.message += ` (${identifier})`;
              this.closeWithError(error);
          });
          socket.once("close", hadError => {
              if (hadError) {
                  this.closeWithError(new Error(`Socket closed due to transmission error (${identifier})`));
              }
          });
          socket.once("timeout", () => this.closeWithError(new Error(`Timeout (${identifier})`)));
      }
      /**
       * Close a socket.
       * @protected
       */
      _closeSocket(socket) {
          if (socket) {
              socket.destroy();
              this._removeSocketListeners(socket);
          }
      }
      /**
       * Remove all default listeners for socket.
       * @protected
       */
      _removeSocketListeners(socket) {
          socket.removeAllListeners();
          // Before Node.js 10.3.0, using `socket.removeAllListeners()` without any name did not work: https://github.com/nodejs/node/issues/20923.
          socket.removeAllListeners("timeout");
          socket.removeAllListeners("data");
          socket.removeAllListeners("end");
          socket.removeAllListeners("error");
          socket.removeAllListeners("close");
          socket.removeAllListeners("connect");
      }
      /**
       * Provide a new socket instance.
       *
       * Internal use only, replaced for unit tests.
       */
      _newSocket() {
          return new net_1.Socket();
      }
  }
  exports.FTPContext = FTPContext;
  
  
  /***/ })
  
  /******/ },
  /******/ function(__webpack_require__) { // webpackRuntimeModules
  /******/ 	"use strict";
  /******/ 
  /******/ 	/* webpack/runtime/make namespace object */
  /******/ 	!function() {
  /******/ 		// define __esModule on exports
  /******/ 		__webpack_require__.r = function(exports) {
  /******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  /******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  /******/ 			}
  /******/ 			Object.defineProperty(exports, '__esModule', { value: true });
  /******/ 		};
  /******/ 	}();
  /******/ 	
  /******/ 	/* webpack/runtime/define property getter */
  /******/ 	!function() {
  /******/ 		// define getter function for harmony exports
  /******/ 		var hasOwnProperty = Object.prototype.hasOwnProperty;
  /******/ 		__webpack_require__.d = function(exports, name, getter) {
  /******/ 			if(!hasOwnProperty.call(exports, name)) {
  /******/ 				Object.defineProperty(exports, name, { enumerable: true, get: getter });
  /******/ 			}
  /******/ 		};
  /******/ 	}();
  /******/ 	
  /******/ 	/* webpack/runtime/create fake namespace object */
  /******/ 	!function() {
  /******/ 		// create a fake namespace object
  /******/ 		// mode & 1: value is a module id, require it
  /******/ 		// mode & 2: merge all properties of value into the ns
  /******/ 		// mode & 4: return value when already ns object
  /******/ 		// mode & 8|1: behave like require
  /******/ 		__webpack_require__.t = function(value, mode) {
  /******/ 			if(mode & 1) value = this(value);
  /******/ 			if(mode & 8) return value;
  /******/ 			if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
  /******/ 			var ns = Object.create(null);
  /******/ 			__webpack_require__.r(ns);
  /******/ 			Object.defineProperty(ns, 'default', { enumerable: true, value: value });
  /******/ 			if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
  /******/ 			return ns;
  /******/ 		};
  /******/ 	}();
  /******/ 	
  /******/ 	/* webpack/runtime/compat get default export */
  /******/ 	!function() {
  /******/ 		// getDefaultExport function for compatibility with non-harmony modules
  /******/ 		__webpack_require__.n = function(module) {
  /******/ 			var getter = module && module.__esModule ?
  /******/ 				function getDefault() { return module['default']; } :
  /******/ 				function getModuleExports() { return module; };
  /******/ 			__webpack_require__.d(getter, 'a', getter);
  /******/ 			return getter;
  /******/ 		};
  /******/ 	}();
  /******/ 	
  /******/ }
  );