source: trip-planner-front/node_modules/adjust-sourcemap-loader/codec/utility/enhanced-relative.js@ 6a80231

Last change on this file since 6a80231 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.2 KB
Line 
1'use strict';
2
3var fs = require('fs'),
4 path = require('path');
5
6var cache;
7
8/**
9 * Perform <code>path.relative()</code> but try to detect and correct sym-linked node modules.
10 * @param {string} from The base path
11 * @param {string} to The full path
12 */
13function enhancedRelative(from, to) {
14
15 // relative path
16 var relative = path.relative(from, to);
17
18 // trailing is the relative path portion without any '../'
19 var trailing = relative.replace(/^\.{2}[\\\/]/, ''),
20 leading = to.replace(trailing, '');
21
22 // within project is what we want
23 var isInProject = (relative === trailing);
24 if (isInProject) {
25 return relative;
26 }
27 // otherwise look at symbolic linked modules
28 else {
29 var splitTrailing = trailing.split(/[\\\/]/);
30
31 // ensure failures can retry with fresh cache
32 for (var i = cache ? 2 : 1, foundPath = false; (i > 0) && !foundPath; i--) {
33
34 // ensure cache
35 cache = cache || indexLinkedModules(from);
36
37 // take elements from the trailing path and append them the the leading path in an attempt to find a package.json
38 for (var j = 0; (j < splitTrailing.length) && !foundPath; j++) {
39
40 // find the name of packages in the actual file location
41 // start at the lowest concrete directory that appears in the relative path
42 var packagePath = path.join.apply(path, [leading].concat(splitTrailing.slice(0, j + 1))),
43 packageJsonPath = path.join(packagePath, 'package.json'),
44 packageName = fs.existsSync(packageJsonPath) && require(packageJsonPath).name;
45
46 // lookup any package name in the cache
47 var linkedPackagePath = !!packageName && cache[packageName];
48 if (linkedPackagePath) {
49
50 // the remaining portion of the trailing path, not including the package path
51 var remainingPath = path.join.apply(path, splitTrailing.slice(j + 1));
52
53 // validate the remaining path in the linked location
54 // failure implies we will keep trying nested sym-linked packages
55 var linkedFilePath = path.join(linkedPackagePath, remainingPath),
56 isValid = !!linkedFilePath && fs.existsSync(linkedFilePath) &&
57 fs.statSync(linkedFilePath).isFile();
58
59 // path is found where valid
60 foundPath = isValid && linkedFilePath;
61 }
62 }
63
64 // cache cannot be trusted if a file can't be found
65 // set the cache to false to trigger its rebuild
66 cache = !!foundPath && cache;
67 }
68
69 // the relative path should now be within the project
70 return foundPath ? path.relative(from, foundPath) : relative;
71 }
72}
73
74module.exports = enhancedRelative;
75
76/**
77 * Make a hash of linked modules within the given directory by breadth-first search.
78 * @param {string} directory A path to start searching
79 * @returns {object} A collection of sym-linked paths within the project keyed by their package name
80 */
81function indexLinkedModules(directory) {
82 var buffer = listSymLinkedModules(directory),
83 hash = {};
84
85 // while there are items in the buffer
86 while (buffer.length > 0) {
87 var modulePath = buffer.shift(),
88 packageJsonPath = path.join(modulePath, 'package.json'),
89 packageName = fs.existsSync(packageJsonPath) && require(packageJsonPath).name;
90 if (packageName) {
91
92 // add this path keyed by package name, so long as it doesn't exist at a lower level
93 hash[packageName] = hash[packageName] || modulePath;
94
95 // detect nested module and push to the buffer (breadth-first)
96 buffer.push.apply(buffer, listSymLinkedModules(modulePath));
97 }
98 }
99 return hash;
100
101 function listSymLinkedModules(directory) {
102 var modulesPath = path.join(directory, 'node_modules'),
103 hasNodeModules = fs.existsSync(modulesPath) && fs.statSync(modulesPath).isDirectory(),
104 subdirectories = !!hasNodeModules && fs.readdirSync(modulesPath) || [];
105
106 return subdirectories
107 .map(joinDirectory)
108 .filter(testIsSymLink);
109
110 function joinDirectory(subdirectory) {
111 return path.join(modulesPath, subdirectory);
112 }
113
114 function testIsSymLink(directory) {
115 return fs.lstatSync(directory).isSymbolicLink(); // must use lstatSync not statSync
116 }
117 }
118}
Note: See TracBrowser for help on using the repository browser.