'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.writeDependenciesLinksToDir = exports.getIndexFileName = exports.writeComponentsDependenciesLinks = exports.writeEntryPointsForComponent = undefined;

var _regenerator;

function _load_regenerator() {
  return _regenerator = _interopRequireDefault(require('babel-runtime/regenerator'));
}

/**
 * a component may have many dependencies, this function returns the links content for all of its dependencies
 */
var getComponentLinks = function () {
  var _ref4 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(_ref3) {
    var consumer = _ref3.consumer,
        component = _ref3.component,
        componentMap = _ref3.componentMap,
        dependencies = _ref3.dependencies,
        createNpmLinkFiles = _ref3.createNpmLinkFiles;

    var directDependencies, flattenedDependencies, links, internalCustomResolvedLinks, flattenLinks, _groupLinks, postInstallLinks, linksToWrite, symlinks;

    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            directDependencies = _getDirectDependencies(component, componentMap);
            flattenedDependencies = _getFlattenedDependencies(component, componentMap);

            if (!(!directDependencies || !directDependencies.length)) {
              _context.next = 4;
              break;
            }

            return _context.abrupt('return', []);

          case 4:
            links = directDependencies.map(function (dep) {
              if (!dep.relativePaths || (_ramda || _load_ramda()).default.isEmpty(dep.relativePaths)) return [];
              var getDependencyIdWithResolvedVersion = function getDependencyIdWithResolvedVersion() {
                // Check if the dependency is latest, if yes we need to resolve if from the flatten dependencies to get the
                // Actual version number, because on the bitmap we have only specific versions
                if (dep.id.getVersion().latest) {
                  return flattenedDependencies.resolveVersion(dep.id);
                }
                return dep.id;
              };
              var dependencyId = getDependencyIdWithResolvedVersion();
              var getDependencyComponent = function getDependencyComponent() {
                return dependencies.find(function (dependency) {
                  return dependency.id.isEqual(dependencyId);
                });
              };
              var dependencyComponent = getDependencyComponent();

              if (!dependencyComponent) {
                var errorMessage = `link-generation: failed finding ${dependencyId.toString()} in the dependencies array of ${component.id}.
The dependencies array has the following ids: ${dependencies.map(function (d) {
                  return d.id;
                }).join(', ')}`;
                throw new Error(errorMessage);
              }

              var dependencyLinks = dep.relativePaths.map(function (relativePath) {
                return _getLinksForOneDependencyFile({
                  consumer,
                  component,
                  componentMap,
                  relativePath,
                  dependencyId,
                  dependencyComponent,
                  createNpmLinkFiles
                });
              });
              return (_ramda || _load_ramda()).default.flatten(dependencyLinks);
            });
            internalCustomResolvedLinks = component.customResolvedPaths.length ? getInternalCustomResolvedLinks(component, componentMap, createNpmLinkFiles) : [];
            flattenLinks = (_ramda || _load_ramda()).default.flatten(links).concat(internalCustomResolvedLinks);
            _groupLinks = groupLinks(flattenLinks), postInstallLinks = _groupLinks.postInstallLinks, linksToWrite = _groupLinks.linksToWrite, symlinks = _groupLinks.symlinks;

            if (!postInstallLinks.length) {
              _context.next = 11;
              break;
            }

            _context.next = 11;
            return generatePostInstallScript(component, postInstallLinks);

          case 11:
            if (symlinks.length) {
              createSymlinks(symlinks, component.id);
            }
            return _context.abrupt('return', linksToWrite);

          case 13:
          case 'end':
            return _context.stop();
        }
      }
    }, _callee, this);
  }));

  return function getComponentLinks(_x) {
    return _ref4.apply(this, arguments);
  };
}();

/**
 * The following scenario will help understanding why links are needed.
 * Component A has a dependency B. (for instance, in a.js there is a require statement to 'b.js').
 * While importing component A, it knows about the B dependency and it saves it under 'dependencies' directory of A.
 * The problem is that the above require is broken, because 'b.js' is not in the same place where it was originally.
 * This function solves this issue by creating the 'b.js' file in the original location and points to the new location
 * under 'dependencies' of A.
 *
 * It does the link generation in two steps.
 * step 1: "componentsLinks", it generates links to all imported components.
 * target: imported components. source: dependencies.
 * step 2: "dependenciesLinks", it generates links to all dependencies of the imported components.
 * target: dependencies. source: other dependencies.
 * this step is not needed when the imported components don't have dependencies, or when the
 * dependencies were installed as npm/yarn packages.
 */
var writeComponentsDependenciesLinks = function () {
  var _ref5 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(componentDependencies, consumer, createNpmLinkFiles) {
    var _this = this;

    var allLinksP, allLinks, linksWithoutNulls, linksWithoutDuplications;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            allLinksP = componentDependencies.map(function () {
              var _ref6 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(componentWithDeps) {
                var componentMap, componentsLinks, dependenciesLinks;
                return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
                  while (1) {
                    switch (_context2.prev = _context2.next) {
                      case 0:
                        componentMap = consumer.bitMap.getComponent(componentWithDeps.component.id);

                        if (!(componentMap.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.AUTHORED)) {
                          _context2.next = 4;
                          break;
                        }

                        (_logger || _load_logger()).default.debug(`writeComponentsDependenciesLinks, ignoring a component ${componentWithDeps.component.id} as it is an author component`);
                        return _context2.abrupt('return', null);

                      case 4:
                        // it must be IMPORTED. We don't pass NESTED to this function
                        (_logger || _load_logger()).default.debug(`writeComponentsDependenciesLinks, generating links for ${componentWithDeps.component.id}`);

                        _context2.next = 7;
                        return getComponentLinks({
                          consumer,
                          component: componentWithDeps.component,
                          componentMap,
                          dependencies: componentWithDeps.allDependencies,
                          createNpmLinkFiles
                        });

                      case 7:
                        componentsLinks = _context2.sent;

                        if (!componentWithDeps.component.dependenciesSavedAsComponents) {
                          _context2.next = 13;
                          break;
                        }

                        _context2.next = 11;
                        return Promise.all(componentWithDeps.allDependencies.map(function (dep) {
                          var depComponentMap = consumer.bitMap.getComponent(dep.id);
                          // We pass here the componentWithDeps.dependencies again because it contains the full dependencies objects
                          // also the indirect ones
                          // The dep.dependencies contain only an id and relativePaths and not the full object
                          return getComponentLinks({
                            consumer,
                            component: dep,
                            componentMap: depComponentMap,
                            dependencies: componentWithDeps.allDependencies,
                            createNpmLinkFiles
                          });
                        }));

                      case 11:
                        dependenciesLinks = _context2.sent;
                        return _context2.abrupt('return', [componentsLinks].concat(_toConsumableArray(dependenciesLinks)));

                      case 13:
                        return _context2.abrupt('return', componentsLinks);

                      case 14:
                      case 'end':
                        return _context2.stop();
                    }
                  }
                }, _callee2, _this);
              }));

              return function (_x5) {
                return _ref6.apply(this, arguments);
              };
            }());
            _context3.next = 3;
            return Promise.all(allLinksP);

          case 3:
            allLinks = _context3.sent;
            linksWithoutNulls = (_ramda || _load_ramda()).default.flatten(allLinks).filter(function (x) {
              return x;
            });
            linksWithoutDuplications = (0, (_lodash || _load_lodash()).default)(linksWithoutNulls, 'filePath');
            return _context3.abrupt('return', Promise.all(linksWithoutDuplications.map(function (link) {
              return (0, (_utils || _load_utils()).outputFile)(link);
            })));

          case 7:
          case 'end':
            return _context3.stop();
        }
      }
    }, _callee3, this);
  }));

  return function writeComponentsDependenciesLinks(_x2, _x3, _x4) {
    return _ref5.apply(this, arguments);
  };
}();

/**
 * when using custom module resolutions, and inside a component there is a file that requires
 * another file by custom-resolved syntax, we must generate links on the imported component inside
 * node_modules.
 *
 * E.g. original component "utils/jump" has two files:
 * bar/foo.js => require('utils/is-string); // "src" is set to be a module-directory
 * utils/is-string.js
 *
 * imported component:
 * components/utils/jump/bar/foo.js
 * components/utils/jump/utils/is-string.js
 * components/utils/jump/node_modules/utils/is-string // this is the file we generate here
 */


/**
 * change the package.json of a component to include postInstall script.
 * @see postInstallTemplate() JSDoc to understand better why this postInstall script is needed
 */
var generatePostInstallScript = function () {
  var _ref7 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(component, postInstallLinks) {
    var componentDir, linkPathsObject, postInstallCode, POST_INSTALL_FILENAME, postInstallFilePath, postInstallScript, override;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            componentDir = component.writtenPath;
            // convert from array to object for easier parsing in the postinstall script

            linkPathsObject = postInstallLinks.reduce(function (acc, val) {
              acc[val.filePath] = val.content;
              return acc;
            }, {});

            if (component.packageJsonInstance) {
              _context4.next = 4;
              break;
            }

            throw new Error(`packageJsonInstance is missing for ${component.id.toString()}`);

          case 4:
            postInstallCode = (0, (_postinstall || _load_postinstall()).default)(JSON.stringify(linkPathsObject));
            POST_INSTALL_FILENAME = '.bit.postinstall.js';
            postInstallFilePath = (_path || _load_path()).default.join(componentDir, POST_INSTALL_FILENAME);
            postInstallScript = `node ${POST_INSTALL_FILENAME}`;

            component.packageJsonInstance.scripts = { postinstall: postInstallScript };
            override = true;
            _context4.next = 12;
            return Promise.all([(_fsExtra || _load_fsExtra()).default.writeFile(postInstallFilePath, postInstallCode), component.packageJsonInstance.write({ override })]);

          case 12:
          case 'end':
            return _context4.stop();
        }
      }
    }, _callee4, this);
  }));

  return function generatePostInstallScript(_x6, _x7) {
    return _ref7.apply(this, arguments);
  };
}();

/**
 * Relevant for IMPORTED and NESTED only
 */


var writeEntryPointsForComponent = function () {
  var _ref8 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee5(component, consumer) {
    var componentMap, componentRoot, mainFile, indexName, entryPointFileContent, entryPointPath, distDir, entryPointDist;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee5$(_context5) {
      while (1) {
        switch (_context5.prev = _context5.next) {
          case 0:
            componentMap = consumer.bitMap.getComponent(component.id);
            componentRoot = component.writtenPath || componentMap.rootDir;

            if (!(componentMap.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.AUTHORED)) {
              _context5.next = 4;
              break;
            }

            return _context5.abrupt('return', Promise.resolve());

          case 4:
            mainFile = component.dists.calculateMainDistFile(component.mainFile);
            indexName = getIndexFileName(mainFile); // Move to bit-javascript

            entryPointFileContent = (0, (_linkContent || _load_linkContent()).default)(`./${mainFile}`);
            entryPointPath = (_path || _load_path()).default.join(componentRoot, indexName);

            if (!(!component.dists.isEmpty() && component.dists.writeDistsFiles && !consumer.shouldDistsBeInsideTheComponent())) {
              _context5.next = 14;
              break;
            }

            distDir = component.dists.getDistDirForConsumer(consumer, componentMap.rootDir);
            entryPointDist = (_path || _load_path()).default.join(distDir, indexName);

            (_logger || _load_logger()).default.debug(`writeEntryPointFile, on ${entryPointDist}`);
            _context5.next = 14;
            return (0, (_utils || _load_utils()).outputFile)({ filePath: entryPointDist, content: entryPointFileContent, override: false });

          case 14:
            (_logger || _load_logger()).default.debug(`writeEntryPointFile, on ${entryPointPath}`);
            return _context5.abrupt('return', (0, (_utils || _load_utils()).outputFile)({ filePath: entryPointPath, content: entryPointFileContent, override: false }));

          case 16:
          case 'end':
            return _context5.stop();
        }
      }
    }, _callee5, this);
  }));

  return function writeEntryPointsForComponent(_x8, _x9) {
    return _ref8.apply(this, arguments);
  };
}();

/**
 * used for writing compiler and tester dependencies to the directory of their configuration file
 * the configuration directory is not always the same as the component, it can be moved by 'eject-conf' command
 * this methods write the environment dependency links no matter where the directory located on the workspace
 *
 */


var writeDependenciesLinksToDir = function () {
  var _ref9 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee7(targetDir, component, dependencies, consumer) {
    var _this2 = this;

    var linksP, links, flattenLinks, _groupLinks2, linksToWrite;

    return (_regenerator || _load_regenerator()).default.wrap(function _callee7$(_context7) {
      while (1) {
        switch (_context7.prev = _context7.next) {
          case 0:
            linksP = dependencies.get().map(function () {
              var _ref10 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee6(dependency) {
                var dependencyComponent, dependencyLinks;
                return (_regenerator || _load_regenerator()).default.wrap(function _callee6$(_context6) {
                  while (1) {
                    switch (_context6.prev = _context6.next) {
                      case 0:
                        _context6.next = 2;
                        return consumer.loadComponentFromModel(dependency.id);

                      case 2:
                        dependencyComponent = _context6.sent;
                        dependencyLinks = dependency.relativePaths.map(function (relativePath) {
                          return _getLinksForOneDependencyFile({
                            consumer,
                            component,
                            componentMap: component.componentMap,
                            relativePath,
                            dependencyId: dependency.id,
                            dependencyComponent,
                            createNpmLinkFiles: false,
                            targetDir
                          });
                        });
                        return _context6.abrupt('return', (_ramda || _load_ramda()).default.flatten(dependencyLinks));

                      case 5:
                      case 'end':
                        return _context6.stop();
                    }
                  }
                }, _callee6, _this2);
              }));

              return function (_x14) {
                return _ref10.apply(this, arguments);
              };
            }());
            _context7.next = 3;
            return Promise.all(linksP);

          case 3:
            links = _context7.sent;
            flattenLinks = (_ramda || _load_ramda()).default.flatten(links);
            _groupLinks2 = groupLinks(flattenLinks), linksToWrite = _groupLinks2.linksToWrite;
            return _context7.abrupt('return', Promise.all(linksToWrite.map(function (link) {
              return (0, (_utils || _load_utils()).outputFile)(link);
            })));

          case 7:
          case 'end':
            return _context7.stop();
        }
      }
    }, _callee7, this);
  }));

  return function writeDependenciesLinksToDir(_x10, _x11, _x12, _x13) {
    return _ref9.apply(this, arguments);
  };
}();

var _fsExtra;

function _load_fsExtra() {
  return _fsExtra = _interopRequireDefault(require('fs-extra'));
}

var _path;

function _load_path() {
  return _path = _interopRequireDefault(require('path'));
}

var _ramda;

function _load_ramda() {
  return _ramda = _interopRequireDefault(require('ramda'));
}

var _lodash;

function _load_lodash() {
  return _lodash = _interopRequireDefault(require('lodash.uniqby'));
}

var _lodash2;

function _load_lodash2() {
  return _lodash2 = _interopRequireDefault(require('lodash.groupby'));
}

var _constants;

function _load_constants() {
  return _constants = require('../constants');
}

var _utils;

function _load_utils() {
  return _utils = require('../utils');
}

var _logger;

function _load_logger() {
  return _logger = _interopRequireDefault(require('../logger/logger'));
}

var _scope;

function _load_scope() {
  return _scope = require('../scope');
}

var _component;

function _load_component() {
  return _component = _interopRequireDefault(require('../consumer/component'));
}

var _dependencies;

function _load_dependencies() {
  return _dependencies = require('../consumer/component/dependencies');
}

var _bitId;

function _load_bitId() {
  return _bitId = require('../bit-id');
}

var _globalConfig;

function _load_globalConfig() {
  return _globalConfig = require('../api/consumer/lib/global-config');
}

var _consumer;

function _load_consumer() {
  return _consumer = require('../consumer');
}

var _componentMap;

function _load_componentMap() {
  return _componentMap = _interopRequireDefault(require('../consumer/bit-map/component-map'));
}

var _postinstall;

function _load_postinstall() {
  return _postinstall = _interopRequireDefault(require('../consumer/component/templates/postinstall.default-template'));
}

var _dependencies2;

function _load_dependencies2() {
  return _dependencies2 = _interopRequireDefault(require('../consumer/component/dependencies/dependencies'));
}

var _linkContent;

function _load_linkContent() {
  return _linkContent = _interopRequireDefault(require('./link-content'));
}

var _createSymlinkOrCopy;

function _load_createSymlinkOrCopy() {
  return _createSymlinkOrCopy = _interopRequireDefault(require('../utils/fs/create-symlink-or-copy'));
}

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

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

// todo: move to bit-javascript
function getIndexFileName(mainFile) {
  return `${(_constants || _load_constants()).DEFAULT_INDEX_NAME}.${(0, (_utils || _load_utils()).getExt)(mainFile)}`;
}

function prepareLinkFile(_ref) {
  var componentId = _ref.componentId,
      mainFile = _ref.mainFile,
      linkPath = _ref.linkPath,
      relativePathInDependency = _ref.relativePathInDependency,
      relativePath = _ref.relativePath,
      depRootDir = _ref.depRootDir,
      isNpmLink = _ref.isNpmLink;

  // this is used to convert the component name to a valid npm package  name
  var packagePath = `${(0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_REGISTRY_DOMAIN_PREFIX) || (_constants || _load_constants()).DEFAULT_REGISTRY_DOMAIN_PREFIX}/${componentId.toStringWithoutVersion().replace(/\//g, '.')}`;
  var actualFilePath = depRootDir ? (_path || _load_path()).default.join(depRootDir, relativePathInDependency) : relativePathInDependency;
  if (relativePathInDependency === mainFile) {
    actualFilePath = depRootDir ? (_path || _load_path()).default.join(depRootDir, mainFile) : mainFile;
  }
  var relativeFilePath = (_path || _load_path()).default.relative((_path || _load_path()).default.dirname(linkPath), actualFilePath);
  var importSpecifiers = relativePath.importSpecifiers;
  var linkContent = (0, (_linkContent || _load_linkContent()).default)(relativeFilePath, importSpecifiers, isNpmLink, packagePath);
  (_logger || _load_logger()).default.debug(`prepareLinkFile, on ${linkPath}`);
  var linkPathExt = (0, (_utils || _load_utils()).getExt)(linkPath);
  var isEs6 = importSpecifiers && linkPathExt === 'js';
  var symlinkTo = linkContent ? undefined : actualFilePath;
  return { linkPath, linkContent, isEs6, symlinkTo };
}

/**
 * a dependency component may have multiple files required by the main component.
 * this function returns the link content of one file of a dependency.
 * @see RelativePath docs for more info
 */
function _getLinksForOneDependencyFile(_ref2) {
  var consumer = _ref2.consumer,
      component = _ref2.component,
      componentMap = _ref2.componentMap,
      relativePath = _ref2.relativePath,
      dependencyId = _ref2.dependencyId,
      dependencyComponent = _ref2.dependencyComponent,
      createNpmLinkFiles = _ref2.createNpmLinkFiles,
      targetDir = _ref2.targetDir;

  var consumerPath = consumer.getPath();
  var getTargetDir = function getTargetDir() {
    if (targetDir) return targetDir;
    // when running from bit build, the writtenPath is not available
    if (!component.writtenPath) return consumer.toAbsolutePath(componentMap.rootDir);
    if ((_path || _load_path()).default.isAbsolute(component.writtenPath)) return component.writtenPath;
    return consumer.toAbsolutePath(component.writtenPath);
  };
  var parentDir = getTargetDir();
  var relativePathInDependency = (_path || _load_path()).default.normalize(relativePath.destinationRelativePath);
  var mainFile = dependencyComponent.dists.calculateMainDistFile(dependencyComponent.mainFile);
  var hasDist = component.dists.writeDistsFiles && !component.dists.isEmpty();
  var distRoot = component.dists.getDistDirForConsumer(consumer, componentMap.rootDir);

  var relativeDistPathInDependency = (0, (_utils || _load_utils()).searchFilesIgnoreExt)(dependencyComponent.dists.get(), relativePathInDependency, 'relative');
  relativeDistPathInDependency = relativeDistPathInDependency // $FlowFixMe relative is defined
  ? relativeDistPathInDependency.relative : relativePathInDependency;

  var relativeDistExtInDependency = (0, (_utils || _load_utils()).getExt)(relativeDistPathInDependency);
  var sourceRelativePath = relativePath.sourceRelativePath;
  var getLinkPath = function getLinkPath() {
    if (!relativePath.isCustomResolveUsed) return (_path || _load_path()).default.join(parentDir, sourceRelativePath);
    // $FlowFixMe relativePath.importSource is set when isCustomResolveUsed
    var importSource = relativePath.importSource;
    var importSourceFileExt = relativeDistExtInDependency || (_path || _load_path()).default.extname(relativePath.sourceRelativePath);
    // e.g. for require('utils/is-string'), the link should be at node_modules/utils/is-string/index.js
    var importSourceFile = (_path || _load_path()).default.extname(importSource) ? importSource : (_path || _load_path()).default.join(importSource, `${(_constants || _load_constants()).DEFAULT_INDEX_NAME}.${importSourceFileExt}`);
    var importSourcePath = (_path || _load_path()).default.join('node_modules', importSourceFile);
    // if createNpmLinkFiles, the path will be part of the postinstall script, so it shouldn't be absolute
    return createNpmLinkFiles ? importSourcePath : (_path || _load_path()).default.join(parentDir, importSourcePath);
  };
  var linkPath = getLinkPath();

  var linkFiles = [];
  var depComponentMap = component.dependenciesSavedAsComponents ? consumer.bitMap.getComponent(dependencyId) : undefined;

  var depRootDir = depComponentMap && depComponentMap.rootDir ? (_path || _load_path()).default.join(consumerPath, depComponentMap.rootDir) : undefined;
  var isNpmLink = createNpmLinkFiles || !component.dependenciesSavedAsComponents;
  var depRootDirDist = depComponentMap && depComponentMap.rootDir ? dependencyComponent.dists.getDistDirForConsumer(consumer, depComponentMap.rootDir) : undefined;
  var isCustomResolvedWithDistInside = relativePath.isCustomResolveUsed && depRootDirDist && consumer.shouldDistsBeInsideTheComponent() && hasDist;

  var prepareLinkFileParams = {
    componentId: dependencyId,
    mainFile,
    linkPath,
    relativePathInDependency: isCustomResolvedWithDistInside ? `${(0, (_utils || _load_utils()).getWithoutExt)(relativePathInDependency)}.${relativeDistExtInDependency}` : relativePathInDependency,
    relativePath,
    depRootDir: isCustomResolvedWithDistInside ? depRootDirDist : depRootDir,
    isNpmLink
  };

  var linkFile = prepareLinkFile(prepareLinkFileParams);
  if (relativePath.isCustomResolveUsed && createNpmLinkFiles) {
    linkFile.postInstallLink = true;
  }
  linkFiles.push(linkFile);

  if (hasDist) {
    prepareLinkFileParams.relativePathInDependency = relativeDistPathInDependency;
    prepareLinkFileParams.depRootDir = depRootDirDist;
    if (relativePath.isCustomResolveUsed) {
      if (!consumer.shouldDistsBeInsideTheComponent()) {
        // when isCustomResolvedUsed, the link is generated inside node_module directory, so for
        // dist inside the component, only one link is needed at the parentRootDir. for dist
        // outside the component dir, another link is needed for the dist/parentRootDir.
        // $FlowFixMe relativePath.importSource is set when isCustomResolveUsed
        prepareLinkFileParams.linkPath = (_path || _load_path()).default.join(distRoot, 'node_modules', relativePath.importSource);
        var linkFileInNodeModules = prepareLinkFile(prepareLinkFileParams);
        linkFiles.push(linkFileInNodeModules);
      }
    } else {
      var sourceRelativePathWithCompiledExt = `${(0, (_utils || _load_utils()).getWithoutExt)(sourceRelativePath)}.${relativeDistExtInDependency}`;
      // Generate a link file inside dist folder of the dependent component
      prepareLinkFileParams.linkPath = (_path || _load_path()).default.join(distRoot, sourceRelativePathWithCompiledExt);
      var linkFileInDist = prepareLinkFile(prepareLinkFileParams);
      linkFiles.push(linkFileInDist);
    }
  }

  return linkFiles;
}

function _getDirectDependencies(component, componentMap) {
  // devDependencies of Nested components are not written to the filesystem, so no need to link them.
  return componentMap.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.NESTED ? component.dependencies.get() : component.getAllNonEnvsDependencies();
}

function _getFlattenedDependencies(component, componentMap) {
  return componentMap.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.NESTED ? component.flattenedDependencies : component.getAllNonEnvsFlattenedDependencies();
}

function createSymlinks(symlinks, componentId) {
  symlinks.forEach(function (symlink) {
    (0, (_createSymlinkOrCopy || _load_createSymlinkOrCopy()).default)(symlink.source, symlink.dest, componentId);
  });
}

function groupLinks(flattenLinks) {
  var groupedLinks = (0, (_lodash2 || _load_lodash2()).default)(flattenLinks, function (link) {
    return link.linkPath;
  });
  var linksToWrite = [];
  var postInstallLinks = [];
  var symlinks = [];
  Object.keys(groupedLinks).forEach(function (group) {
    var content = '';
    var firstGroupItem = groupedLinks[group][0];
    if (firstGroupItem.symlinkTo) {
      symlinks.push({ source: firstGroupItem.symlinkTo, dest: firstGroupItem.linkPath });
      return;
    }
    if (firstGroupItem.isEs6) {
      // check by the first item of the array, it can be any other item as well
      content = 'Object.defineProperty(exports, "__esModule", { value: true });\n';
    }
    content += groupedLinks[group].map(function (linkItem) {
      return linkItem.linkContent;
    }).join('\n');
    var linkFile = { filePath: group, content };
    if (firstGroupItem.postInstallLink) {
      postInstallLinks.push(linkFile);
    } else {
      linksToWrite.push(linkFile);
    }
  });
  return { postInstallLinks, linksToWrite, symlinks };
}function getInternalCustomResolvedLinks(component, componentMap, createNpmLinkFiles) {
  var componentDir = component.writtenPath || componentMap.rootDir;
  if (!componentDir) {
    throw new Error(`getInternalCustomResolvedLinks, unable to find the written path of ${component.id.toString()}`);
  }
  var getDestination = function getDestination(importSource) {
    return `node_modules/${importSource}`;
  };
  return component.customResolvedPaths.map(function (customPath) {
    var sourceAbs = (_path || _load_path()).default.join(componentDir, customPath.destinationPath);
    var dest = getDestination(customPath.importSource);
    var destAbs = (_path || _load_path()).default.join(componentDir, dest);
    var destRelative = (_path || _load_path()).default.relative((_path || _load_path()).default.dirname(destAbs), sourceAbs);
    var linkContent = (0, (_linkContent || _load_linkContent()).default)(destRelative);
    return { linkPath: createNpmLinkFiles ? dest : destAbs, linkContent, postInstallLink: createNpmLinkFiles };
  });
}exports.writeEntryPointsForComponent = writeEntryPointsForComponent;
exports.writeComponentsDependenciesLinks = writeComponentsDependenciesLinks;
exports.getIndexFileName = getIndexFileName;
exports.writeDependenciesLinksToDir = writeDependenciesLinksToDir;