Skip to content

Commit eaa2863

Browse files
committed
[INTERNAL] npm t8r: Add includeDeduped option
When set to true, deduped modules are still included in the tree rather than silently ignored. This is usefull when analyzing a projects dependency tree. However most modules like builder and server do not really care about deduped modules.
1 parent 84f7b25 commit eaa2863

File tree

4 files changed

+293
-175
lines changed

4 files changed

+293
-175
lines changed

lib/normalizer.js

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ const projectPreprocessor = require("./projectPreprocessor");
88
* @module normalizer/normalizer
99
*/
1010
const Normalizer = {
11-
1211
/**
1312
* Generates a project and dependency tree via translators and configures all projects via the projectPreprocessor
1413
*
15-
* @param {Object} options Options
16-
* @param {string} options.cwd Current working directory
17-
* @param {string} options.configPath Path to configuration file
18-
* @param {string} options.translator Translator to use
14+
* @param {Object} [options]
15+
* @param {string} [options.cwd] Current working directory
16+
* @param {string} [options.configPath] Path to configuration file
17+
* @param {string} [options.translator] Translator to use
1918
* @returns {Promise} Promise resolving to tree object
2019
*/
2120
generateProjectTree: async function(options = {}) {
@@ -26,40 +25,42 @@ const Normalizer = {
2625
}
2726
return projectPreprocessor.processTree(tree);
2827
},
28+
2929
/**
3030
* Generates a project and dependency tree via translators
3131
*
32-
* @param {Object} options Options
33-
* @param {string} options.cwd Current working directory
34-
* @param {string} options.configPath Path to configuration file
35-
* @param {string} options.translator Translator to use
32+
* @param {Object} [options]
33+
* @param {string} [options.cwd=.] Current working directory
34+
* @param {string} [options.translator=npm] Translator to use
35+
* @param {object} [options.translatorOptions] Options to pass to translator
3636
* @returns {Promise} Promise resolving to tree object
3737
*/
38-
generateDependencyTree: async function(options = {}) {
38+
generateDependencyTree: async function({cwd = ".", translator="npm", translatorOptions={}} = {}) {
39+
// TODO NEXT MAJOR: Rename "translator" option to "translatorName"
3940
log.verbose("Building dependency tree...");
40-
const cwd = options && options.cwd || ".";
4141

42-
let translatorName = "npm"; // Default is npm translator
4342
let translatorParams = [];
44-
if (options.translator) {
45-
const translatorOptions = options.translator.split(":");
46-
translatorName = translatorOptions[0];
47-
translatorParams = translatorOptions.slice(1);
43+
let translatorName = translator;
44+
if (translator.indexOf(":") !== -1) {
45+
translatorParams = translator.split(":");
46+
translatorName = translatorParams[0];
47+
translatorParams = translatorParams.slice(1);
4848
}
4949

50-
let translator;
50+
let translatorModule;
5151
switch (translatorName) {
5252
case "static":
53-
translator = require("./translators/static");
53+
translatorModule = require("./translators/static");
5454
break;
5555
case "npm":
56-
translator = require("./translators/npm");
56+
translatorModule = require("./translators/npm");
5757
break;
5858
default:
5959
return Promise.reject(new Error(`Unknown translator ${translatorName}`));
6060
}
6161

62-
return translator.generateDependencyTree(cwd, translatorParams);
62+
translatorOptions.parameters = translatorParams;
63+
return translatorModule.generateDependencyTree(cwd, translatorOptions);
6364
}
6465
};
6566

lib/translators/npm.js

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ const resolveModulePath = promisify(require("resolve"));
99
const parentNameRegExp = new RegExp(/:([^:]+):$/i);
1010

1111
class NpmTranslator {
12-
constructor() {
12+
constructor({includeDeduped}) {
1313
this.projectCache = {};
1414
this.projectsWoUi5Deps = [];
1515
this.pendingDeps = {};
16+
this.includeDeduped = includeDeduped;
1617
}
1718

1819
/*
@@ -171,15 +172,21 @@ class NpmTranslator {
171172
// Check whether modules has already been processed in the current subtree (indicates a loop)
172173
if (parentPath.indexOf(`:${moduleName}:`) !== -1) {
173174
// This is a loop => abort further processing
174-
return cache.pPkg.then((pkg) => {
175-
return [{
176-
id: moduleName,
177-
version: pkg.version,
178-
path: modulePath,
179-
dependencies: [],
180-
deduped: true
181-
}];
182-
});
175+
if (this.includeDeduped) {
176+
// Add module marked as deduped
177+
return cache.pPkg.then((pkg) => {
178+
return {
179+
id: moduleName,
180+
version: pkg.version,
181+
path: modulePath,
182+
dependencies: [],
183+
deduped: true
184+
};
185+
});
186+
} else {
187+
// Ignore this dependency
188+
return Promise.resolve(null);
189+
}
183190
} else {
184191
return cache.pProject;
185192
}
@@ -312,15 +319,18 @@ class NpmTranslator {
312319
const parent = this.pendingDeps[project.id].parents[i];
313320
// Check whether modules has already been processed in the current subtree (indicates a loop)
314321
if (parent.path.indexOf(`:${project.id}:`) !== -1) {
315-
// This is a loop => abort further processing
316-
const dedupedProject = {
317-
id: project.id,
318-
version: project.version,
319-
path: project.path,
320-
dependencies: [],
321-
deduped: true
322-
};
323-
parent.project.dependencies.push(dedupedProject);
322+
// This is a loop
323+
if (this.includeDeduped) {
324+
// Add module marked as deduped
325+
const dedupedProject = {
326+
id: project.id,
327+
version: project.version,
328+
path: project.path,
329+
dependencies: [],
330+
deduped: true
331+
};
332+
parent.project.dependencies.push(dedupedProject);
333+
} // else: do nothing
324334
} else {
325335
parent.project.dependencies.push(project);
326336
}
@@ -401,9 +411,11 @@ module.exports = {
401411
* Generates a dependency tree for npm projects
402412
*
403413
* @param {string} dirPath Project path
414+
* @param {object} [options]
415+
* @param {boolean} [options.includeDeduped=false]
404416
* @returns {Promise} Promise resolving with a dependency tree
405417
*/
406-
generateDependencyTree(dirPath) {
407-
return new NpmTranslator().generateDependencyTree(dirPath);
418+
generateDependencyTree(dirPath, options = {includeDeduped: false}) {
419+
return new NpmTranslator(options).generateDependencyTree(dirPath);
408420
}
409421
};

lib/translators/static.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ const parseYaml = require("js-yaml").safeLoad;
1414
* This feature is <b>EXPERIMENTAL</b> and used for testing purposes only.
1515
*
1616
* @param {string} dirPath Project path
17-
* @param {Array} [translatorOptions] Configuration options
17+
* @param {object} [options]
18+
* @param {Array} [options.parameters] CLI configuration options
1819
* @returns {Promise} Promise resolving with a dependency tree
1920
*/
20-
function generateDependencyTree(dirPath, translatorOptions = []) {
21-
const depFilePath = translatorOptions[0] || path.join(dirPath, "projectDependencies.yaml");
21+
function generateDependencyTree(dirPath, options = {}) {
22+
// TODO NEXT MAJOR: "options" used to be the the parameters array. We check for that here to stay compatible:
23+
const parameters = Array.isArray(options) ? options : options.parameters;
24+
const depFilePath = parameters && parameters[0] || path.join(dirPath, "projectDependencies.yaml");
2225

2326
return new Promise(function(resolve, reject) {
2427
fs.readFile(depFilePath, function(err, buffer) {

0 commit comments

Comments
 (0)