UNPKG

3.46 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = findSymlinkedModules;
7
8function _path() {
9 const data = _interopRequireDefault(require("path"));
10
11 _path = function () {
12 return data;
13 };
14
15 return data;
16}
17
18function _fs() {
19 const data = _interopRequireDefault(require("fs"));
20
21 _fs = function () {
22 return data;
23 };
24
25 return data;
26}
27
28function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
30/**
31 * Copyright (c) Facebook, Inc. and its affiliates.
32 *
33 * This source code is licensed under the MIT license found in the
34 * LICENSE file in the root directory of this source tree.
35 */
36
37/**
38 * Find symlinked modules inside "node_modules."
39 *
40 * Naively, we could just perform a depth-first search of all folders in
41 * node_modules, recursing when we find a symlink.
42 *
43 * We can be smarter than this due to our knowledge of how npm/Yarn lays out
44 * "node_modules" / how tools that build on top of npm/Yarn (such as Lerna)
45 * install dependencies.
46 *
47 * Starting from a given root node_modules folder, this algorithm will look at
48 * both the top level descendants of the node_modules folder or second level
49 * descendants of folders that start with "@" (which indicates a scoped
50 * package). If any of those folders is a symlink, it will recurse into the
51 * link, and perform the same search in the linked folder.
52 *
53 * The end result should be a list of all resolved module symlinks for a given
54 * root.
55 */
56function findSymlinkedModules(projectRoot, ignoredRoots = []) {
57 const nodeModuleRoot = _path().default.join(projectRoot, 'node_modules');
58
59 const resolvedSymlinks = findModuleSymlinks(nodeModuleRoot, [...ignoredRoots, projectRoot]);
60 return resolvedSymlinks;
61}
62
63function findModuleSymlinks(modulesPath, ignoredPaths = []) {
64 if (!_fs().default.existsSync(modulesPath)) {
65 return [];
66 } // Find module symlinks
67
68
69 const moduleFolders = _fs().default.readdirSync(modulesPath);
70
71 const symlinks = moduleFolders.reduce((links, folderName) => {
72 const folderPath = _path().default.join(modulesPath, folderName);
73
74 const maybeSymlinkPaths = [];
75
76 if (folderName.startsWith('@')) {
77 const scopedModuleFolders = _fs().default.readdirSync(folderPath);
78
79 maybeSymlinkPaths.push(...scopedModuleFolders.map(name => _path().default.join(folderPath, name)));
80 } else {
81 maybeSymlinkPaths.push(folderPath);
82 }
83
84 return links.concat(resolveSymlinkPaths(maybeSymlinkPaths, ignoredPaths));
85 }, []); // For any symlinks found, look in _that_ modules node_modules directory
86 // and find any symlinked modules
87
88 const nestedSymlinks = symlinks.reduce((links, symlinkPath) => links.concat( // We ignore any found symlinks or anything from the ignored list,
89 findModuleSymlinks(_path().default.join(symlinkPath, 'node_modules'), [...ignoredPaths, ...symlinks])), []);
90 return [...new Set([...symlinks, ...nestedSymlinks])];
91}
92
93function resolveSymlinkPaths(maybeSymlinkPaths, ignoredPaths) {
94 return maybeSymlinkPaths.reduce((links, maybeSymlinkPath) => {
95 if (_fs().default.lstatSync(maybeSymlinkPath).isSymbolicLink()) {
96 const resolved = _path().default.resolve(_path().default.dirname(maybeSymlinkPath), _fs().default.readlinkSync(maybeSymlinkPath));
97
98 if (ignoredPaths.indexOf(resolved) === -1 && _fs().default.existsSync(resolved)) {
99 links.push(resolved);
100 }
101 }
102
103 return links;
104 }, []);
105}
\No newline at end of file