Skip to content

Commit 54d06fe

Browse files
committed
2 parents bdd59ea + 26cd05e commit 54d06fe

File tree

3 files changed

+95
-21
lines changed

3 files changed

+95
-21
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ you want. `app-root-path` is aware of this edge-case and will strip the `/bin` a
9090

9191
## Change Log
9292

93+
### 3.0.0
94+
- Improved Yarn Plug'n'Play support
95+
- Fixed bug when used with webpack
96+
9397
### 2.2.1
9498
- Better handling of webpack
9599

@@ -148,4 +152,4 @@ This helps ensure that commits match the expected format. Commits to `master` w
148152
[david-dm-img]: https://david-dm.org/inxilpro/node-app-root-path.svg
149153
[david-dm]: https://david-dm.org/inxilpro/node-app-root-path
150154
[codecov-img]: https://codecov.io/gh/inxilpro/node-app-root-path/branch/master/graph/badge.svg
151-
[codecov]: https://codecov.io/gh/inxilpro/node-app-root-path
155+
[codecov]: https://codecov.io/gh/inxilpro/node-app-root-path

lib/resolve.js

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,30 @@ var requireFunction = ("function" === typeof __webpack_require__ || "function" =
2323
? __non_webpack_require__
2424
: require;
2525

26+
const isInstalledWithPNPM = function(resolved) {
27+
const pnpmDir = sep + '.pnpm';
28+
29+
for (const globalPath of globalPaths) {
30+
if (-1 !== globalPath.indexOf(pnpmDir) && -1 !== resolved.indexOf(pnpmDir)) {
31+
return true;
32+
}
33+
}
34+
return false;
35+
}
36+
37+
const getFirstPartFromNodeModules = function(resolved) {
38+
const nodeModulesDir = sep + 'node_modules';
39+
40+
if (-1 !== resolved.indexOf(nodeModulesDir)) {
41+
const parts = resolved.split(nodeModulesDir);
42+
if (parts.length) {
43+
return parts[0];
44+
}
45+
}
46+
47+
return null;
48+
}
49+
2650
// Resolver
2751
module.exports = function resolve(dirname) {
2852
// Check for environmental variable
@@ -55,6 +79,16 @@ module.exports = function resolve(dirname) {
5579
var alternateMethod = false;
5680
var appRootPath = null;
5781

82+
// Check if the globalPaths contain some folders with '.pnpm' in the path
83+
// If yes this means it is most likely installed with pnpm
84+
if (isInstalledWithPNPM(resolved)) {
85+
appRootPath = getFirstPartFromNodeModules(resolved);
86+
87+
if (appRootPath) {
88+
return appRootPath;
89+
}
90+
}
91+
5892
// Make sure that we're not loaded from a global include path
5993
// Eg. $HOME/.node_modules
6094
// $HOME/.node_libraries
@@ -67,19 +101,14 @@ module.exports = function resolve(dirname) {
67101

68102
// If the app-root-path library isn't loaded globally,
69103
// and node_modules exists in the path, just split __dirname
70-
var nodeModulesDir = sep + 'node_modules';
71-
if (!alternateMethod && -1 !== resolved.indexOf(nodeModulesDir)) {
72-
var parts = resolved.split(nodeModulesDir);
73-
if (parts.length) {
74-
appRootPath = parts[0];
75-
parts = null;
76-
}
104+
if (!alternateMethod) {
105+
appRootPath = getFirstPartFromNodeModules(resolved);
77106
}
78107

79108
// If the above didn't work, or this module is loaded globally, then
80109
// resort to require.main.filename (See http://nodejs.org/api/modules.html)
81110
if (alternateMethod || null == appRootPath) {
82-
appRootPath = path.dirname(require.main.filename);
111+
appRootPath = path.dirname(requireFunction.main.filename);
83112
}
84113

85114
// Handle global bin/ directory edge-case

test/index.js

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@ var path = require('path');
44
var assert = require('assert');
55
var mockery = require('mockery');
66

7+
function globalPathsContainPnpm() {
8+
return undefined !== require('module').globalPaths.find(function(e) {
9+
return e.indexOf('.pnpm') !== -1
10+
});
11+
}
12+
713
describe('The path resolution method', function() {
814
var resolve = require('../lib/resolve.js');
915
var originalReqMainFilename = require.main.filename;
16+
const isPnpm = globalPathsContainPnpm();
1017

1118
// Make sure env variable isn't set for tests
1219
if (process.env.APP_ROOT_PATH) {
@@ -21,14 +28,53 @@ describe('The path resolution method', function() {
2128
require.main.filename = originalReqMainFilename;
2229
});
2330

24-
// Check global paths
25-
it('should use require.main.filename if the path is in the globalPaths array', function() {
26-
var expected = path.dirname(require.main.filename);
27-
require('module').globalPaths.forEach(function(globalPath) {
28-
var testPath = globalPath + path.sep + 'node-app-root-path';
29-
assert.equal(resolve(testPath), expected);
31+
if (isPnpm) {
32+
it('should use require.main.filename if the path is in the globalPaths array (PNPM)', function() {
33+
var expected = path.dirname(require.main.filename);
34+
var root = path.resolve(__dirname, '..');
35+
36+
require('module').globalPaths.forEach(function(globalPath) {
37+
var testPath = globalPath + path.sep + 'node-app-root-path';
38+
39+
if (-1 !== testPath.indexOf('.pnpm')) {
40+
assert.equal(resolve(testPath), root);
41+
} else {
42+
assert.equal(resolve(testPath), expected);
43+
}
44+
});
45+
});
46+
47+
// Check pnpm
48+
it('should use String.split() if installed with pnpm', function() {
49+
var cases = [
50+
'/var/www/node_modules/.pnpm/node_modules/node-app-root-path',
51+
'/var/www/node_modules/.pnpm/custom_registry/node-app-root-path',
52+
];
53+
var expected = '/var/www';
54+
55+
cases.forEach(function(testPath) {
56+
assert.equal(resolve(testPath), expected);
57+
});
3058
});
31-
});
59+
60+
// Check root path
61+
it('should still use String.split() in the root directory (PNPM)', function() {
62+
assert.equal(resolve('/node_modules'), path.dirname(require.main.filename));
63+
});
64+
} else {
65+
it('should use require.main.filename if the path is in the globalPaths array', function() {
66+
var expected = path.dirname(require.main.filename);
67+
require('module').globalPaths.forEach(function(globalPath) {
68+
var testPath = globalPath + path.sep + 'node-app-root-path';
69+
assert.equal(resolve(testPath), expected);
70+
});
71+
});
72+
73+
// Check root path
74+
it('should still use String.split() in the root directory', function() {
75+
assert.equal(resolve('/node_modules'), '');
76+
});
77+
}
3278

3379
// Check bin/ dir in global path
3480
it('should correctly handle the global bin/ edge case', function() {
@@ -54,11 +100,6 @@ describe('The path resolution method', function() {
54100
});
55101
});
56102

57-
// Check root path
58-
it('should still use String.split() in the root directory', function() {
59-
assert.equal(resolve('/node_modules'), '');
60-
});
61-
62103
// Check unexpected path
63104
it('should use require.main.filename on unexpected input', function() {
64105
var cases = [

0 commit comments

Comments
 (0)