From ee998b9565066e8051d351bcb7bf16f57d442b75 Mon Sep 17 00:00:00 2001 From: ChidoW Date: Fri, 30 Jun 2023 08:12:09 +0200 Subject: [PATCH 1/7] catering for nested/local node_modules --- index.js | 25 ++++++++++++++++++ test/test.mjs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/index.js b/index.js index 9199268..f0f95f4 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ 'use strict'; const fs = require('node:fs'); +const path = require('node:path'); const { debuglog } = require('node:util'); const cabinet = require('filing-cabinet'); const precinct = require('precinct'); @@ -161,6 +162,7 @@ function traverse(config = {}) { for (const dependency of dependencies) { const localConfig = config.clone(); localConfig.filename = dependency; + localConfig.directory = getDirectory(localConfig); if (localConfig.isListForm) { for (const item of traverse(localConfig)) { @@ -192,3 +194,26 @@ function dedupeNonExistent(nonExistent) { i++; } } + +//If the file is in a node module, use the root directory of the module +function getDirectory(localConfig){ + function _getProjectPath(filename) { + try{ + const nodeModuleParts = filename.split('node_modules') + const packageSubPathPath = nodeModuleParts.pop().split(path.sep).filter(function(v){ return !!v}) + const packageName = packageSubPathPath[0].startsWith("@") ? `${packageSubPathPath[0]}${path.sep}${packageSubPathPath[1]}` : packageSubPathPath[0] + + return path.join(...nodeModuleParts, 'node_modules', packageName) + } + catch(err){ + debug(`Could not determine the root directory of package file ${filename}. Using default`); + return null + } + } + + if (!localConfig.filename.includes('node_modules')){ + return localConfig.directory + } + + return _getProjectPath(path.dirname(localConfig.filename)) || localConfig.directory +} \ No newline at end of file diff --git a/test/test.mjs b/test/test.mjs index d38cf33..4666cdb 100644 --- a/test/test.mjs +++ b/test/test.mjs @@ -472,6 +472,79 @@ describe('dependencyTree', () => { }); }); + describe("It uses package specific node_module directory when resolving package dependencies", () => { + testTreesForFormat('commonjs'); + + it('It can find sub package in node module package', () => { + mockfs({ + [path.join(__dirname, '/es6')]: { + 'module.entry.js': 'import * as module from "parent_module_a"', + node_modules: { // eslint-disable-line camelcase + 'parent_module_a': { + 'index.main.js': 'import * as child_module from "child_node_module"; module.exports = child_module;', + 'package.json': '{ "main": "index.main.js"}', + node_modules: { + child_node_module: { + 'index.main.js': 'module.exports = "child_node_module_of_parent_a"', + 'package.json': '{ "main": "index.main.js"}', + } + } + } + } + } + }); + + const directory = path.join(__dirname, '/es6'); + const filename = path.normalize(`${directory}/module.entry.js`); + + const treeList = dependencyTree({ + filename, + directory, + isListForm: true + }); + + assert.ok(treeList.includes(path.normalize(`${directory}/node_modules/parent_module_a/node_modules/child_node_module/index.main.js`))); + }); + + + it('it usues correct version of sub package in node module package', () => { + mockfs({ + [path.join(__dirname, '/es6')]: { + 'module.entry.js': 'import * as module from "parent_module_a"', + node_modules: { // eslint-disable-line camelcase + child_node_module: { + 'index.main.js': 'module.exports = "child_node_module"', + 'package.json': '{ "main": "index.main.js", "version": "2.0.0"}', + }, + parent_module_a: { + 'index.main.js': 'import * as child_module from "child_node_module"; module.exports = child_module;', + 'package.json': '{ "main": "index.main.js"}', + node_modules: { + child_node_module: { + 'index.main.js': 'module.exports = "child_node_module_of_parent_a"', + 'package.json': '{ "main": "index.main.js", "version": "1.0.0"}', + } + } + } + } + } + }); + + const directory = path.join(__dirname, '/es6'); + const filename = path.normalize(`${directory}/module.entry.js`); + + const treeList = dependencyTree({ + filename, + directory, + isListForm: true + }); + + assert.ok(!treeList.includes(path.normalize(`${directory}/node_modules/child_node_module/index.main.js`))); + assert.ok(treeList.includes(path.normalize(`${directory}/node_modules/parent_module_a/node_modules/child_node_module/index.main.js`))); + + }); + }) + describe('module formats', () => { describe('amd', () => { testTreesForFormat('amd'); From bb9551ec232072ce2ccc5b597f593d548d2cf88f Mon Sep 17 00:00:00 2001 From: ChidoW Date: Sat, 1 Jul 2023 17:40:32 +0200 Subject: [PATCH 2/7] linting --- index.js | 33 ++++++++++++++++----------------- test/test.mjs | 28 +++++++++++++--------------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/index.js b/index.js index f0f95f4..04cc38f 100644 --- a/index.js +++ b/index.js @@ -195,25 +195,24 @@ function dedupeNonExistent(nonExistent) { } } -//If the file is in a node module, use the root directory of the module -function getDirectory(localConfig){ +// If the file is in a node module, use the root directory of the module +function getDirectory(localConfig) { function _getProjectPath(filename) { - try{ - const nodeModuleParts = filename.split('node_modules') - const packageSubPathPath = nodeModuleParts.pop().split(path.sep).filter(function(v){ return !!v}) - const packageName = packageSubPathPath[0].startsWith("@") ? `${packageSubPathPath[0]}${path.sep}${packageSubPathPath[1]}` : packageSubPathPath[0] - - return path.join(...nodeModuleParts, 'node_modules', packageName) - } - catch(err){ - debug(`Could not determine the root directory of package file ${filename}. Using default`); - return null - } + try { + const nodeModuleParts = filename.split('node_modules'); + const packageSubPathPath = nodeModuleParts.pop().split(path.sep).filter(Boolean); + const packageName = packageSubPathPath[0].startsWith('@') ? `${packageSubPathPath[0]}${path.sep}${packageSubPathPath[1]}` : packageSubPathPath[0]; + + return path.join(...nodeModuleParts, 'node_modules', packageName); + } catch { + debug(`Could not determine the root directory of package file ${filename}. Using default`); + return null; + } } - if (!localConfig.filename.includes('node_modules')){ - return localConfig.directory + if (!localConfig.filename.includes('node_modules')) { + return localConfig.directory; } - return _getProjectPath(path.dirname(localConfig.filename)) || localConfig.directory -} \ No newline at end of file + return _getProjectPath(path.dirname(localConfig.filename)) || localConfig.directory; +} diff --git a/test/test.mjs b/test/test.mjs index 4666cdb..64661e4 100644 --- a/test/test.mjs +++ b/test/test.mjs @@ -472,7 +472,7 @@ describe('dependencyTree', () => { }); }); - describe("It uses package specific node_module directory when resolving package dependencies", () => { + describe('It uses package specific node_module directory when resolving package dependencies', () => { testTreesForFormat('commonjs'); it('It can find sub package in node module package', () => { @@ -480,13 +480,13 @@ describe('dependencyTree', () => { [path.join(__dirname, '/es6')]: { 'module.entry.js': 'import * as module from "parent_module_a"', node_modules: { // eslint-disable-line camelcase - 'parent_module_a': { + parent_module_a: { // eslint-disable-line camelcase 'index.main.js': 'import * as child_module from "child_node_module"; module.exports = child_module;', 'package.json': '{ "main": "index.main.js"}', - node_modules: { - child_node_module: { + node_modules: { // eslint-disable-line camelcase + child_node_module: { // eslint-disable-line camelcase 'index.main.js': 'module.exports = "child_node_module_of_parent_a"', - 'package.json': '{ "main": "index.main.js"}', + 'package.json': '{ "main": "index.main.js"}' } } } @@ -506,23 +506,22 @@ describe('dependencyTree', () => { assert.ok(treeList.includes(path.normalize(`${directory}/node_modules/parent_module_a/node_modules/child_node_module/index.main.js`))); }); - it('it usues correct version of sub package in node module package', () => { mockfs({ [path.join(__dirname, '/es6')]: { 'module.entry.js': 'import * as module from "parent_module_a"', node_modules: { // eslint-disable-line camelcase - child_node_module: { + child_node_module: { // eslint-disable-line camelcase 'index.main.js': 'module.exports = "child_node_module"', - 'package.json': '{ "main": "index.main.js", "version": "2.0.0"}', + 'package.json': '{ "main": "index.main.js", "version": "2.0.0"}' }, - parent_module_a: { + parent_module_a: { // eslint-disable-line camelcase 'index.main.js': 'import * as child_module from "child_node_module"; module.exports = child_module;', 'package.json': '{ "main": "index.main.js"}', - node_modules: { - child_node_module: { + node_modules: { // eslint-disable-line camelcase + child_node_module: { // eslint-disable-line camelcase 'index.main.js': 'module.exports = "child_node_module_of_parent_a"', - 'package.json': '{ "main": "index.main.js", "version": "1.0.0"}', + 'package.json': '{ "main": "index.main.js", "version": "1.0.0"}' } } } @@ -541,10 +540,9 @@ describe('dependencyTree', () => { assert.ok(!treeList.includes(path.normalize(`${directory}/node_modules/child_node_module/index.main.js`))); assert.ok(treeList.includes(path.normalize(`${directory}/node_modules/parent_module_a/node_modules/child_node_module/index.main.js`))); - }); - }) - + }); + describe('module formats', () => { describe('amd', () => { testTreesForFormat('amd'); From bef160c5d0a817a1ae38c2037e2977e868bf4b26 Mon Sep 17 00:00:00 2001 From: ChidoW Date: Tue, 4 Jul 2023 13:22:55 +0200 Subject: [PATCH 3/7] reconstructing path appropriately --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 04cc38f..80b2333 100644 --- a/index.js +++ b/index.js @@ -203,7 +203,7 @@ function getDirectory(localConfig) { const packageSubPathPath = nodeModuleParts.pop().split(path.sep).filter(Boolean); const packageName = packageSubPathPath[0].startsWith('@') ? `${packageSubPathPath[0]}${path.sep}${packageSubPathPath[1]}` : packageSubPathPath[0]; - return path.join(...nodeModuleParts, 'node_modules', packageName); + return path.normalize([...nodeModuleParts, `${path.sep}${packageName}`].join('node_modules')); } catch { debug(`Could not determine the root directory of package file ${filename}. Using default`); return null; From 9fab66ded14b6ab5997680057a12e3c62c8583cd Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Sun, 23 Jul 2023 08:21:55 +0300 Subject: [PATCH 4/7] Update test.mjs --- test/test.mjs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/test.mjs b/test/test.mjs index 64661e4..ce54991 100644 --- a/test/test.mjs +++ b/test/test.mjs @@ -479,12 +479,12 @@ describe('dependencyTree', () => { mockfs({ [path.join(__dirname, '/es6')]: { 'module.entry.js': 'import * as module from "parent_module_a"', - node_modules: { // eslint-disable-line camelcase - parent_module_a: { // eslint-disable-line camelcase + node_modules: { + parent_module_a: { 'index.main.js': 'import * as child_module from "child_node_module"; module.exports = child_module;', 'package.json': '{ "main": "index.main.js"}', - node_modules: { // eslint-disable-line camelcase - child_node_module: { // eslint-disable-line camelcase + node_modules: { + child_node_module: { 'index.main.js': 'module.exports = "child_node_module_of_parent_a"', 'package.json': '{ "main": "index.main.js"}' } @@ -510,16 +510,16 @@ describe('dependencyTree', () => { mockfs({ [path.join(__dirname, '/es6')]: { 'module.entry.js': 'import * as module from "parent_module_a"', - node_modules: { // eslint-disable-line camelcase - child_node_module: { // eslint-disable-line camelcase + node_modules: { + child_node_module: { 'index.main.js': 'module.exports = "child_node_module"', 'package.json': '{ "main": "index.main.js", "version": "2.0.0"}' }, - parent_module_a: { // eslint-disable-line camelcase + parent_module_a: { 'index.main.js': 'import * as child_module from "child_node_module"; module.exports = child_module;', 'package.json': '{ "main": "index.main.js"}', - node_modules: { // eslint-disable-line camelcase - child_node_module: { // eslint-disable-line camelcase + node_modules: { + child_node_module: { 'index.main.js': 'module.exports = "child_node_module_of_parent_a"', 'package.json': '{ "main": "index.main.js", "version": "1.0.0"}' } From c0bea6c6cb75b5128f24fc3b0280b86db73638d6 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Sat, 8 Feb 2025 12:02:28 +0200 Subject: [PATCH 5/7] Update index.js --- index.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/index.js b/index.js index 3407732..7b3ca6e 100644 --- a/index.js +++ b/index.js @@ -198,22 +198,22 @@ function dedupeNonExistent(nonExistent) { // If the file is in a node module, use the root directory of the module function getDirectory(localConfig) { - function _getProjectPath(filename) { - try { - const nodeModuleParts = filename.split('node_modules'); - const packageSubPathPath = nodeModuleParts.pop().split(path.sep).filter(Boolean); - const packageName = packageSubPathPath[0].startsWith('@') ? `${packageSubPathPath[0]}${path.sep}${packageSubPathPath[1]}` : packageSubPathPath[0]; - - return path.normalize([...nodeModuleParts, `${path.sep}${packageName}`].join('node_modules')); - } catch { - debug(`Could not determine the root directory of package file ${filename}. Using default`); - return null; - } - } - if (!localConfig.filename.includes('node_modules')) { return localConfig.directory; } - return _getProjectPath(path.dirname(localConfig.filename)) || localConfig.directory; + return getProjectPath(path.dirname(localConfig.filename)) || localConfig.directory; +} + +function getProjectPath(filename) { + try { + const nodeModuleParts = filename.split('node_modules'); + const packageSubPathPath = nodeModuleParts.pop().split(path.sep).filter(Boolean); + const packageName = packageSubPathPath[0].startsWith('@') ? `${packageSubPathPath[0]}${path.sep}${packageSubPathPath[1]}` : packageSubPathPath[0]; + + return path.normalize([...nodeModuleParts, `${path.sep}${packageName}`].join('node_modules')); + } catch { + debug(`Could not determine the root directory of package file ${filename}. Using default`); + return null; + } } From 9b647d3d3c566b6f873c49b3993df76450ffba9d Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Sat, 8 Feb 2025 12:04:39 +0200 Subject: [PATCH 6/7] Update test.mjs --- test/test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.mjs b/test/test.mjs index 57f2173..fbd94ec 100644 --- a/test/test.mjs +++ b/test/test.mjs @@ -506,7 +506,7 @@ describe('dependencyTree', () => { assert.ok(treeList.includes(path.normalize(`${directory}/node_modules/parent_module_a/node_modules/child_node_module/index.main.js`))); }); - it('it usues correct version of sub package in node module package', () => { + it('it uses correct version of sub package in node module package', () => { mockfs({ [path.join(__dirname, '/es6')]: { 'module.entry.js': 'import * as module from "parent_module_a"', From b7d0333fcb238bcbbabc7621d3ab258c6dc1e1d1 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Sat, 8 Feb 2025 12:06:29 +0200 Subject: [PATCH 7/7] Update test.mjs --- test/test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.mjs b/test/test.mjs index fbd94ec..8a97d8d 100644 --- a/test/test.mjs +++ b/test/test.mjs @@ -472,10 +472,10 @@ describe('dependencyTree', () => { }); }); - describe('It uses package specific node_module directory when resolving package dependencies', () => { + describe('it uses package specific node_module directory when resolving package dependencies', () => { testTreesForFormat('commonjs'); - it('It can find sub package in node module package', () => { + it('it can find sub package in node module package', () => { mockfs({ [path.join(__dirname, '/es6')]: { 'module.entry.js': 'import * as module from "parent_module_a"',