"use strict";

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

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

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

  return data;
}

function _path() {
  const data = require("path");

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

  return data;
}

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

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

  return data;
}

function _execa() {
  const data = _interopRequireDefault(require("execa"));

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

  return data;
}

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

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

  return data;
}

function _sortPackageJson() {
  const data = _interopRequireDefault(require("sort-package-json"));

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

  return data;
}

var _getBlockGenerator = require("./getBlockGenerator");

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

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

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; }

/**
 * 依赖从数组转化为对象
 * @param {*} templateTmpDirPath
 */
const depsArrayToObject = loc => loc.map(dep => {
  return {
    [dep[0]]: dep[1]
  };
}).reduce((pre, next) => {
  return _objectSpread({}, pre, {}, next);
}, {});
/**
 * 安装依赖包
 * - 获取项目路径
 * - 递归获得依赖项。
 * - 调用 npm 来合并安装依赖项
 * @param {*} param0
 * @param {*} ctx
 */


function installDependencies(_x, _x2) {
  return _installDependencies.apply(this, arguments);
}

function _installDependencies() {
  _installDependencies = _asyncToGenerator(function* ({
    npmClient,
    registry,
    applyPlugins,
    paths,
    debug,
    dryRun,
    spinner,
    skipDependencies,
    execa: selfExeca
  }, ctx) {
    const exec = selfExeca || _execa().default; // read project package.json


    const projectPkgPath = applyPlugins('_modifyBlockPackageJSONPath', {
      initialValue: (0, _path().join)(paths.cwd, 'package.json')
    }); // 判断 package.json 是否存在

    (0, _assert().default)((0, _fs().existsSync)(projectPkgPath), `No package.json found in your project`); // eslint-disable-next-line

    const projectPkg = require(projectPkgPath); // get _mock.js dependencie


    let devDependencies = {};
    const mockFilePath = (0, _path().join)(ctx.sourcePath, 'src/_mock.js');

    if ((0, _fs().existsSync)(mockFilePath)) {
      devDependencies = (0, _getBlockGenerator.getMockDependencies)((0, _fs().readFileSync)(mockFilePath, 'utf-8'), ctx.pkg);
    }

    const allBlockDependencies = (0, _getBlockGenerator.getAllBlockDependencies)(ctx.templateTmpDirPath, ctx.pkg); // 构造 _modifyBlockDependencies 的执行参数

    const initialValue = (0, _getBlockGenerator.dependenciesConflictCheck)(allBlockDependencies, projectPkg.dependencies, devDependencies, _objectSpread({}, projectPkg.devDependencies, {}, projectPkg.dependencies)); // get conflict dependencies and lack dependencies

    const _applyPlugins = applyPlugins('_modifyBlockDependencies', {
      initialValue
    }),
          conflicts = _applyPlugins.conflicts,
          lacks = _applyPlugins.lacks,
          devConflicts = _applyPlugins.devConflicts,
          devLacks = _applyPlugins.devLacks;

    debug(`conflictDeps ${conflicts}, lackDeps ${lacks}`, `devConflictDeps ${devConflicts}, devLackDeps ${devLacks}`); // find conflict dependencies throw error

    const allConflicts = [...conflicts, ...devConflicts];
    const ErrorInfo = allConflicts.map(info => {
      return `* ${info[0]}: ${info[2]}(your project) not compatible with ${info[1]}(block)`;
    }).join('\n'); // 如果有冲突，抛出错误流程结束。

    if (allConflicts.length) {
      throw new Error(`find dependencies conflict between block and your project:${ErrorInfo}`);
    } // find lack conflict, auto install


    if (dryRun) {
      debug('dryRun is true, skip install dependencies');
      return;
    }

    if (skipDependencies) {
      // 中间层转化
      // [["react","16.5"]] => {"react":16.5}
      const dependencies = depsArrayToObject(lacks);
      const devDependencies = depsArrayToObject(devLacks); // 格式化 package.json

      const content = JSON.stringify((0, _sortPackageJson().default)(_objectSpread({}, projectPkg, {
        dependencies: _objectSpread({}, dependencies, {}, projectPkg.dependencies),
        devDependencies: _objectSpread({}, devDependencies, {}, projectPkg.devDependencies)
      })), null, 2); // 写入文件

      (0, _fs().writeFileSync)(projectPkgPath, content);
      return;
    } // 安装依赖


    if (lacks.length) {
      const deps = lacks.map(dep => `${dep[0]}@${dep[1]}`);
      spinner.start(`📦  Install additional dependencies ${deps.join(',')} with ${npmClient} --registry ${registry}`);

      try {
        let npmArgs = npmClient.includes('yarn') ? ['add'] : ['install', '-d'];
        npmArgs = [...npmArgs, ...deps, `--registry=${registry}`]; // 安装区块的时候不需要安装 puppeteer, 因为 yarn 会全量安装一次所有依赖。
        // 加个环境变量规避一下

        yield exec(npmClient, npmClient.includes('yarn') ? npmArgs : [...npmArgs, '--save'], {
          cwd: (0, _path().dirname)(projectPkgPath),
          env: _objectSpread({}, process.env, {
            // ref  https://github.com/GoogleChrome/puppeteer/blob/411347cd7bb03edacf0854760712d32b0d9ba68f/docs/api.md#environment-variables
            PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
          })
        });
      } catch (e) {
        spinner.fail();
        throw new Error(e);
      }

      spinner.succeed();
    } // 安装 dev 依赖


    if (devLacks.length) {
      // need skip devDependency which already install in dependencies
      const devDeps = devLacks.filter(dep => !lacks.find(item => item[0] === dep[0])).map(dep => `${dep[0]}@${dep[1]}`);
      spinner.start(`Install additional devDependencies ${devDeps.join(',')} with ${npmClient}  --registry ${registry}`);

      try {
        let npmArgs = npmClient.includes('yarn') ? ['add'] : ['install'];
        npmArgs = [...npmArgs, ...devDeps, `--registry=${registry}`];
        yield exec(npmClient, npmClient.includes('yarn') ? npmArgs : [...npmArgs, '--save-dev'], {
          cwd: (0, _path().dirname)(projectPkgPath)
        });
      } catch (e) {
        spinner.fail();
        throw new Error(e);
      }

      spinner.succeed();
    }
  });
  return _installDependencies.apply(this, arguments);
}

var _default = installDependencies;
exports.default = _default;