"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = dev;

function _react() {
  const data = _interopRequireDefault(require("react"));

  _react = function _react() {
    return data;
  };

  return data;
}

function _fs() {
  const data = _interopRequireDefault(require("fs"));

  _fs = function _fs() {
    return data;
  };

  return data;
}

function _openBrowser() {
  const data = _interopRequireDefault(require("react-dev-utils/openBrowser"));

  _openBrowser = function _openBrowser() {
    return data;
  };

  return data;
}

function _webpack() {
  const data = _interopRequireDefault(require("webpack"));

  _webpack = function _webpack() {
    return data;
  };

  return data;
}

function _assert() {
  const data = _interopRequireDefault(require("assert"));

  _assert = function _assert() {
    return data;
  };

  return data;
}

function _webpackDevServer() {
  const data = _interopRequireDefault(require("webpack-dev-server"));

  _webpackDevServer = function _webpackDevServer() {
    return data;
  };

  return data;
}

function _chalk() {
  const data = _interopRequireDefault(require("chalk"));

  _chalk = function _chalk() {
    return data;
  };

  return data;
}

function _lodash() {
  const data = require("lodash");

  _lodash = function _lodash() {
    return data;
  };

  return data;
}

var _prepareUrls = _interopRequireDefault(require("./prepareUrls"));

var _clearConsole = _interopRequireDefault(require("./clearConsole"));

var _errorOverlayMiddleware = _interopRequireDefault(require("./errorOverlayMiddleware"));

var _send = _interopRequireWildcard(require("./send"));

function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

const isInteractive = process.stdout.isTTY;
const HOST = process.env.HOST || '0.0.0.0';
const PROTOCOL = process.env.HTTPS ? 'https' : 'http';
const CERT = process.env.HTTPS && process.env.CERT ? _fs().default.readFileSync(process.env.CERT) : '';
const KEY = process.env.HTTPS && process.env.KEY ? _fs().default.readFileSync(process.env.KEY) : '';

const noop = () => {};

process.env.NODE_ENV = 'development';

function getWebpackConfig(webpackConfig) {
  return Array.isArray(webpackConfig) ? webpackConfig[0] : webpackConfig;
}

function dev({
  webpackConfig,
  _beforeServerWithApp,
  beforeMiddlewares,
  afterMiddlewares,
  beforeServer,
  afterServer,
  contentBase,
  onCompileDone = noop,
  onFail = noop,
  proxy,
  port,
  history,
  base,
  serverConfig: serverConfigFromOpts = {}
}) {
  (0, _assert().default)(webpackConfig, 'webpackConfig should be supplied.');
  (0, _assert().default)((0, _lodash().isPlainObject)(webpackConfig) || Array.isArray(webpackConfig), 'webpackConfig should be plain object or array.');
  (0, _assert().default)(port, `port should be passed, but got ${port}`); // Send message to parent process when port choosed

  process.send({
    type: 'UPDATE_PORT',
    port
  });
  const compiler = (0, _webpack().default)(webpackConfig);
  let server = null;
  let isFirstCompile = true;
  const IS_CI = !!process.env.CI;
  const SILENT = !!process.env.SILENT;
  const urls = (0, _prepareUrls.default)(PROTOCOL, HOST, port, base, history);
  compiler.hooks.done.tap('af-webpack done', stats => {
    if (stats.hasErrors()) {
      // make sound
      // ref: https://github.com/JannesMeyer/system-bell-webpack-plugin/blob/bb35caf/SystemBellPlugin.js#L14
      if (process.env.SYSTEM_BELL !== 'none') {
        process.stdout.write('\x07');
      }

      (0, _send.default)({
        type: _send.ERROR
      });
      onFail({
        stats
      });
      return;
    }

    let copied = '';

    if (isFirstCompile && !IS_CI && !SILENT) {
      try {
        require('clipboardy').writeSync(urls.localUrlForBrowser);

        copied = _chalk().default.dim('(copied to clipboard)');
      } catch (e) {
        copied = _chalk().default.red(`(copy to clipboard failed)`);
      }

      console.log();
      console.log([`  App running at:`, `  - Local:   ${_chalk().default.cyan(urls.localUrlForTerminal)} ${copied}`, urls.lanUrlForTerminal ? `  - Network: ${_chalk().default.cyan(urls.lanUrlForTerminal)}` : ''].join('\n'));
      console.log();
    }

    const exportedUrls = {
      local: urls.localUrlForTerminal,
      lan: urls.lanUrlForTerminal,
      rawLocal: urls.localUrlForBrowser,
      rawLanUrl: urls.rawLanUrl
    };
    onCompileDone({
      port,
      isFirstCompile,
      stats,
      server,
      urls: exportedUrls
    });

    if (isFirstCompile) {
      isFirstCompile = false;
      (0, _openBrowser().default)(urls.localUrlForBrowser);
      (0, _send.default)({
        type: _send.DONE,
        urls: exportedUrls
      });
    }
  });

  const serverConfig = _objectSpread({
    disableHostCheck: true,
    compress: true,
    clientLogLevel: 'none',
    hot: true,
    quiet: true,
    headers: {
      'access-control-allow-origin': '*'
    },
    publicPath: getWebpackConfig(webpackConfig).output.publicPath,
    watchOptions: {
      ignored: /node_modules/
    },
    historyApiFallback: false,
    overlay: false,
    host: HOST,
    proxy,
    https: !!process.env.HTTPS,
    cert: CERT,
    key: KEY,
    contentBase: contentBase || process.env.CONTENT_BASE,

    before(app) {
      (beforeMiddlewares || []).forEach(middleware => {
        app.use(middleware);
      }); // internal usage for proxy

      if (_beforeServerWithApp) {
        _beforeServerWithApp(app);
      }

      app.use((0, _errorOverlayMiddleware.default)());
    },

    after(app) {
      (afterMiddlewares || []).forEach(middleware => {
        app.use(middleware);
      });
    }

  }, serverConfigFromOpts, {}, getWebpackConfig(webpackConfig).devServer || {});

  server = new (_webpackDevServer().default)(compiler, serverConfig);
  ['SIGINT', 'SIGTERM'].forEach(signal => {
    process.on(signal, () => {
      server.close(() => {
        process.exit(0);
      });
    });
  });

  if (beforeServer) {
    beforeServer(server);
  }

  server.listen(port, HOST, err => {
    if (err) {
      console.log(err);
      return;
    }

    if (isInteractive) {
      (0, _clearConsole.default)();
    }

    console.log(_chalk().default.cyan('Starting the development server...\n'));
    (0, _send.default)({
      type: _send.STARTING
    });

    if (afterServer) {
      afterServer(server, port);
    }
  });
}