"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.addComponentsToRoot = addComponentsToRoot;
exports.addComponentsWithVersionToRoot = addComponentsWithVersionToRoot;
exports.changeDependenciesToRelativeSyntax = changeDependenciesToRelativeSyntax;
exports.write = write;
exports.preparePackageJsonToWrite = preparePackageJsonToWrite;
exports.updateAttribute = updateAttribute;
exports.addWorkspacesToPackageJson = addWorkspacesToPackageJson;
exports.removeComponentsFromWorkspacesAndDependencies = removeComponentsFromWorkspacesAndDependencies;
exports.convertToValidPathForPackageManager = convertToValidPathForPackageManager;

function _objectSpread2() {
  const data = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));

  _objectSpread2 = function () {
    return data;
  };

  return data;
}

function _bluebird() {
  const data = require("bluebird");

  _bluebird = function () {
    return data;
  };

  return data;
}

function _ramda() {
  const data = _interopRequireDefault(require("ramda"));

  _ramda = function () {
    return data;
  };

  return data;
}

function _fsExtra() {
  const data = _interopRequireDefault(require("fs-extra"));

  _fsExtra = function () {
    return data;
  };

  return data;
}

function _bitId() {
  const data = require("../../bit-id");

  _bitId = function () {
    return data;
  };

  return data;
}

function _constants() {
  const data = require("../../constants");

  _constants = function () {
    return data;
  };

  return data;
}

function _componentMap() {
  const data = _interopRequireDefault(require("../bit-map/component-map"));

  _componentMap = function () {
    return data;
  };

  return data;
}

function _utils() {
  const data = require("../../utils");

  _utils = function () {
    return data;
  };

  return data;
}

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

  _path = function () {
    return data;
  };

  return data;
}

function _componentNodeModulesPath() {
  const data = _interopRequireDefault(require("../../utils/bit/component-node-modules-path"));

  _componentNodeModulesPath = function () {
    return data;
  };

  return data;
}

function _logger() {
  const data = _interopRequireDefault(require("../../logger/logger"));

  _logger = function () {
    return data;
  };

  return data;
}

function _generalError() {
  const data = _interopRequireDefault(require("../../error/general-error"));

  _generalError = function () {
    return data;
  };

  return data;
}

function _jsonFile() {
  const data = _interopRequireDefault(require("./sources/json-file"));

  _jsonFile = function () {
    return data;
  };

  return data;
}

function _npmRegistryName() {
  const data = _interopRequireDefault(require("../../utils/bit/npm-registry-name"));

  _npmRegistryName = function () {
    return data;
  };

  return data;
}

function _componentIdToPackageName() {
  const data = _interopRequireDefault(require("../../utils/bit/component-id-to-package-name"));

  _componentIdToPackageName = function () {
    return data;
  };

  return data;
}

function _packageJsonFile() {
  const data = _interopRequireDefault(require("./package-json-file"));

  _packageJsonFile = function () {
    return data;
  };

  return data;
}

function _searchFilesIgnoreExt() {
  const data = _interopRequireDefault(require("../../utils/fs/search-files-ignore-ext"));

  _searchFilesIgnoreExt = function () {
    return data;
  };

  return data;
}

function _componentVersion() {
  const data = _interopRequireDefault(require("../../scope/component-version"));

  _componentVersion = function () {
    return data;
  };

  return data;
}

/**
 * Add components as dependencies to root package.json
 */
function addComponentsToRoot(_x, _x2) {
  return _addComponentsToRoot.apply(this, arguments);
}
/**
 * Add given components with their versions to root package.json
 */


function _addComponentsToRoot() {
  _addComponentsToRoot = (0, _bluebird().coroutine)(function* (consumer, components) {
    const componentsToAdd = components.reduce((acc, component) => {
      const componentMap = consumer.bitMap.getComponent(component.id);
      if (componentMap.origin !== _constants().COMPONENT_ORIGINS.IMPORTED) return acc;

      if (!componentMap.rootDir) {
        throw new (_generalError().default)(`rootDir is missing from an imported component ${component.id.toString()}`);
      }

      const locationAsUnixFormat = convertToValidPathForPackageManager(componentMap.rootDir);
      const packageName = (0, _componentIdToPackageName().default)(component.id, component.bindingPrefix);
      acc[packageName] = locationAsUnixFormat;
      return acc;
    }, {});
    if (_ramda().default.isEmpty(componentsToAdd)) return;
    yield _addDependenciesPackagesIntoPackageJson(consumer.getPath(), componentsToAdd);
  });
  return _addComponentsToRoot.apply(this, arguments);
}

function addComponentsWithVersionToRoot(_x3, _x4) {
  return _addComponentsWithVersionToRoot.apply(this, arguments);
}

function _addComponentsWithVersionToRoot() {
  _addComponentsWithVersionToRoot = (0, _bluebird().coroutine)(function* (consumer, componentsVersions) {
    const componentsToAdd = _ramda().default.fromPairs(componentsVersions.map(({
      component,
      version
    }) => {
      const packageName = (0, _componentIdToPackageName().default)(component.toBitId(), component.bindingPrefix);
      return [packageName, version];
    }));

    yield _addDependenciesPackagesIntoPackageJson(consumer.getPath(), componentsToAdd);
  });
  return _addComponentsWithVersionToRoot.apply(this, arguments);
}

function changeDependenciesToRelativeSyntax(_x5, _x6, _x7) {
  return _changeDependenciesToRelativeSyntax.apply(this, arguments);
}

function _changeDependenciesToRelativeSyntax() {
  _changeDependenciesToRelativeSyntax = (0, _bluebird().coroutine)(function* (consumer, components, dependencies) {
    const dependenciesIds = _bitId().BitIds.fromArray(dependencies.map(dependency => dependency.id));

    const updateComponentPackageJson =
    /*#__PURE__*/
    function () {
      var _ref = (0, _bluebird().coroutine)(function* (component) {
        const componentMap = consumer.bitMap.getComponent(component.id);
        const componentRootDir = componentMap.rootDir;
        if (!componentRootDir) return null;
        const packageJsonFile = yield _packageJsonFile().default.load(consumer.getPath(), componentRootDir);
        if (!packageJsonFile.fileExist) return null; // if package.json doesn't exist no need to update anything

        const devDeps = getPackages(component.devDependencies, componentMap);
        const compilerDeps = getPackages(component.compilerDependencies, componentMap);
        const testerDeps = getPackages(component.testerDependencies, componentMap);
        packageJsonFile.addDependencies(getPackages(component.dependencies, componentMap));
        packageJsonFile.addDevDependencies((0, _objectSpread2().default)({}, devDeps, compilerDeps, testerDeps));
        return packageJsonFile.toVinylFile();
      });

      return function updateComponentPackageJson(_x23) {
        return _ref.apply(this, arguments);
      };
    }();

    const packageJsonFiles = yield Promise.all(components.map(component => updateComponentPackageJson(component))); // $FlowFixMe

    return packageJsonFiles.filter(file => file);

    function getPackages(deps, componentMap) {
      return deps.get().reduce((acc, dependency) => {
        const dependencyId = dependency.id.toStringWithoutVersion();

        if (dependenciesIds.searchWithoutVersion(dependency.id)) {
          const dependencyComponent = dependencies.find(d => d.id.isEqualWithoutVersion(dependency.id));

          if (!dependencyComponent) {
            throw new Error('getDependenciesAsPackages, dependencyComponent is missing');
          }

          const dependencyComponentMap = consumer.bitMap.getComponentIfExist(dependencyComponent.id);
          const dependencyPackageValue = getPackageDependencyValue(dependencyId, componentMap, dependencyComponentMap);

          if (dependencyPackageValue) {
            const packageName = (0, _componentIdToPackageName().default)(dependency.id, dependencyComponent.bindingPrefix || (0, _npmRegistryName().default)());
            acc[packageName] = dependencyPackageValue;
          }
        }

        return acc;
      }, {});
    }
  });
  return _changeDependenciesToRelativeSyntax.apply(this, arguments);
}

function write(_x8, _x9, _x10) {
  return _write.apply(this, arguments);
}

function _write() {
  _write = (0, _bluebird().coroutine)(function* (consumer, component, bitDir, writeBitDependencies = false, excludeRegistryPrefix) {
    const {
      packageJson,
      distPackageJson
    } = preparePackageJsonToWrite(consumer, component, bitDir, writeBitDependencies, excludeRegistryPrefix);
    yield packageJson.write();
    if (distPackageJson) yield distPackageJson.write();
    return packageJson;
  });
  return _write.apply(this, arguments);
}

function preparePackageJsonToWrite(consumer, component, bitDir, override = true, writeBitDependencies = false, excludeRegistryPrefix) {
  _logger().default.debug(`package-json.preparePackageJsonToWrite. bitDir ${bitDir}. override ${override.toString()}`);

  const getBitDependencies = dependencies => {
    if (!writeBitDependencies) return {};
    return dependencies.get().reduce((acc, dep) => {
      const packageDependency = consumer ? getPackageDependency(consumer, dep.id, component.id) : null;
      const packageName = (0, _componentIdToPackageName().default)(dep.id, component.bindingPrefix || (0, _npmRegistryName().default)());
      acc[packageName] = packageDependency;
      return acc;
    }, {});
  };

  const addDependencies = packageJsonFile => {
    packageJsonFile.addDependencies(bitDependencies);
    packageJsonFile.addDevDependencies((0, _objectSpread2().default)({}, bitDevDependencies, bitCompilerDependencies, bitTesterDependencies));
  };

  const bitDependencies = getBitDependencies(component.dependencies);
  const bitDevDependencies = getBitDependencies(component.devDependencies);
  const bitCompilerDependencies = getBitDependencies(component.compilerDependencies);
  const bitTesterDependencies = getBitDependencies(component.testerDependencies);

  const packageJson = _packageJsonFile().default.createFromComponent(bitDir, component, excludeRegistryPrefix);

  const main = (0, _path().pathNormalizeToLinux)(component.dists.calculateMainDistFile(component.mainFile));
  packageJson.addOrUpdateProperty('main', main);
  addDependencies(packageJson);
  let distPackageJson;

  if (!component.dists.isEmpty() && !component.dists.areDistsInsideComponentDir) {
    const distRootDir = component.dists.distsRootDir;
    if (!distRootDir) throw new (_generalError().default)('component.dists.distsRootDir is not defined yet');
    distPackageJson = _packageJsonFile().default.createFromComponent(distRootDir, component, excludeRegistryPrefix);
    const distMainFile = (0, _searchFilesIgnoreExt().default)(component.dists.get(), component.mainFile, 'relative');
    distPackageJson.addOrUpdateProperty('main', component.dists.getMainDistFile() || distMainFile);
    addDependencies(distPackageJson);
  }

  return {
    packageJson,
    distPackageJson
  };
}

function updateAttribute(_x11, _x12, _x13, _x14) {
  return _updateAttribute.apply(this, arguments);
}
/**
 * Adds workspace array to package.json - only if user wants to work with yarn workspaces
 */


function _updateAttribute() {
  _updateAttribute = (0, _bluebird().coroutine)(function* (consumer, componentDir, attributeName, attributeValue) {
    const packageJsonFile = yield _packageJsonFile().default.load(consumer.getPath(), componentDir);
    if (!packageJsonFile.fileExist) return; // package.json doesn't exist, that's fine, no need to update anything

    packageJsonFile.addOrUpdateProperty(attributeName, attributeValue);
    yield packageJsonFile.write();
  });
  return _updateAttribute.apply(this, arguments);
}

function addWorkspacesToPackageJson(_x15, _x16) {
  return _addWorkspacesToPackageJson.apply(this, arguments);
}

function _addWorkspacesToPackageJson() {
  _addWorkspacesToPackageJson = (0, _bluebird().coroutine)(function* (consumer, customImportPath) {
    if (consumer.config.manageWorkspaces && consumer.config.packageManager === 'yarn' && consumer.config.useWorkspaces) {
      const rootDir = consumer.getPath();
      const dependenciesDirectory = consumer.config.dependenciesDirectory;
      const {
        componentsDefaultDirectory
      } = consumer.dirStructure;
      const driver = consumer.driver.getDriver(false);
      const PackageJson = driver.PackageJson;
      yield PackageJson.addWorkspacesToPackageJson(rootDir, componentsDefaultDirectory + _constants().SUB_DIRECTORIES_GLOB_PATTERN, dependenciesDirectory + _constants().SUB_DIRECTORIES_GLOB_PATTERN, customImportPath ? consumer.getPathRelativeToConsumer(customImportPath) : customImportPath);
    }
  });
  return _addWorkspacesToPackageJson.apply(this, arguments);
}

function removeComponentsFromWorkspacesAndDependencies(_x17, _x18) {
  return _removeComponentsFromWorkspacesAndDependencies.apply(this, arguments);
}

function _removeComponentsFromWorkspacesAndDependencies() {
  _removeComponentsFromWorkspacesAndDependencies = (0, _bluebird().coroutine)(function* (consumer, componentIds) {
    const rootDir = consumer.getPath();
    const driver = consumer.driver.getDriver(false);
    const PackageJson = driver.PackageJson;

    if (consumer.config.manageWorkspaces && consumer.config.packageManager === 'yarn' && consumer.config.useWorkspaces) {
      const dirsToRemove = componentIds.map(id => consumer.bitMap.getComponent(id, {
        ignoreVersion: true
      }).rootDir);
      yield PackageJson.removeComponentsFromWorkspaces(rootDir, dirsToRemove);
    }

    yield PackageJson.removeComponentsFromDependencies(rootDir, (0, _npmRegistryName().default)(), componentIds.map(id => id.toStringWithoutVersion()));
    yield removeComponentsFromNodeModules(consumer, componentIds);
  });
  return _removeComponentsFromWorkspacesAndDependencies.apply(this, arguments);
}

function _addDependenciesPackagesIntoPackageJson(_x19, _x20) {
  return _addDependenciesPackagesIntoPackageJson2.apply(this, arguments);
}

function _addDependenciesPackagesIntoPackageJson2() {
  _addDependenciesPackagesIntoPackageJson2 = (0, _bluebird().coroutine)(function* (dir, dependencies) {
    const packageJsonFile = yield _packageJsonFile().default.load(dir);
    packageJsonFile.addDependencies(dependencies);
    yield packageJsonFile.write();
  });
  return _addDependenciesPackagesIntoPackageJson2.apply(this, arguments);
}

function removeComponentsFromNodeModules(_x21, _x22) {
  return _removeComponentsFromNodeModules.apply(this, arguments);
}

function _removeComponentsFromNodeModules() {
  _removeComponentsFromNodeModules = (0, _bluebird().coroutine)(function* (consumer, componentIds) {
    _logger().default.debug(`removeComponentsFromNodeModules: ${componentIds.map(c => c.toString()).join(', ')}`);

    const registryPrefix = (0, _npmRegistryName().default)(); // paths without scope name, don't have a symlink in node-modules

    const pathsToRemove = componentIds.map(id => {
      return id.scope ? (0, _componentNodeModulesPath().default)(registryPrefix, id) : null;
    }).filter(a => a); // remove null

    _logger().default.debug(`deleting the following paths: ${pathsToRemove.join('\n')}`); // $FlowFixMe nulls were removed in the previous filter function


    return Promise.all(pathsToRemove.map(componentPath => _fsExtra().default.remove(consumer.toAbsolutePath(componentPath))));
  });
  return _removeComponentsFromNodeModules.apply(this, arguments);
}

function convertToValidPathForPackageManager(pathStr) {
  const prefix = 'file:'; // it works for both, Yarn and NPM

  return prefix + (pathStr.startsWith('.') ? pathStr : `./${pathStr}`);
}
/**
 * Only imported components should be saved with relative path in package.json
 * If a component is nested or imported as a package dependency, it should be saved with the version
 * If a component is authored, no need to save it as a dependency of the imported component because
 * the root package.json takes care of it already.
 */


function getPackageDependencyValue(dependencyId, parentComponentMap, dependencyComponentMap) {
  if (!dependencyComponentMap || dependencyComponentMap.origin === _constants().COMPONENT_ORIGINS.NESTED) {
    return dependencyId.version;
  }

  if (dependencyComponentMap.origin === _constants().COMPONENT_ORIGINS.AUTHORED) {
    return null;
  }

  const dependencyRootDir = dependencyComponentMap.rootDir;

  if (!dependencyRootDir) {
    throw new (_generalError().default)(`rootDir is missing from an imported component ${dependencyId.toString()}`);
  }

  if (!parentComponentMap.rootDir) throw new (_generalError().default)('rootDir is missing from an imported component');
  const rootDirRelative = (0, _utils().pathRelativeLinux)(parentComponentMap.rootDir, dependencyRootDir);
  return convertToValidPathForPackageManager(rootDirRelative);
}

function getPackageDependency(consumer, dependencyId, parentId) {
  const parentComponentMap = consumer.bitMap.getComponent(parentId);
  const dependencyComponentMap = consumer.bitMap.getComponentIfExist(dependencyId);
  return getPackageDependencyValue(dependencyId, parentComponentMap, dependencyComponentMap);
}