/*!
 * @nuxt/cli v2.15.8 (c) 2016-2021
 * Released under the MIT License
 * Repository: https://github.com/nuxt/nuxt.js
 * Website: https://nuxtjs.org
*/
'use strict';

const utils = require('@nuxt/utils');
const config = require('@nuxt/config');
const path = require('path');
const exit = require('exit');
const chalk = require('chalk');
const env = require('std-env');
const wrapAnsi = require('wrap-ansi');
const boxen = require('boxen');
const consola = require('consola');
const minimist = require('minimist');
const Hookable = require('hable');
const defu = require('defu');
const semver = require('semver');
const fs = require('fs');
const execa = require('execa');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

const path__default = /*#__PURE__*/_interopDefaultLegacy(path);
const exit__default = /*#__PURE__*/_interopDefaultLegacy(exit);
const chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
const env__default = /*#__PURE__*/_interopDefaultLegacy(env);
const wrapAnsi__default = /*#__PURE__*/_interopDefaultLegacy(wrapAnsi);
const boxen__default = /*#__PURE__*/_interopDefaultLegacy(boxen);
const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola);
const minimist__default = /*#__PURE__*/_interopDefaultLegacy(minimist);
const Hookable__default = /*#__PURE__*/_interopDefaultLegacy(Hookable);
const defu__default = /*#__PURE__*/_interopDefaultLegacy(defu);
const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
const execa__default = /*#__PURE__*/_interopDefaultLegacy(execa);

const commands = {
  start: () => Promise.resolve().then(function () { return require('./cli-start.js'); }),
  serve: () => Promise.resolve().then(function () { return require('./cli-serve.js'); }),
  dev: () => Promise.resolve().then(function () { return require('./cli-dev.js'); }),
  build: () => Promise.resolve().then(function () { return require('./cli-build.js'); }),
  generate: () => Promise.resolve().then(function () { return require('./cli-generate.js'); }),
  export: () => Promise.resolve().then(function () { return require('./cli-export.js'); }),
  webpack: () => Promise.resolve().then(function () { return require('./cli-webpack.js'); }),
  help: () => Promise.resolve().then(function () { return require('./cli-help.js'); })
};

function getCommand (name) {
  if (!commands[name]) {
    return Promise.resolve(null)
  }
  return commands[name]().then(m => m.default)
}

const index$1 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  'default': getCommand
});

const importModule = (id) => {
  try {
    return Promise.resolve(utils.requireModule(id))
  } catch (err) {
    if (err.code === 'MODULE_NOT_FOUND') {
      err.message = `Cannot import module '${id}'`;
    }
    return Promise.reject(err)
  }
};

const builder = () => importModule('@nuxt/builder');
const webpack = () => importModule('@nuxt/webpack');
const generator = () => importModule('@nuxt/generator');
const core = () => importModule('@nuxt/core');
const server$1 = () => importModule('@nuxt/server');

const imports = /*#__PURE__*/Object.freeze({
  __proto__: null,
  importModule: importModule,
  builder: builder,
  webpack: webpack,
  generator: generator,
  core: core,
  server: server$1
});

const forceExitTimeout = 5;

const startSpaces = 2;
const optionSpaces = 2;

// 80% of terminal column width
// this is a fn because console width can have changed since startup
const maxCharsPerLine = () => (process.stdout.columns || 100) * 80 / 100;

function indent (count, chr = ' ') {
  return chr.repeat(count)
}

function indentLines (string, spaces, firstLineSpaces) {
  const lines = Array.isArray(string) ? string : string.split('\n');
  let s = '';
  if (lines.length) {
    const i0 = indent(firstLineSpaces === undefined ? spaces : firstLineSpaces);
    s = i0 + lines.shift();
  }
  if (lines.length) {
    const i = indent(spaces);
    s += '\n' + lines.map(l => i + l).join('\n');
  }
  return s
}

function foldLines (string, spaces, firstLineSpaces, charsPerLine = maxCharsPerLine()) {
  return indentLines(wrapAnsi__default['default'](string, charsPerLine), spaces, firstLineSpaces)
}

function colorize (text) {
  return text
    .replace(/\[[^ ]+]/g, m => chalk__default['default'].grey(m))
    .replace(/<[^ ]+>/g, m => chalk__default['default'].green(m))
    .replace(/ (-[-\w,]+)/g, m => chalk__default['default'].bold(m))
    .replace(/`([^`]+)`/g, (_, m) => chalk__default['default'].bold.cyan(m))
}

function box (message, title, options) {
  return boxen__default['default']([
    title || chalk__default['default'].white('Nuxt Message'),
    '',
    chalk__default['default'].white(foldLines(message, 0, 0, maxCharsPerLine()))
  ].join('\n'), Object.assign({
    borderColor: 'white',
    borderStyle: 'round',
    padding: 1,
    margin: 1
  }, options)) + '\n'
}

function successBox (message, title) {
  return box(message, title || chalk__default['default'].green('✔ Nuxt Success'), {
    borderColor: 'green'
  })
}

function warningBox (message, title) {
  return box(message, title || chalk__default['default'].yellow('⚠ Nuxt Warning'), {
    borderColor: 'yellow'
  })
}

function errorBox (message, title) {
  return box(message, title || chalk__default['default'].red('✖ Nuxt Error'), {
    borderColor: 'red'
  })
}

function fatalBox (message, title) {
  return errorBox(message, title || chalk__default['default'].red('✖ Nuxt Fatal Error'))
}

const eventsMapping = {
  add: { icon: '+', color: 'green', action: 'Created' },
  change: { icon: env__default['default'].windows ? '»' : '↻', color: 'blue', action: 'Updated' },
  unlink: { icon: '-', color: 'red', action: 'Removed' }
};

function formatPath (filePath) {
  if (!filePath) {
    return
  }
  return filePath.replace(process.cwd() + path__default['default'].sep, '')
}

/**
 * Normalize string argument in command
 *
 * @export
 * @param {String} argument
 * @param {*} defaultValue
 * @returns formatted argument
 */
function normalizeArg (arg, defaultValue) {
  switch (arg) {
    case 'true': arg = true; break
    case '': arg = true; break
    case 'false': arg = false; break
    case undefined: arg = defaultValue; break
  }
  return arg
}

function forceExit (cmdName, timeout) {
  if (timeout !== false) {
    const exitTimeout = setTimeout(() => {
      const msg = `The command 'nuxt ${cmdName}' finished but did not exit after ${timeout}s
This is most likely not caused by a bug in Nuxt
Make sure to cleanup all timers and listeners you or your plugins/modules start.
Nuxt will now force exit

${chalk__default['default'].bold('DeprecationWarning: Starting with Nuxt version 3 this will be a fatal error')}`;

      // TODO: Change this to a fatal error in v3
      process.stderr.write(warningBox(msg));
      exit__default['default'](0);
    }, timeout * 1000);
    exitTimeout.unref();
  } else {
    exit__default['default'](0);
  }
}

// An immediate export throws an error when mocking with jest
// TypeError: Cannot set property createLock of #<Object> which has only a getter
function createLock (...args) {
  return utils.lock(...args)
}

const common = {
  spa: {
    alias: 's',
    type: 'boolean',
    description: 'Launch in SPA mode'
  },
  universal: {
    alias: 'u',
    type: 'boolean',
    description: 'Launch in Universal mode (default)'
  },
  'config-file': {
    alias: 'c',
    type: 'string',
    default: config.defaultNuxtConfigFile,
    description: `Path to Nuxt config file (default: \`${config.defaultNuxtConfigFile}\`)`
  },
  modern: {
    alias: 'm',
    type: 'string',
    description: 'Build/Start app for modern browsers, e.g. server, client and false',
    prepare (cmd, options, argv) {
      if (argv.modern !== undefined) {
        options.modern = normalizeArg(argv.modern);
      }
    }
  },
  target: {
    alias: 't',
    type: 'string',
    description: 'Build/start app for a different target, e.g. server, serverless and static',
    prepare (cmd, options, argv) {
      if (argv.target) {
        options.target = argv.target;
      }
    }
  },
  'force-exit': {
    type: 'boolean',
    default (cmd) {
      return ['build', 'generate', 'export'].includes(cmd.name)
    },
    description: 'Whether Nuxt should force exit after the command has finished'
  },
  version: {
    alias: 'v',
    type: 'boolean',
    description: 'Display the Nuxt version'
  },
  help: {
    alias: 'h',
    type: 'boolean',
    description: 'Display this message'
  },
  processenv: {
    type: 'boolean',
    default: true,
    description: 'Disable reading from `process.env` and updating it with dotenv'
  },
  dotenv: {
    type: 'string',
    default: '.env',
    description: 'Specify path to dotenv file (default: `.env`). Use `false` to disable'
  }
};

const server = {
  port: {
    alias: 'p',
    type: 'string',
    description: 'Port number on which to start the application',
    prepare (cmd, options, argv) {
      if (argv.port) {
        options.server.port = +argv.port;
      }
    }
  },
  hostname: {
    alias: 'H',
    type: 'string',
    description: 'Hostname on which to start the application',
    prepare (cmd, options, argv) {
      if (argv.hostname === '') {
        consola__default['default'].fatal('Provided hostname argument has no value');
      }
    }
  },
  'unix-socket': {
    alias: 'n',
    type: 'string',
    description: 'Path to a UNIX socket'
  }
};

const locking = {
  lock: {
    type: 'boolean',
    default: true,
    description: 'Do not set a lock on the project when building'
  }
};

const index = /*#__PURE__*/Object.freeze({
  __proto__: null,
  common: common,
  server: server,
  locking: locking
});

var name = "@nuxt/cli";
var version = "2.15.8";

async function loadNuxtConfig (argv, configContext) {
  const rootDir = path__default['default'].resolve(argv._[0] || '.');
  const configFile = argv['config-file'];

  // Load config
  const options = await config.loadNuxtConfig({
    rootDir,
    configFile,
    configContext,
    envConfig: {
      dotenv: argv.dotenv === 'false' ? false : argv.dotenv,
      env: argv.processenv ? process.env : {}
    }
  });

  if (argv.spa === true) {
    options.ssr = false;
  } else if (argv.universal === true) {
    options.ssr = true;
  }

  // Server options
  options.server = defu__default['default']({
    port: argv.port || null,
    host: argv.hostname || null,
    socket: argv['unix-socket'] || null
  }, options.server || {}, config.getDefaultNuxtConfig().server);

  return options
}

class NuxtCommand extends Hookable__default['default'] {
  constructor (cmd = { name: '', usage: '', description: '' }, argv = process.argv.slice(2), hooks = {}) {
    super(consola__default['default']);
    this.addHooks(hooks);

    if (!cmd.options) {
      cmd.options = {};
    }
    this.cmd = cmd;

    this._argv = Array.from(argv);
    this._parsedArgv = null; // Lazy evaluate
  }

  static run (cmd, argv, hooks) {
    return NuxtCommand.from(cmd, argv, hooks).run()
  }

  static from (cmd, argv, hooks) {
    if (cmd instanceof NuxtCommand) {
      return cmd
    }
    return new NuxtCommand(cmd, argv, hooks)
  }

  async run () {
    await this.callHook('run:before', {
      argv: this._argv,
      cmd: this.cmd,
      rootDir: path__default['default'].resolve(this.argv._[0] || '.')
    });

    if (this.argv.help) {
      this.showHelp();
      return
    }

    if (this.argv.version) {
      this.showVersion();
      return
    }

    if (typeof this.cmd.run !== 'function') {
      throw new TypeError('Invalid command! Commands should at least implement run() function.')
    }

    let cmdError;

    try {
      await this.cmd.run(this);
    } catch (e) {
      cmdError = e;
    }

    if (this.argv.lock) {
      await this.releaseLock();
    }

    if (this.argv['force-exit']) {
      const forceExitByUser = this.isUserSuppliedArg('force-exit');
      if (cmdError) {
        consola__default['default'].fatal(cmdError);
      }
      forceExit(this.cmd.name, forceExitByUser ? false : forceExitTimeout);
      if (forceExitByUser) {
        return
      }
    }

    if (cmdError) {
      throw cmdError
    }
  }

  showVersion () {
    process.stdout.write(`${name} v${version}\n`);
  }

  showHelp () {
    process.stdout.write(this._getHelp());
  }

  get argv () {
    if (!this._parsedArgv) {
      const minimistOptions = this._getMinimistOptions();
      this._parsedArgv = minimist__default['default'](this._argv, minimistOptions);
    }
    return this._parsedArgv
  }

  async getNuxtConfig (extraOptions = {}) {
    // Flag to indicate nuxt is running with CLI (not programmatic)
    extraOptions._cli = true;

    const context = {
      command: this.cmd.name,
      dev: !!extraOptions.dev
    };

    const config = await loadNuxtConfig(this.argv, context);
    const options = Object.assign(config, extraOptions);

    for (const name of Object.keys(this.cmd.options)) {
      this.cmd.options[name].prepare && this.cmd.options[name].prepare(this, options, this.argv);
    }

    await this.callHook('config', options);

    return options
  }

  async getNuxt (options) {
    const { Nuxt } = await core();

    const nuxt = new Nuxt(options);
    await nuxt.ready();

    return nuxt
  }

  async getBuilder (nuxt) {
    const { Builder } = await builder();
    const { BundleBuilder } = await webpack();
    return new Builder(nuxt, BundleBuilder)
  }

  async getGenerator (nuxt) {
    const { Generator } = await generator();
    const builder = await this.getBuilder(nuxt);
    return new Generator(nuxt, builder)
  }

  async setLock (lockRelease) {
    if (lockRelease) {
      if (this._lockRelease) {
        consola__default['default'].warn(`A previous unreleased lock was found, this shouldn't happen and is probably an error in 'nuxt ${this.cmd.name}' command. The lock will be removed but be aware of potential strange results`);

        await this.releaseLock();
        this._lockRelease = lockRelease;
      } else {
        this._lockRelease = lockRelease;
      }
    }
  }

  async releaseLock () {
    if (this._lockRelease) {
      await this._lockRelease();
      this._lockRelease = undefined;
    }
  }

  isUserSuppliedArg (option) {
    return this._argv.includes(`--${option}`) || this._argv.includes(`--no-${option}`)
  }

  _getDefaultOptionValue (option) {
    return typeof option.default === 'function' ? option.default(this.cmd) : option.default
  }

  _getMinimistOptions () {
    const minimistOptions = {
      alias: {},
      boolean: [],
      string: [],
      default: {}
    };

    for (const name of Object.keys(this.cmd.options)) {
      const option = this.cmd.options[name];

      if (option.alias) {
        minimistOptions.alias[option.alias] = name;
      }
      if (option.type) {
        minimistOptions[option.type].push(option.alias || name);
      }
      if (option.default) {
        minimistOptions.default[option.alias || name] = this._getDefaultOptionValue(option);
      }
    }

    return minimistOptions
  }

  _getHelp () {
    const options = [];
    let maxOptionLength = 0;

    for (const name in this.cmd.options) {
      const option = this.cmd.options[name];

      let optionHelp = '--';
      optionHelp += option.type === 'boolean' && this._getDefaultOptionValue(option) ? 'no-' : '';
      optionHelp += name;
      if (option.alias) {
        optionHelp += `, -${option.alias}`;
      }

      maxOptionLength = Math.max(maxOptionLength, optionHelp.length);
      options.push([optionHelp, option.description]);
    }

    const _opts = options.map(([option, description]) => {
      const i = indent(maxOptionLength + optionSpaces - option.length);
      return foldLines(
        option + i + description,
        startSpaces + maxOptionLength + optionSpaces * 2,
        startSpaces + optionSpaces
      )
    }).join('\n');

    const usage = foldLines(`Usage: nuxt ${this.cmd.usage} [options]`, startSpaces);
    const description = foldLines(this.cmd.description, startSpaces);
    const opts = foldLines('Options:', startSpaces) + '\n\n' + _opts;

    let helpText = colorize(`${usage}\n\n`);
    if (this.cmd.description) {
      helpText += colorize(`${description}\n\n`);
    }
    if (options.length) {
      helpText += colorize(`${opts}\n\n`);
    }

    return helpText
  }
}

const dependencies = {
  webpack: '^4.46.0',
  'css-loader': '>=4.2.0',
  'sass-loader': '^10.1.1'
};

const nodeVersion = '>=12.0.0';

function getInstalledVersion (name) {
  try {
    return utils.getPKG(name).version
  } catch { }
}

function checkDependencies () {
  for (const name in dependencies) {
    const installedVersion = getInstalledVersion(name);
    if (!installedVersion) {
      continue // Ignore to avoid false-positive warnings
    }
    const expectedRange = dependencies[name];
    if (!semver.satisfies(installedVersion, expectedRange)) {
      consola__default['default'].warn(`${name}@${installedVersion} is installed but ${expectedRange} is expected`);
    }
  }

  // Check Node versions
  if (!semver.satisfies(process.version, nodeVersion)) {
    consola__default['default'].warn(`You are using an unsupported version of Node.js (${process.version}). It is recommended to use the latest LTS version (https://nodejs.org/en/about/releases)`);
  }
}

let _setup = false;

function setup ({ dev }) {
  // Apply default NODE_ENV if not provided
  if (!process.env.NODE_ENV) {
    process.env.NODE_ENV = dev ? 'development' : 'production';
  }

  if (_setup) {
    return
  }
  _setup = true;

  checkDependencies();

  // Global error handler
  /* istanbul ignore next */
  process.on('unhandledRejection', (err) => {
    consola__default['default'].error(err);
  });

  // Exit process on fatal errors
  /* istanbul ignore next */
  consola__default['default'].addReporter({
    log (logObj) {
      if (logObj.type === 'fatal') {
        const errorMessage = String(logObj.args[0]);
        process.stderr.write(fatalBox(errorMessage));
        exit__default['default'](1);
      }
    }
  });

  // Wrap all console logs with consola for better DX
  consola__default['default'].wrapConsole();
}

function isNuxtDir (rootDir) {
  if (fs__default['default'].existsSync(path__default['default'].join(rootDir, 'nuxt.config.js')) ||
    fs__default['default'].existsSync(path__default['default'].join(rootDir, 'pages')) ||
    fs__default['default'].existsSync(path__default['default'].join(rootDir, 'nuxt.config.ts'))) {
    return true
  }
  return false
}

async function run (_argv, hooks = {}) {
  // Check for not installing both nuxt and nuxt-edge
  const dupPkg = 'cli-edge';
  const dupPkgJSON = path.resolve(__dirname, '../..' /* dist/../.. */, dupPkg, 'package.json');
  if (fs.existsSync(dupPkgJSON) && utils.requireModule(dupPkgJSON).name !== '@nuxt/' + dupPkg) {
    consola__default['default'].warn('Both `nuxt` and `nuxt-edge` dependencies are installed! Please choose one and remove the other one from dependencies.');
  }

  // Read from process.argv
  const argv = _argv ? Array.from(_argv) : process.argv.slice(2);

  // Check for internal command
  let cmd = await getCommand(argv[0]);

  // Matching `nuxt` or `nuxt [dir]` or `nuxt -*` for `nuxt dev` shortcut
  if (!cmd && (!argv[0] || argv[0][0] === '-' || isNuxtDir(argv[0]))) {
    argv.unshift('dev');
    cmd = await getCommand('dev');
  }

  // Check for dev
  const dev = argv[0] === 'dev';

  // Setup env
  setup({ dev });

  // Try internal command
  if (cmd) {
    return NuxtCommand.run(cmd, argv.slice(1), hooks)
  }

  // Try external command
  try {
    await execa__default['default'](`nuxt-${argv[0]}`, argv.slice(1), {
      stdout: process.stdout,
      stderr: process.stderr,
      stdin: process.stdin
    });
  } catch (error) {
    if (error.exitCode === 2) {
      throw String(`Command not found: nuxt-${argv[0]}`)
    }
    throw String(`Failed to run command \`nuxt-${argv[0]}\`:\n${error}`)
  }
}

async function getWebpackConfig (name = 'client', loadOptions = {}) {
  const { loadNuxt } = await core();
  const { getBuilder } = await builder();

  const nuxt = await loadNuxt(loadOptions);
  const builder$1 = await getBuilder(nuxt);
  const { bundleBuilder } = builder$1;
  return bundleBuilder.getWebpackConfig(name)
}

exports.NuxtCommand = NuxtCommand;
exports.colorize = colorize;
exports.common = common;
exports.core = core;
exports.createLock = createLock;
exports.eventsMapping = eventsMapping;
exports.foldLines = foldLines;
exports.formatPath = formatPath;
exports.getCommand = getCommand;
exports.getWebpackConfig = getWebpackConfig;
exports.imports = imports;
exports.indent = indent;
exports.index = index$1;
exports.index$1 = index;
exports.isNuxtDir = isNuxtDir;
exports.loadNuxtConfig = loadNuxtConfig;
exports.locking = locking;
exports.normalizeArg = normalizeArg;
exports.optionSpaces = optionSpaces;
exports.run = run;
exports.server = server$1;
exports.server$1 = server;
exports.setup = setup;
exports.startSpaces = startSpaces;
exports.successBox = successBox;
