Fix scoped symlink module resolution (#1482)

Summary:
Fixes https://github.com/facebook/flipper/issues/1481

## Changelog

Fix symlinked scoped module resolving to outer directory

Pull Request resolved: https://github.com/facebook/flipper/pull/1482

Test Plan:
Added one more case to the existing test case for `getWatchFolders.ts`

```
❯ yarn run test:debug getWatchFolders
yarn run v1.22.4
$ yarn build:pkg && node --inspect node_modules/.bin/jest --runInBand getWatchFolders
$ cd pkg && yarn build
$ tsc -b
Debugger listening on ws://127.0.0.1:9229/41e16e0b-8a44-42fe-93ac-9dd9d06e418d
For help, see: https://nodejs.org/en/docs/inspector
 PASS  pkg-lib/src/__tests__/getWatchFolders.node.ts
  getWatchFolders
    ✓ getWatchFolders correctly resolves symlinked packages (12 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 passed, 1 total
Time:        2.358 s
Ran all test suites matching /getWatchFolders/i.
{emoji:2728}  Done in 8.60s.
```

Reviewed By: mweststrate

Differential Revision: D23293357

Pulled By: nikoant

fbshipit-source-id: de2a506693727489238c6f6ec62d07526f8f0c69
This commit is contained in:
Rakha Kanz Kautsar
2020-08-24 06:12:40 -07:00
committed by Facebook GitHub Bot
parent 8a5860cb78
commit 573bf8a940
2 changed files with 22 additions and 4 deletions

View File

@@ -44,6 +44,11 @@ describe('getWatchFolders', () => {
fb_plugin_module_2: mockfs.symlink({
path: '../plugins/fb/fb_plugin_module_2',
}),
'@scoped': {
local_module_3: mockfs.symlink({
path: '../../local_module_3',
}),
},
},
local_module_1: {
'package.json': '{"dependencies": {"installed_module_1": "1.0.0"}}',
@@ -52,9 +57,13 @@ describe('getWatchFolders', () => {
'package.json':
'{"dependencies": {"fb_plugin_module_1": "1.0.0", "plugin_module_1": "1.0.0"}}',
},
local_module_3: {
'package.json': '{"dependencies": {"installed_module_1": "1.0.0"}}',
},
plugins: {
plugin_module_1: {
'package.json': '{"dependencies": {"local_module_2": "1.0.0"}}',
'package.json':
'{"dependencies": {"local_module_2": "1.0.0", "@scoped/local_module_3": "1.0.0"}}',
},
plugin_module_2: {
'package.json': '{"dependencies": {"fb_plugin_module_1": "1.0.0"}}',
@@ -102,6 +111,7 @@ describe('getWatchFolders', () => {
"/test/root/plugins/fb/node_modules",
"/test/root/plugins/plugin_module_1",
"/test/root/plugins/plugin_module_2",
"/test/root/local_module_3",
]
`);
} finally {

View File

@@ -36,15 +36,23 @@ export default async (packageDir: string): Promise<string[]> => {
if (await fs.pathExists(nodeModulesDir)) {
watchDirs.add(nodeModulesDir);
for (const moduleName of dependenciesSet) {
const isModuleNameScoped = moduleName.includes('/');
const fullModulePath = path.join(nodeModulesDir, moduleName);
if (await fs.pathExists(fullModulePath)) {
dependenciesSet.delete(moduleName);
const stat = await fs.lstat(fullModulePath);
if (stat.isSymbolicLink()) {
const targetDir = await fs.readlink(fullModulePath);
const absoluteTargetDir = path.isAbsolute(targetDir)
? targetDir
: path.resolve(nodeModulesDir, targetDir);
let absoluteTargetDir;
if (path.isAbsolute(targetDir)) {
absoluteTargetDir = targetDir;
} else if (isModuleNameScoped) {
const scope = moduleName.split('/')[0];
const scopeDir = path.join(nodeModulesDir, scope);
absoluteTargetDir = path.resolve(scopeDir, targetDir);
} else {
absoluteTargetDir = path.resolve(nodeModulesDir, targetDir);
}
if (!processedPackages.has(absoluteTargetDir)) {
packagesToProcess.push(absoluteTargetDir);
processedPackages.add(absoluteTargetDir);