Function.prototype.$asyncbind = function $asyncbind(self, catcher) {
  "use strict";

  if (!Function.prototype.$asyncbind) {
    Object.defineProperty(Function.prototype, "$asyncbind", {
      value: $asyncbind,
      enumerable: false,
      configurable: true,
      writable: true
    });
  }

  if (!$asyncbind.trampoline) {
    $asyncbind.trampoline = function trampoline(t, x, s, e, u) {
      return function b(q) {
        while (q) {
          if (q.then) {
            q = q.then(b, e);
            return u ? undefined : q;
          }

          try {
            if (q.pop) {
              if (q.length) return q.pop() ? x.call(t) : q;
              q = s;
            } else q = q.call(t);
          } catch (r) {
            return e(r);
          }
        }
      };
    };
  }

  if (!$asyncbind.LazyThenable) {
    $asyncbind.LazyThenable = function () {
      function isThenable(obj) {
        return obj && obj instanceof Object && typeof obj.then === "function";
      }

      function resolution(p, r, how) {
        try {
          var x = how ? how(r) : r;
          if (p === x) return p.reject(new TypeError("Promise resolution loop"));

          if (isThenable(x)) {
            x.then(function (y) {
              resolution(p, y);
            }, function (e) {
              p.reject(e);
            });
          } else {
            p.resolve(x);
          }
        } catch (ex) {
          p.reject(ex);
        }
      }

      function Chained() {}

      ;
      Chained.prototype = {
        resolve: _unchained,
        reject: _unchained,
        then: thenChain
      };

      function _unchained(v) {}

      function thenChain(res, rej) {
        this.resolve = res;
        this.reject = rej;
      }

      function then(res, rej) {
        var chain = new Chained();

        try {
          this._resolver(function (value) {
            return isThenable(value) ? value.then(res, rej) : resolution(chain, value, res);
          }, function (ex) {
            resolution(chain, ex, rej);
          });
        } catch (ex) {
          resolution(chain, ex, rej);
        }

        return chain;
      }

      function Thenable(resolver) {
        this._resolver = resolver;
        this.then = then;
      }

      ;

      Thenable.resolve = function (v) {
        return Thenable.isThenable(v) ? v : {
          then: function then(resolve) {
            return resolve(v);
          }
        };
      };

      Thenable.isThenable = isThenable;
      return Thenable;
    }();

    $asyncbind.EagerThenable = $asyncbind.Thenable = ($asyncbind.EagerThenableFactory = function (tick) {
      tick = tick || typeof process === "object" && process.nextTick || typeof setImmediate === "function" && setImmediate || function (f) {
        setTimeout(f, 0);
      };

      var soon = function () {
        var fq = [],
            fqStart = 0,
            bufferSize = 1024;

        function callQueue() {
          while (fq.length - fqStart) {
            try {
              fq[fqStart]();
            } catch (ex) {}

            fq[fqStart++] = undefined;

            if (fqStart === bufferSize) {
              fq.splice(0, bufferSize);
              fqStart = 0;
            }
          }
        }

        return function (fn) {
          fq.push(fn);
          if (fq.length - fqStart === 1) tick(callQueue);
        };
      }();

      function Zousan(func) {
        if (func) {
          var me = this;
          func(function (arg) {
            me.resolve(arg);
          }, function (arg) {
            me.reject(arg);
          });
        }
      }

      Zousan.prototype = {
        resolve: function resolve(value) {
          if (this.state !== undefined) return;
          if (value === this) return this.reject(new TypeError("Attempt to resolve promise with self"));
          var me = this;

          if (value && (typeof value === "function" || typeof value === "object")) {
            try {
              var first = 0;
              var then = value.then;

              if (typeof then === "function") {
                then.call(value, function (ra) {
                  if (!first++) {
                    me.resolve(ra);
                  }
                }, function (rr) {
                  if (!first++) {
                    me.reject(rr);
                  }
                });
                return;
              }
            } catch (e) {
              if (!first) this.reject(e);
              return;
            }
          }

          this.state = STATE_FULFILLED;
          this.v = value;
          if (me.c) soon(function () {
            for (var n = 0, l = me.c.length; n < l; n++) STATE_FULFILLED(me.c[n], value);
          });
        },
        reject: function reject(reason) {
          if (this.state !== undefined) return;
          this.state = STATE_REJECTED;
          this.v = reason;
          var clients = this.c;
          if (clients) soon(function () {
            for (var n = 0, l = clients.length; n < l; n++) STATE_REJECTED(clients[n], reason);
          });
        },
        then: function then(onF, onR) {
          var p = new Zousan();
          var client = {
            y: onF,
            n: onR,
            p: p
          };

          if (this.state === undefined) {
            if (this.c) this.c.push(client);else this.c = [client];
          } else {
            var s = this.state,
                a = this.v;
            soon(function () {
              s(client, a);
            });
          }

          return p;
        }
      };

      function STATE_FULFILLED(c, arg) {
        if (typeof c.y === "function") {
          try {
            var yret = c.y.call(undefined, arg);
            c.p.resolve(yret);
          } catch (err) {
            c.p.reject(err);
          }
        } else c.p.resolve(arg);
      }

      function STATE_REJECTED(c, reason) {
        if (typeof c.n === "function") {
          try {
            var yret = c.n.call(undefined, reason);
            c.p.resolve(yret);
          } catch (err) {
            c.p.reject(err);
          }
        } else c.p.reject(reason);
      }

      Zousan.resolve = function (val) {
        if (val && val instanceof Zousan) return val;
        var z = new Zousan();
        z.resolve(val);
        return z;
      };

      Zousan.reject = function (err) {
        if (err && err instanceof Zousan) return err;
        var z = new Zousan();
        z.reject(err);
        return z;
      };

      Zousan.version = "2.3.3-nodent";
      return Zousan;
    })();
  }

  var resolver = this;

  switch (catcher) {
    case true:
      return new $asyncbind.Thenable(boundThen);

    case 0:
      return new $asyncbind.LazyThenable(boundThen);

    case undefined:
      boundThen.then = boundThen;
      return boundThen;

    default:
      return function () {
        try {
          return resolver.apply(self, arguments);
        } catch (ex) {
          return catcher(ex);
        }
      };
  }

  function boundThen() {
    return resolver.apply(self, arguments);
  }
};

const path = require("path");

const ora = require("ora");

const execa = require("execa");

const createDefault = require("@patternplate/create-default");

const sander = require("@marionebl/sander");

const MemoryFilesystem = require("memory-fs");

const importFrom = require("import-from");

const resolveFrom = require("resolve-from");

const resolvePkg = require("resolve-pkg");

const commandExists = require("command-exists");

module.exports = create;
const INSTALLERS = ["yarn", "npm"];

function create({
  flags,
  pkg
}) {
  return new Promise(function ($return, $error) {
    var resolved, self, cwd, rel, template, spinner, installer, data, fs, target;

    if (typeof flags.out !== "string") {
      return $error(error("create: --out flag is required"));
    }

    resolved = resolvePkg("@patternplate/cli");
    self = typeof resolved === "string" ? resolved : path.dirname(__dirname);
    cwd = flags.cwd || process.cwd();
    rel = path.relative(cwd, path.resolve(cwd, flags.out));
    template = typeof flags.template === "string" ? importFrom(cwd, templateId) : createDefault;
    spinner = ora(`Creating patternplate project at "${rel}"`);

    if (typeof template !== "function") {
      return $error(error(`create: template "${templateId}" is not a function.`));
    }

    return new Promise(function ($return, $error) {
      var $logicalAnd_1;

      if ($logicalAnd_1 = !flags.force) {
        return sander.exists(cwd, flags.out).then(function ($await_8) {
          $logicalAnd_1 = $await_8;
          return $If_3.call(this);
        }.$asyncbind(this, $error), $error);
      }

      function $If_3() {
        return $return($logicalAnd_1);
      }

      return $If_3.call(this);
    }.$asyncbind(this)).then(function ($await_9) {
      if ($await_9) {
        return $error(error(`create: target "${flags.out}" already exists at "${rel}", aborting.`));
      }

      return Promise.all(INSTALLERS.map(i => commandExists(i))).then(function ($await_10) {
        installer = $await_10.filter(Boolean)[0];

        if (flags.install !== false) {
          if (!installer) {
            return $error(error(`No compatible installer found, one of the following must be installed: ${INSTALLERS.join(", ")}`));
          }
        }

        spinner.start();
        return new Promise(function ($return, $error) {
          var $logicalAnd_2;

          if ($logicalAnd_2 = flags.force) {
            return sander.exists(cwd, flags.out).then(function ($await_11) {
              $logicalAnd_2 = $await_11;
              return $If_7.call(this);
            }.$asyncbind(this, $error), $error);
          }

          function $If_7() {
            return $return($logicalAnd_2);
          }

          return $If_7.call(this);
        }.$asyncbind(this)).then(function ($await_12) {
          if ($await_12) {
            return sander.rimraf(cwd, flags.out).then(function ($await_13) {
              return $If_4.call(this);
            }.$asyncbind(this, $error), $error);
          }

          function $If_4() {
            return sander.mkdir(cwd, flags.out).then(function ($await_14) {
              data = {
                name: path.basename(flags.out),
                cliVersion: pkg.version
              };
              fs = template(data, new MemoryFilesystem());
              target = path.join(cwd, flags.out);
              return dump(fs, "/", target).then(function ($await_15) {
                spinner.succeed(`Created patternplate project at "${rel}"`);

                if (flags.git !== false) {
                  return execa("git", ["init"], {
                    cwd: target
                  }).then(function ($await_16) {
                    return $If_5.call(this);
                  }.$asyncbind(this, $error), $error);
                }

                function $If_5() {
                  if (flags.install !== false) {
                    spinner.text = `Installing dependencies via ${installer}`;
                    spinner.start();
                    return execa("npm", ["install"], {
                      cwd: target
                    }).then(function ($await_17) {
                      spinner.succeed(`Installed dependencies via ${installer}`);
                      return $If_6.call(this);
                    }.$asyncbind(this, $error), $error);
                  }

                  function $If_6() {
                    if (flags.guide !== true) {
                      console.log(`\nProceed via`);
                      console.log(`- cd ${rel}`);

                      if (flags.install === false) {
                        console.log(`- ${installer} install`);
                      }

                      console.log(`- ${installer} start`);
                    } else {
                      console.log(`Head back to https://git.io/vxeY1 for further instructions`);
                    }

                    return $return();
                  }

                  return $If_6.call(this);
                }

                return $If_5.call(this);
              }.$asyncbind(this, $error), $error);
            }.$asyncbind(this, $error), $error);
          }

          return $If_4.call(this);
        }.$asyncbind(this, $error), $error);
      }.$asyncbind(this, $error), $error);
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}

function error(message) {
  const err = new Error(message);
  err.patternplate = true;
  return err;
}

function dump(fs, base, target) {
  return new Promise(function ($return, $error) {
    const files = list(fs, base);
    return $return(Promise.all(files.map(file => new Promise(function ($return, $error) {
      sander.writeFile(target, file.slice(1), fs.readFileSync(file));
      return $return();
    }.$asyncbind(this)))));
  }.$asyncbind(this));
}

function list(fs, base) {
  return fs.readdirSync(base).reduce((acc, name) => {
    const p = path.join(base, name);
    const stat = fs.statSync(p);

    if (stat.isFile()) {
      acc.push(p);
    } else {
      acc = acc.concat(list(fs, p));
    }

    return acc;
  }, []);
}
//# sourceMappingURL=index.js.map