-
Notifications
You must be signed in to change notification settings - Fork 3
/
modify-resolve-lookup-paths.js
100 lines (79 loc) · 3.25 KB
/
modify-resolve-lookup-paths.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
var Module = require("module");
var fs = require("fs");
var path = require("path");
var spawnSync = require("child_process").spawnSync;
var implicitNewReturn = parseInt(process.versions.node.split(".")[0], 10) >= 12;
// We are modifying the lookup paths to behave as such:
// 0th: [WORKSPACE] - These are overriden packages.
// 1st - (N-1)th: [Standard Lookup Paths]
// Nth: [resolveLookupPaths(root)] - These are simulated peer dependencies.
// FIXME: Should we *only* climb into known packages?
module.exports = function modifyResolveLookupPaths(packages)
{
var oldResolveLookupPaths = Module._resolveLookupPaths;
var mappings = getPackageMappings(packages);
Module._resolveLookupPaths = function(request, parent, newReturn)
{
var result = oldResolveLookupPaths.apply(this, arguments);
var firstCharacter = request.charAt(0);
if (firstCharacter === "/" ||
request.substr(0, 2) === "./" ||
request.substr(0, 3) === "../")
return result;
var pathComponents = request.split(path.sep);
var name = firstCharacter === "@" ?
path.join(pathComponents[0], pathComponents[1]) :
pathComponents[0];
var mapping = mappings[name];
var workspaceResult = mapping ? [mapping.path] : [];
var rootResult = !process.mainModule ? [] :
parent === process.mainModule ? [] :
oldResolveLookupPaths.apply(this, [request, process.mainModule, newReturn]);
if (implicitNewReturn || newReturn)
return workspaceResult.concat(result || []).concat(rootResult);
return [result[0], workspaceResult.concat(result[1]).concat(rootResult[1])];
}
}
function getPackageMappings(descriptions)
{
return Object.keys(descriptions)
.map(function (name)
{
var description = descriptions[name];
var fullPath = description.path;
var ending = "/" + name;
var namedCorrectly = fullPath.substr(fullPath.length - ending.length) === ending;
var scoped = description.scoped;
if (namedCorrectly)
return { name: name, path: getSearchPath(fullPath, scoped) };
var checksum = getChecksum(description);
var tmpPath = path.join(
"/tmp/petrified-links/",
checksum,
(scoped ? path.dirname(name) : ""));
spawnSync("mkdir", ["-p", tmpPath], { stdio: [0, 1, 2] });
var linkPath = path.join(tmpPath, path.basename(name));
if (!fs.existsSync(linkPath))
fs.symlinkSync(fullPath, linkPath, "dir");
return { name: name, path: getSearchPath(linkPath, scoped) };
})
.reduce(function (mappings, description)
{
mappings[description.name] = description;
return mappings;
}, Object.create(null));
}
function getSearchPath(fullPath, scoped)
{
if (scoped)
return path.dirname(path.dirname(fullPath));
return path.dirname(fullPath);
}
function getChecksum(mapping)
{
return require("crypto")
.createHash("sha512")
.update(JSON.stringify(mapping))
.digest("base64")
.replace(/\//g, "_");
}