1*8d307f52SEvan Baconimport path from 'path';
2*8d307f52SEvan Baconimport resolveFrom from 'resolve-from';
3*8d307f52SEvan Bacon
4*8d307f52SEvan Bacon/**
5*8d307f52SEvan Bacon * Return true if the parent folder for a given file path is named "node_modules".
6*8d307f52SEvan Bacon *
7*8d307f52SEvan Bacon * @example
8*8d307f52SEvan Bacon * isModuleRootPathInNodeModulesFolder('./foo/expo') -> false
9*8d307f52SEvan Bacon * isModuleRootPathInNodeModulesFolder('./node_modules/expo') -> true
10*8d307f52SEvan Bacon */
11*8d307f52SEvan Baconfunction isModuleRootPathInNodeModulesFolder(moduleRootPath: string): boolean {
12*8d307f52SEvan Bacon  const parentFolderName = path.basename(path.dirname(moduleRootPath));
13*8d307f52SEvan Bacon  return parentFolderName === 'node_modules';
14*8d307f52SEvan Bacon}
15*8d307f52SEvan Bacon
16*8d307f52SEvan Bacon/**
17*8d307f52SEvan Bacon * Given a node module name, and a project path, this method will:
18*8d307f52SEvan Bacon *
19*8d307f52SEvan Bacon * 1. Resolve the module path.
20*8d307f52SEvan Bacon * 2. Find the module root folder.
21*8d307f52SEvan Bacon * 3. Return true if the module root folder is in a folder named `node_modules`
22*8d307f52SEvan Bacon *
23*8d307f52SEvan Bacon * @param projectRoot
24*8d307f52SEvan Bacon * @param moduleId
25*8d307f52SEvan Bacon *
26*8d307f52SEvan Bacon * @example
27*8d307f52SEvan Bacon * isModuleSymlinked('./expo/apps/native-component-list', {
28*8d307f52SEvan Bacon *   moduleId: 'react-native'
29*8d307f52SEvan Bacon * })
30*8d307f52SEvan Bacon */
31*8d307f52SEvan Baconexport function isModuleSymlinked(
32*8d307f52SEvan Bacon  projectRoot: string,
33*8d307f52SEvan Bacon  {
34*8d307f52SEvan Bacon    moduleId,
35*8d307f52SEvan Bacon    isSilent,
36*8d307f52SEvan Bacon  }: {
37*8d307f52SEvan Bacon    moduleId: string;
38*8d307f52SEvan Bacon    isSilent?: boolean;
39*8d307f52SEvan Bacon  }
40*8d307f52SEvan Bacon): boolean {
41*8d307f52SEvan Bacon  try {
42*8d307f52SEvan Bacon    const moduleRootPath = path.dirname(resolveFrom(projectRoot, `${moduleId}/package.json`));
43*8d307f52SEvan Bacon    return !isModuleRootPathInNodeModulesFolder(moduleRootPath);
44*8d307f52SEvan Bacon  } catch (error) {
45*8d307f52SEvan Bacon    if (!isSilent) {
46*8d307f52SEvan Bacon      throw error;
47*8d307f52SEvan Bacon    }
48*8d307f52SEvan Bacon    // Failed to resolve the package.json relative to the project, not sure what to do here.
49*8d307f52SEvan Bacon    // This is probably not possible due to node module resolution.
50*8d307f52SEvan Bacon    return false;
51*8d307f52SEvan Bacon  }
52*8d307f52SEvan Bacon}
53