rev-dep 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -378,12 +378,12 @@ Checks if a filePath is required from entryPoint(s) and prints the resolution pa
378
378
  #### Usage
379
379
 
380
380
  ```sh
381
- rev-dep resolve <filePath> [entryPoints...] [options]
381
+ rev-dep resolve <filePathOrNodeModuleName> [entryPoints...] [options]
382
382
  ```
383
383
 
384
384
  #### Arguments
385
385
 
386
- - `filePath` - Path to a file that should be resolved in entry points (**required**)
386
+ - `filePathOrNodeModuleName` - undefined (**required**)
387
387
  - `entryPoints...` - List of entry points to look for file (_optional_)
388
388
 
389
389
  #### Options
@@ -395,6 +395,7 @@ rev-dep resolve <filePath> [entryPoints...] [options]
395
395
  - `-cs, --compactSummary` - print a compact summary of reverse resolution with a count of found paths (_optional_)
396
396
  - `-a, --all` - finds all paths combination of a given dependency. Might work very slow or crash for some projects due to heavy usage of RAM (_optional_)
397
397
  - `-ntp --notTraversePaths <paths...>` - Specify file paths relative to resolution root, that should not be traversed when finding dependency path (_optional_)
398
+ - `-inm --includeNodeModules` - Whether to include node modules in dependency graph. Has to be provided to resolve node module. (_optional_)
398
399
  - `-iti --ignoreTypesImports` - Use this flag to not follow type imports when resolving modules (_optional_)
399
400
 
400
401
  ### Command `entry-points`
@@ -0,0 +1,5 @@
1
+ export declare const babelParsingOptions: {
2
+ errorRecovery: boolean;
3
+ sourceType: string;
4
+ plugins: string[];
5
+ };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.babelParsingOptions = void 0;
4
+ exports.babelParsingOptions = {
5
+ errorRecovery: true,
6
+ sourceType: 'module',
7
+ plugins: [
8
+ 'jsx',
9
+ 'typescript',
10
+ 'objectRestSpread',
11
+ 'classProperties',
12
+ 'asyncGenerators',
13
+ 'decorators-legacy'
14
+ ]
15
+ };
@@ -0,0 +1 @@
1
+ export function groupBy(arr: any, property: any): any;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.groupBy = void 0;
4
+ function groupBy(arr, property) {
5
+ return arr.reduce((result, obj) => {
6
+ const key = obj[property];
7
+ if (!result[key]) {
8
+ result[key] = [];
9
+ }
10
+ result[key].push(obj);
11
+ return result;
12
+ }, {});
13
+ }
14
+ exports.groupBy = groupBy;
@@ -4,19 +4,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const node_path = require('path');
5
5
  const fs = require('fs');
6
6
  const parser = require('@babel/parser');
7
- const template = require('@babel/template').default;
8
7
  const utils_1 = require("../lib/utils");
8
+ const template_1 = require("./template");
9
9
  const SKIP = Symbol('SKIP');
10
+ const babelParsingOptions_1 = require("./babelParsingOptions");
11
+ const groupBy_1 = require("./groupBy");
10
12
  /**
11
13
  *
12
14
  * TODO
13
- * - support imports from baseUrl from TS config
14
- * - persist the original import alias
15
- * - group named imports from the same file
16
- * - handle type imports properly - we don't preserve the import was a type import
17
- * - If that has to be used as a codemod, we have to refactor to make sure we don't change structure of other parts of the code and we preserve imports order
15
+ * + If that has to be used as a codemod, we have to refactor to make sure we don't change structure of other parts of the code and we preserve imports order
16
+ * +- group named imports from the same file
17
+ * + support imports from baseUrl from TS config -> relative | baseUrl | alias
18
+ * + persist the original import alias
19
+ * + allow for a list of files to rewire
20
+ * + use cache for not resolved modules as well
21
+ * + handle type imports properly - we don't preserve the import was a type import
22
+ * + do not touch imports that don't need changes
18
23
  */
19
- module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsConfig)() }) {
24
+ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsConfig)(), cache = new Map(), includeBarrelExportFiles, excludeBarrelExportFiles = [] }) {
20
25
  const root = tsConfigPath.replace('/tsconfig.json', '');
21
26
  const tsConfigContent = fs.readFileSync(tsConfigPath).toString();
22
27
  const tsConfigContentCleaned = tsConfigContent
@@ -26,9 +31,21 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
26
31
  const tsConfig = JSON.parse(tsConfigContentCleaned);
27
32
  const aliases = tsConfig.compilerOptions.paths;
28
33
  const aliasesKeys = Object.keys(aliases);
29
- const aliasesRegexes = Object.keys(aliases).map((alias) => {
30
- return new RegExp(`^${alias.replace('*', '(.)+')}$`);
31
- });
34
+ const makeRegExpFromAliasExpression = (aliasExpression) => {
35
+ return new RegExp(`^${aliasExpression.replace('*', '(.+)')}$`);
36
+ };
37
+ const aliasesRegexes = Object.keys(aliases).map(makeRegExpFromAliasExpression);
38
+ // TODO we assume that only one aliased path can exist
39
+ const aliasedPathRegExps = Object.values(aliases).map(([fistAliasedPath]) => makeRegExpFromAliasExpression(fistAliasedPath));
40
+ const interpolateAliasWithPath = (aliasKey, aliasedPathRegExp, resolvedSourcePathRelativeToBaseUrl) => {
41
+ const [_, ...groups] = aliasedPathRegExp.exec(resolvedSourcePathRelativeToBaseUrl);
42
+ const aliasParts = aliasKey.split('*');
43
+ const interpolatedAlias = aliasParts.reduce((mergedPath, aliasPart, idx) => {
44
+ var _a;
45
+ return `${mergedPath}${aliasPart}${(_a = groups[idx]) !== null && _a !== void 0 ? _a : ''}`;
46
+ }, '');
47
+ return interpolatedAlias;
48
+ };
32
49
  let baseUrlDirs = [];
33
50
  const baseUrl = tsConfig.compilerOptions.baseUrl;
34
51
  if (baseUrl) {
@@ -39,10 +56,10 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
39
56
  .map((dirent) => dirent.name + '/');
40
57
  baseUrlDirs = dirNames;
41
58
  }
42
- const cache = new Map();
43
59
  const getFile = (original, paths) => {
44
60
  if (paths.length === 0) {
45
- throw new Error('Cannot resolve import ' + original);
61
+ console.warn('Cannot resolve import ' + original);
62
+ return null;
46
63
  }
47
64
  const path = paths[0];
48
65
  try {
@@ -52,18 +69,18 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
52
69
  return getFile(original, paths.slice(1));
53
70
  }
54
71
  };
55
- const isPathNotANodeModule = (path) => {
72
+ const shouldPathBeAnalyzed = (path) => {
56
73
  const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(path));
57
74
  const isRelative = path.startsWith('./') || path.startsWith('../');
58
75
  const isAbsolute = path.startsWith('/');
59
76
  const isBaseUrlPath = baseUrlDirs.some((dir) => path.startsWith(dir));
60
77
  return aliasRegexIdx > -1 || isRelative || isAbsolute || isBaseUrlPath;
61
78
  };
62
- const cacheKey = (identifier, filePath) => `${identifier}-${filePath}`;
79
+ const getCacheKey = (identifier, filePath) => `${identifier}-${filePath}`;
63
80
  const lookup = (identifier, filePath, cwd) => {
64
- const cached = cache.get(cacheKey(identifier, filePath));
81
+ const cached = cache.get(getCacheKey(identifier, filePath));
65
82
  if (cached) {
66
- return cached;
83
+ return { ...cached, isCached: true };
67
84
  }
68
85
  const withExtension = /(\.ts|\.tsx)$/.test(filePath)
69
86
  ? [filePath]
@@ -77,117 +94,124 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
77
94
  `${filePath}/index.js`,
78
95
  `${filePath}/index.jsx`
79
96
  ];
80
- const [resolvedFilePath, file] = getFile(filePath, withExtension);
81
- const ast = parser.parse(file, {
82
- sourceType: 'module',
83
- plugins: [
84
- 'jsx',
85
- 'typescript',
86
- 'objectRestSpread',
87
- 'classProperties',
88
- 'asyncGenerators',
89
- 'decorators-legacy'
90
- ]
91
- });
92
- /**
93
- * {
94
- * identifier?: string,
95
- * source: string
96
- * }
97
- */
98
- const toLookup = [];
99
- let resolvedAs = null;
100
- ast.program.body.forEach((declaration) => {
101
- var _a, _b, _c;
102
- if (resolvedAs === null) {
103
- if (types.isExportNamedDeclaration(declaration)) {
104
- if (((_a = declaration.declaration) === null || _a === void 0 ? void 0 : _a.type.startsWith('TS')) &&
105
- ((_b = declaration.declaration) === null || _b === void 0 ? void 0 : _b.type.endsWith('Declaration'))) {
106
- const typeName = declaration.declaration.id.name;
107
- if (typeName === identifier) {
108
- resolvedAs = {
109
- // This should be 'type' of something else, but ESLint would handle that
110
- type: 'named',
111
- identifier,
112
- source: filePath
113
- };
97
+ const fileInfo = getFile(filePath, withExtension);
98
+ if (!fileInfo) {
99
+ return { resolvedAs: null, visitedFiles: [] };
100
+ }
101
+ const [resolvedFilePath, file] = fileInfo;
102
+ try {
103
+ const ast = parser.parse(file, babelParsingOptions_1.babelParsingOptions);
104
+ /**
105
+ * {
106
+ * identifier?: string,
107
+ * source: string
108
+ * }
109
+ */
110
+ const toLookup = [];
111
+ let resolvedAs = null;
112
+ ast.program.body.forEach((declaration) => {
113
+ var _a, _b, _c;
114
+ if (resolvedAs === null) {
115
+ if (types.isExportNamedDeclaration(declaration)) {
116
+ if (((_a = declaration.declaration) === null || _a === void 0 ? void 0 : _a.type.startsWith('TS')) &&
117
+ ((_b = declaration.declaration) === null || _b === void 0 ? void 0 : _b.type.endsWith('Declaration'))) {
118
+ const typeName = declaration.declaration.id.name;
119
+ if (typeName === identifier) {
120
+ resolvedAs = {
121
+ // This should be 'type' of something else, but ESLint would handle that
122
+ type: 'named',
123
+ identifier,
124
+ source: filePath
125
+ };
126
+ }
114
127
  }
115
- }
116
- else if (types.isVariableDeclaration(declaration.declaration)) {
117
- const hasIdentifier = declaration.declaration.declarations.find((declarator) => {
118
- return declarator.id.name === identifier;
119
- });
120
- if (hasIdentifier) {
121
- resolvedAs = {
122
- type: 'named',
123
- identifier,
124
- source: filePath
125
- };
128
+ else if (types.isVariableDeclaration(declaration.declaration)) {
129
+ const hasIdentifier = declaration.declaration.declarations.find((declarator) => {
130
+ return declarator.id.name === identifier;
131
+ });
132
+ if (hasIdentifier) {
133
+ resolvedAs = {
134
+ type: 'named',
135
+ identifier,
136
+ source: filePath
137
+ };
138
+ }
126
139
  }
127
- }
128
- else if (types.isFunctionDeclaration(declaration.declaration) ||
129
- types.isClassDeclaration(declaration.declaration)) {
130
- if (declaration.declaration.id.name === identifier) {
131
- resolvedAs = {
132
- type: 'named',
133
- identifier,
134
- source: filePath
135
- };
140
+ else if (types.isFunctionDeclaration(declaration.declaration) ||
141
+ types.isClassDeclaration(declaration.declaration)) {
142
+ if (declaration.declaration.id.name === identifier) {
143
+ resolvedAs = {
144
+ type: 'named',
145
+ identifier,
146
+ source: filePath
147
+ };
148
+ }
136
149
  }
137
- }
138
- else {
139
- const source = (_c = declaration.source) === null || _c === void 0 ? void 0 : _c.value;
140
- declaration.specifiers.forEach((specifier) => {
141
- if (types.isExportSpecifier(specifier)) {
142
- if (specifier.exported.name === identifier) {
143
- if (specifier.local.name === 'default' && source) {
144
- resolvedAs = {
145
- type: 'default',
146
- identifier,
147
- source: getModulePath(source, resolvedFilePath, cwd)
148
- };
149
- }
150
- else if (source === undefined) {
151
- resolvedAs = {
152
- type: 'named',
153
- identifier,
154
- source: filePath
155
- };
156
- }
157
- else if (isPathNotANodeModule(source)) {
158
- toLookup.push({
159
- identifier: specifier.local.name,
160
- source: getModulePath(source, resolvedFilePath, cwd)
161
- });
150
+ else {
151
+ const source = (_c = declaration.source) === null || _c === void 0 ? void 0 : _c.value;
152
+ declaration.specifiers.forEach((specifier) => {
153
+ if (types.isExportSpecifier(specifier)) {
154
+ if (specifier.exported.name === identifier) {
155
+ if (specifier.local.name === 'default' && source) {
156
+ resolvedAs = {
157
+ type: 'default',
158
+ identifier,
159
+ source: getModulePath(source, resolvedFilePath, cwd)
160
+ };
161
+ }
162
+ else if (source === undefined) {
163
+ // Here we could check if identifier comes from import statement, and if so, lookup deeper
164
+ resolvedAs = {
165
+ type: 'named',
166
+ identifier,
167
+ source: filePath
168
+ };
169
+ }
170
+ else if (shouldPathBeAnalyzed(source)) {
171
+ toLookup.push({
172
+ identifier: specifier.local.name,
173
+ source: getModulePath(source, resolvedFilePath, cwd)
174
+ });
175
+ }
162
176
  }
163
177
  }
164
- }
178
+ });
179
+ }
180
+ }
181
+ else if (types.isExportAllDeclaration(declaration) &&
182
+ shouldPathBeAnalyzed(declaration.source.value)) {
183
+ toLookup.push({
184
+ identifier,
185
+ source: getModulePath(declaration.source.value, resolvedFilePath, cwd)
165
186
  });
166
187
  }
167
188
  }
168
- else if (types.isExportAllDeclaration(declaration) &&
169
- isPathNotANodeModule(declaration.source.value)) {
170
- toLookup.push({
171
- identifier,
172
- source: getModulePath(declaration.source.value, resolvedFilePath, cwd)
173
- });
174
- }
189
+ });
190
+ if (resolvedAs) {
191
+ return { resolvedAs, visitedFiles: [resolvedAs.source] };
175
192
  }
176
- });
177
- if (resolvedAs) {
178
- return resolvedAs;
193
+ const nestedResult = toLookup
194
+ .map(({ identifier, source }) => lookup(identifier, source, cwd))
195
+ .filter((lookUpResult) => lookUpResult.resolvedAs !== null);
196
+ if (nestedResult[0]) {
197
+ return {
198
+ resolvedAs: nestedResult[0].resolvedAs,
199
+ visitedFiles: [resolvedFilePath, ...nestedResult[0].visitedFiles]
200
+ };
201
+ }
202
+ return { resolvedAs: null, visitedFiles: [] };
203
+ }
204
+ catch (e) {
205
+ console.log('Lookup parse error', filePath, e);
206
+ process.exit(0);
179
207
  }
180
- const nestedResult = toLookup
181
- .map(({ identifier, source }) => lookup(identifier, source, cwd))
182
- .filter(Boolean);
183
- return nestedResult[0];
184
208
  };
185
209
  const getModulePath = (sourcePath, fileName, cwd) => {
186
210
  var _a;
187
211
  const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(sourcePath));
188
212
  const relativeFileName = node_path.relative(cwd, fileName);
189
213
  const aliasKey = aliasesKeys[aliasRegexIdx];
190
- const alias = (_a = aliases[aliasKey]) === null || _a === void 0 ? void 0 : _a[0];
214
+ const alias = (_a = aliases[aliasKey]) === null || _a === void 0 ? void 0 : _a[0]; // TODO we assume that only one aliased path can exist in config
191
215
  const isAbsoluteToBaseDir = baseUrlDirs.some((baseUrlDir) => sourcePath.startsWith(baseUrlDir));
192
216
  let modulePath = '';
193
217
  if (alias) {
@@ -207,115 +231,214 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
207
231
  }
208
232
  return modulePath;
209
233
  };
234
+ const getImportKind = (sourcePath) => {
235
+ const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(sourcePath));
236
+ const isRelative = sourcePath.startsWith('./') || sourcePath.startsWith('../');
237
+ const isBaseUrlPath = baseUrlDirs.some((dir) => sourcePath.startsWith(dir));
238
+ if (aliasRegexIdx > -1) {
239
+ return 'aliased';
240
+ }
241
+ if (isRelative) {
242
+ return 'relative';
243
+ }
244
+ if (isBaseUrlPath) {
245
+ return 'baseUrl';
246
+ }
247
+ throw new Error('Could not determine import kind');
248
+ };
210
249
  return {
211
250
  visitor: {
212
251
  Program() {
213
252
  // console.log('Cache size', cache.size)
214
253
  },
215
- ImportDeclaration(path, { filename }) {
216
- const sourceRelative = (source) => {
217
- const rel = node_path.relative(node_path.dirname(filename), source);
254
+ ImportDeclaration(path, state) {
255
+ const filename = state.filename;
256
+ const getImportSourceFormatted = (resolvedSourcePath, importKind) => {
257
+ const baseDirPath = node_path.join(root, baseUrl);
258
+ if (importKind === 'baseUrl') {
259
+ const relativeToBaseUrl = node_path.relative(baseDirPath, resolvedSourcePath);
260
+ return relativeToBaseUrl;
261
+ }
262
+ if (importKind === 'aliased') {
263
+ const originalSource = path.node.source.value;
264
+ const currentAliasIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(originalSource));
265
+ const resolvedSourcePathRelativeToBaseUrl = resolvedSourcePath
266
+ .replace(baseDirPath, '')
267
+ .replace(/^\//, '');
268
+ // Try to use current alias if it matches new path
269
+ if (currentAliasIdx > -1) {
270
+ const aliasKey = aliasesKeys[currentAliasIdx];
271
+ const aliasedPathRegExp = aliasedPathRegExps[currentAliasIdx];
272
+ if (aliasedPathRegExp.test(resolvedSourcePathRelativeToBaseUrl)) {
273
+ return interpolateAliasWithPath(aliasKey, aliasedPathRegExp, resolvedSourcePathRelativeToBaseUrl);
274
+ }
275
+ }
276
+ // Try finding matching alias
277
+ const newMatchingAliasIndex = aliasedPathRegExps.findIndex((aliasedPathRegexp) => aliasedPathRegexp.test(resolvedSourcePathRelativeToBaseUrl));
278
+ if (newMatchingAliasIndex > -1) {
279
+ const aliasKey = aliasesKeys[newMatchingAliasIndex];
280
+ const aliasedPathRegExp = aliasedPathRegExps[newMatchingAliasIndex];
281
+ return interpolateAliasWithPath(aliasKey, aliasedPathRegExp, resolvedSourcePathRelativeToBaseUrl);
282
+ }
283
+ }
284
+ const rel = node_path.relative(node_path.dirname(filename), resolvedSourcePath);
218
285
  const whatever = rel.startsWith('.') ? rel : './' + rel;
219
286
  // remove file extension
220
287
  return whatever.replace(/\.(ts|js|tsx|jsx|cjs|mjs)$/, '');
221
288
  };
222
289
  const node = path.node;
290
+ const isTypeImport = node.importKind === 'type';
223
291
  const source = node.source;
224
292
  if (source.type !== 'StringLiteral') {
225
293
  return;
226
294
  }
227
- const shouldSkip = node[SKIP] || !isPathNotANodeModule(source.value);
295
+ const shouldSkip = node[SKIP] || !shouldPathBeAnalyzed(source.value);
228
296
  if (shouldSkip) {
229
297
  return;
230
298
  }
299
+ const importKind = getImportKind(source.value);
231
300
  const modulePath = getModulePath(source.value, filename, root);
232
- const defaultSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier');
233
- const namespaceSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportNamespaceSpecifier');
234
- const specifiers = node.specifiers.filter((specifier) => specifier.type === 'ImportSpecifier');
301
+ const defaultSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier' // import $$ from '$$'
302
+ );
303
+ const namespaceSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportNamespaceSpecifier' // import * as $$ from '$$'
304
+ );
305
+ const specifiers = node.specifiers.filter((specifier) => specifier.type === 'ImportSpecifier' // import { $$ } from '$$'
306
+ );
235
307
  const results = specifiers.map((specifier) => {
236
308
  const importedName = specifier.imported.name;
237
309
  const result = lookup(importedName, modulePath, root);
238
- if (!result) {
239
- return {
310
+ if (!(result === null || result === void 0 ? void 0 : result.isCached)) {
311
+ const cacheKey = getCacheKey(importedName, modulePath);
312
+ // console.log('resolved not cached', cacheKey, result)
313
+ const originalImport = {
314
+ identifier: importedName,
315
+ local: specifier.local.name,
316
+ source: source.value // cannot cache non absolute path
317
+ };
318
+ const originalImportToCache = {
240
319
  identifier: importedName,
241
320
  local: specifier.local.name,
242
- source: source.value
321
+ source: modulePath
243
322
  };
323
+ const originalResolution = {
324
+ resolvedAs: originalImportToCache,
325
+ visitedFiles: []
326
+ };
327
+ if (!result.resolvedAs) {
328
+ cache.set(cacheKey, originalResolution);
329
+ return originalImport;
330
+ }
331
+ if (includeBarrelExportFiles &&
332
+ !includeBarrelExportFiles.some((fileThatHasToBeVisited) => result.visitedFiles.includes(fileThatHasToBeVisited))) {
333
+ cache.set(cacheKey, originalResolution);
334
+ return originalImport;
335
+ }
336
+ if (excludeBarrelExportFiles.some((fileThatCannotBeVisited) => result.visitedFiles.includes(fileThatCannotBeVisited))) {
337
+ cache.set(cacheKey, originalResolution);
338
+ return originalImport;
339
+ }
340
+ cache.set(cacheKey, result);
244
341
  }
245
- cache.set(cacheKey(importedName, modulePath), result);
246
342
  return {
247
- ...result,
248
- source: sourceRelative(result.source),
343
+ ...result.resolvedAs,
344
+ source: getImportSourceFormatted(result.resolvedAs.source, importKind),
249
345
  local: specifier.local.name
250
346
  };
251
347
  });
252
348
  const defaultResult = defaultSpecifier
253
349
  ? lookup('default', modulePath, root)
254
350
  : null;
255
- if (defaultResult) {
256
- cache.set(cacheKey('default', modulePath), defaultResult);
351
+ if (defaultResult && !defaultResult.isCached) {
352
+ const cacheKey = getCacheKey('default', modulePath);
353
+ const originalImportToCache = {
354
+ source: modulePath
355
+ };
356
+ const originalResolution = {
357
+ resolvedAs: originalImportToCache,
358
+ visitedFiles: []
359
+ };
360
+ if (!defaultResult.resolvedAs) {
361
+ cache.set(cacheKey, originalResolution);
362
+ }
363
+ else if (includeBarrelExportFiles &&
364
+ !includeBarrelExportFiles.some((fileThatHasToBeVisited) => defaultResult.visitedFiles.includes(fileThatHasToBeVisited))) {
365
+ cache.set(cacheKey, originalResolution);
366
+ }
367
+ else if (excludeBarrelExportFiles.some((fileThatCannotBeVisited) => defaultResult.visitedFiles.includes(fileThatCannotBeVisited))) {
368
+ cache.set(cacheKey, originalResolution);
369
+ }
370
+ else {
371
+ cache.set(cacheKey, defaultResult);
372
+ }
257
373
  }
258
- const buildNamed = template(`
259
- import { %%IMPORT_NAME%% } from %%SOURCE%%;
374
+ const buildNamed = (0, template_1.template)(`
375
+ import { %%IMPORT_NAME%% } from '%%SOURCE%%';
260
376
  `);
261
- const buildNamedWithAlias = template(`
262
- import { %%IMPORTED_NAME%% as %%LOCAL_NAME%% } from %%SOURCE%%;
377
+ const buildNamedWithAlias = (0, template_1.template)(`
378
+ import { %%IMPORTED_NAME%% as %%LOCAL_NAME%% } from '%%SOURCE%%';
263
379
  `);
264
- const buildDefault = template(`
265
- import %%IMPORT_NAME%% from %%SOURCE%%;
380
+ const buildDefault = (0, template_1.template)(`
381
+ import %%IMPORT_NAME%% from '%%SOURCE%%';
266
382
  `);
267
- const buildNamespace = template(`
268
- import * as %%IMPORT_NAME%% from %%SOURCE%%;
383
+ const buildNamespace = (0, template_1.template)(`
384
+ import * as %%IMPORT_NAME%% from '%%SOURCE%%';
269
385
  `);
270
- const defaultImport = defaultResult
386
+ const defaultImport = (defaultResult === null || defaultResult === void 0 ? void 0 : defaultResult.resolvedAs)
271
387
  ? [
272
388
  buildDefault({
273
- IMPORT_NAME: types.identifier(defaultSpecifier.local.name),
274
- SOURCE: types.stringLiteral(sourceRelative(defaultResult.source))
389
+ IMPORT_NAME: defaultSpecifier.local.name,
390
+ SOURCE: getImportSourceFormatted(defaultResult.resolvedAs.source, importKind)
275
391
  })
276
392
  ]
277
393
  : defaultSpecifier
278
394
  ? [
279
395
  buildDefault({
280
- IMPORT_NAME: types.identifier(defaultSpecifier.local.name),
281
- SOURCE: types.stringLiteral(source.value)
396
+ IMPORT_NAME: defaultSpecifier.local.name,
397
+ SOURCE: source.value
282
398
  })
283
399
  ]
284
400
  : [];
285
401
  const namespaceImport = namespaceSpecifier
286
402
  ? [
287
403
  buildNamespace({
288
- IMPORT_NAME: types.identifier(namespaceSpecifier.local.name),
289
- SOURCE: types.stringLiteral(source.value)
404
+ IMPORT_NAME: namespaceSpecifier.local.name,
405
+ SOURCE: source.value
290
406
  })
291
407
  ]
292
408
  : [];
293
- const named = results.map(({ type, identifier, local, source }) => {
294
- if (type === 'default') {
295
- return buildDefault({
296
- IMPORT_NAME: types.identifier(identifier),
297
- SOURCE: types.stringLiteral(source)
298
- });
299
- }
300
- else if (identifier !== local) {
301
- return buildNamedWithAlias({
302
- IMPORTED_NAME: types.identifier(identifier),
303
- LOCAL_NAME: types.identifier(local),
304
- SOURCE: types.stringLiteral(source)
305
- });
306
- }
307
- else {
308
- return buildNamed({
309
- IMPORT_NAME: types.identifier(identifier),
310
- SOURCE: types.stringLiteral(source)
311
- });
312
- }
409
+ const importsFromNamedGroupedBySource = Object.values((0, groupBy_1.groupBy)(results, 'source'));
410
+ const named = importsFromNamedGroupedBySource.map((imports) => {
411
+ const source = imports[0].source;
412
+ const defaultImport = imports.find(({ type }) => type === 'default');
413
+ const nonDefault = imports.filter(({ type }) => type !== 'default');
414
+ const defaultPart = defaultImport
415
+ ? `${defaultImport.identifier}`
416
+ : null;
417
+ const nonDefaultPart = nonDefault.length > 0
418
+ ? nonDefault
419
+ .map(({ identifier, local }) => identifier !== local
420
+ ? `${identifier} as ${local}`
421
+ : identifier)
422
+ .join(', ')
423
+ : null;
424
+ return `import ${isTypeImport ? 'type ' : ''}${defaultPart ? `${defaultPart}${nonDefaultPart ? ', ' : ''}` : ''}${nonDefaultPart ? `{ ${nonDefaultPart} }` : ''} from '${source}';`;
313
425
  });
314
426
  const newImports = [...namespaceImport, ...defaultImport, ...named].map((node) => {
315
- node[SKIP] = true;
316
427
  return node;
317
428
  });
318
- path.replaceWithMultiple(newImports);
429
+ if (!state.file.metadata) {
430
+ state.file.metadata = {};
431
+ }
432
+ if (!state.file.metadata[filename]) {
433
+ state.file.metadata[filename] = [];
434
+ }
435
+ const modification = {
436
+ modificationCode: newImports.join('\n'),
437
+ start: path.node.start,
438
+ end: path.node.end,
439
+ loc: path.node.loc
440
+ };
441
+ state.file.metadata[filename].push(modification);
319
442
  }
320
443
  }
321
444
  };
@@ -0,0 +1,30 @@
1
+ export declare type CodeModification = {
2
+ modificationCode: string;
3
+ };
4
+ export declare type CodeChange = CodeModification;
5
+ export declare type CodeChangeWithLocation = CodeModification & MatchPosition;
6
+ export declare type MatchPosition = {
7
+ start: number;
8
+ end: number;
9
+ loc: Location;
10
+ };
11
+ declare type ModifyCodeAsTextParams = {
12
+ code: string;
13
+ modificationCode?: string;
14
+ alreadyChangedCodes?: string[];
15
+ location: Pick<MatchPosition, 'start' | 'end'>;
16
+ };
17
+ declare type ProcessCodeModificationsArrayParams = {
18
+ code: string;
19
+ changes: CodeChangeWithLocation[];
20
+ };
21
+ export declare const regExpTest: (regExp: RegExp, text: string) => boolean;
22
+ export declare function modifyCodeAsText({ code, modificationCode, location }: ModifyCodeAsTextParams): {
23
+ fileCode: string;
24
+ locationsChange: {
25
+ from: number;
26
+ to: number;
27
+ };
28
+ };
29
+ export declare function processTextCodeModificationsArray({ code, changes }: ProcessCodeModificationsArrayParams): string;
30
+ export {};
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processTextCodeModificationsArray = exports.modifyCodeAsText = exports.regExpTest = void 0;
4
+ const regExpTest = (regExp, text) => {
5
+ if (!text) {
6
+ return false;
7
+ }
8
+ const matches = text.match(regExp);
9
+ return matches !== null && matches.length > 0;
10
+ };
11
+ exports.regExpTest = regExpTest;
12
+ function modifyCodeAsText({ code, modificationCode, location }) {
13
+ let fileCode = code;
14
+ const codeBeforeMatch = fileCode.slice(0, location.start);
15
+ const codeAfterMatch = fileCode.slice(location.end);
16
+ const replacedCodeLength = location.end - location.start;
17
+ const replacementCodeLength = modificationCode.length;
18
+ const locationsChange = {
19
+ from: location.end,
20
+ to: location.end + replacementCodeLength - replacedCodeLength
21
+ };
22
+ fileCode = `${codeBeforeMatch}${modificationCode}${codeAfterMatch}`;
23
+ return { fileCode, locationsChange };
24
+ }
25
+ exports.modifyCodeAsText = modifyCodeAsText;
26
+ function processTextCodeModificationsArray({ code, changes }) {
27
+ let modifiedCode = code;
28
+ /**
29
+ * Include only changes that are unique by it's location.
30
+ * Remove changes that are inside range of other changes
31
+ */
32
+ const pendingChanges = changes.filter((change, changeIdx) => !changes.some((otherChange, otherChangeIdx) => otherChangeIdx !== changeIdx &&
33
+ otherChange.start <= change.start &&
34
+ otherChange.end >= change.end &&
35
+ // insert changes has the same start and end to distinguish them from anchor node, that might have other changes attached
36
+ change.start !== change.end));
37
+ while (pendingChanges.length > 0) {
38
+ const change = pendingChanges.shift();
39
+ const { locationsChange, fileCode } = modifyCodeAsText({
40
+ code: modifiedCode,
41
+ modificationCode: change.modificationCode,
42
+ location: { start: change.start, end: change.end }
43
+ });
44
+ modifiedCode = fileCode;
45
+ pendingChanges.forEach((pendingChange) => {
46
+ if (pendingChange.start >= locationsChange.from) {
47
+ const diff = locationsChange.to - locationsChange.from;
48
+ pendingChange.end += diff;
49
+ pendingChange.start += diff;
50
+ }
51
+ });
52
+ }
53
+ return modifiedCode;
54
+ }
55
+ exports.processTextCodeModificationsArray = processTextCodeModificationsArray;
@@ -0,0 +1 @@
1
+ export declare function template(template: string): (params: Record<string, string>) => string;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.template = void 0;
4
+ function template(template) {
5
+ return (params) => {
6
+ let code = template.trim();
7
+ Object.entries(params).forEach(([key, value]) => {
8
+ code = code.replace(new RegExp(`%%${key}%%`, 'g'), value);
9
+ });
10
+ return code;
11
+ };
12
+ }
13
+ exports.template = template;
@@ -1 +1,6 @@
1
- export {};
1
+ export function transform({ rootPath, inputFilePath, includeBarrelExportFiles, excludeBarrelExportFiles }: {
2
+ rootPath: any;
3
+ inputFilePath: any;
4
+ includeBarrelExportFiles: any;
5
+ excludeBarrelExportFiles: any;
6
+ }): Promise<void>;
@@ -1,17 +1,15 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transform = void 0;
2
4
  /*eslint-disable @typescript-eslint/no-var-requires */
3
5
  const { getFilesList } = require('@codeque/core');
4
6
  const babelCore = require('@babel/core');
7
+ const parser = require('@babel/parser');
5
8
  const fs = require('fs');
6
9
  const path = require('path');
7
- const rootPath = process.argv[2];
8
- const inputFilePath = process.argv[3];
9
- if (!rootPath) {
10
- console.error('Please provide correct transformation root');
11
- process.exit(1);
12
- }
13
- ;
14
- (async () => {
10
+ const babelParsingOptions_1 = require("./babelParsingOptions");
11
+ const processCodeTextModificationsArray_1 = require("./processCodeTextModificationsArray");
12
+ const transform = async ({ rootPath, inputFilePath, includeBarrelExportFiles, excludeBarrelExportFiles }) => {
15
13
  const root = path.resolve(rootPath);
16
14
  const resolvedInputFilePath = inputFilePath
17
15
  ? path.join(root, inputFilePath)
@@ -25,19 +23,34 @@ if (!rootPath) {
25
23
  });
26
24
  const errors = [];
27
25
  let progressCount = 0;
26
+ let cache = new Map();
28
27
  for (const filePath of filesList) {
29
28
  try {
30
29
  const fileName = path.parse(filePath).name;
30
+ const fileContent = fs.readFileSync(filePath).toString();
31
31
  const result = babelCore.transformFileSync(filePath, {
32
32
  plugins: [
33
- ['./babel.js', { tsConfigPath: path.join(root, 'tsconfig.json') }]
33
+ [
34
+ './babel.js',
35
+ {
36
+ tsConfigPath: path.join(root, 'tsconfig.json'),
37
+ cache,
38
+ includeBarrelExportFiles,
39
+ excludeBarrelExportFiles
40
+ }
41
+ ]
34
42
  ],
35
- parserOpts: {
36
- plugins: ['typescript', 'jsx']
37
- },
43
+ parserOpts: babelParsingOptions_1.babelParsingOptions,
38
44
  filename: fileName
39
45
  });
40
- fs.writeFileSync(filePath, result.code);
46
+ const changes = result.metadata[filePath];
47
+ if ((changes === null || changes === void 0 ? void 0 : changes.length) > 0) {
48
+ const resultCode = (0, processCodeTextModificationsArray_1.processTextCodeModificationsArray)({
49
+ code: fileContent,
50
+ changes
51
+ });
52
+ fs.writeFileSync(filePath, resultCode);
53
+ }
41
54
  progressCount++;
42
55
  if (progressCount % 100 === 0) {
43
56
  console.log(`${progressCount}+${errors.length}/${filesList.length}`);
@@ -49,4 +62,5 @@ if (!rootPath) {
49
62
  }
50
63
  console.log(errors);
51
64
  console.log(`Done: ${progressCount}/${filesList.length}; Failed: ${errors.length}`);
52
- })();
65
+ };
66
+ exports.transform = transform;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const rootPath = process.argv[2];
4
+ const inputFilePath = process.argv[3];
5
+ const transform_1 = require("./transform");
6
+ if (!rootPath) {
7
+ console.error('Please provide correct transformation root');
8
+ process.exit(1);
9
+ }
10
+ const run = async () => {
11
+ const startTime = new Date().getTime();
12
+ await (0, transform_1.transform)({
13
+ rootPath,
14
+ inputFilePath
15
+ });
16
+ console.log('Operation time: ', (new Date().getTime() - startTime) / 1000);
17
+ };
18
+ run();
@@ -1,9 +1,9 @@
1
1
  import { InputParams } from './types';
2
2
  declare type Results = Array<Array<Array<string>>>;
3
- export declare function formatResults({ results, filePath, entryPoints, compactSummary }: {
3
+ export declare function formatResults({ results, filePathOrNodeModuleName, entryPoints, compactSummary }: {
4
4
  results: Results;
5
5
  compactSummary: InputParams['compactSummary'];
6
6
  entryPoints: string[];
7
- filePath: string;
7
+ filePathOrNodeModuleName: string;
8
8
  }): string;
9
9
  export {};
@@ -29,11 +29,11 @@ const pathToString = (str, filePath, indentation) => {
29
29
  return `${str ? `${str}\n` : ''}${' '.repeat(indentation)} ➞ ${filePath}`;
30
30
  };
31
31
  const join = (...args) => args.join(' ') + '\n';
32
- function formatResults({ results, filePath, entryPoints, compactSummary }) {
32
+ function formatResults({ results, filePathOrNodeModuleName, entryPoints, compactSummary }) {
33
33
  let formatted = '';
34
34
  const hasAnyResults = results.some((paths) => paths.length > 0);
35
35
  if (!hasAnyResults) {
36
- formatted = join('No results found for', filePath, 'in the following entry points list:\n' + entryPoints.join('\n'));
36
+ formatted = join('No results found for', filePathOrNodeModuleName, 'in the following entry points list:\n' + entryPoints.join('\n'));
37
37
  return formatted;
38
38
  }
39
39
  if (compactSummary) {
@@ -6,7 +6,7 @@ const utils_1 = require("../../lib/utils");
6
6
  const commonOptions_1 = require("../commonOptions");
7
7
  function createResolve(program) {
8
8
  program
9
- .command('resolve <filePath> [entryPoints...]')
9
+ .command('resolve <filePathOrNodeModuleName> [entryPoints...]')
10
10
  .description('Checks if a filePath is required from entryPoint(s) and prints the resolution path', {
11
11
  filePath: 'Path to a file that should be resolved in entry points',
12
12
  'entryPoints...': 'List of entry points to look for file'
@@ -19,25 +19,27 @@ function createResolve(program) {
19
19
  .option('-cs, --compactSummary', 'print a compact summary of reverse resolution with a count of found paths')
20
20
  .option('-a, --all', 'finds all paths combination of a given dependency. Might work very slow or crash for some projects due to heavy usage of RAM', false)
21
21
  .option('-ntp --notTraversePaths <paths...>', 'Specify file paths relative to resolution root, that should not be traversed when finding dependency path')
22
+ .option('-inm --includeNodeModules', 'Whether to include node modules in dependency graph. Has to be provided to resolve node module.', true)
22
23
  .option(...commonOptions_1.ignoreTypesImports)
23
- .action(async (filePath, entryPoints, data) => {
24
- const { compactSummary, webpackConfig, all, cwd, exclude, include, notTraversePaths, ignoreTypesImports } = data;
24
+ .action(async (filePathOrNodeModuleName, entryPoints, data) => {
25
+ const { compactSummary, webpackConfig, all, cwd, exclude, include, notTraversePaths, ignoreTypesImports, includeNodeModules } = data;
25
26
  const [results, resolveEntryPoints] = await (0, resolve_1.resolve)({
26
27
  entryPoints,
27
- filePath,
28
+ filePathOrNodeModuleName,
28
29
  webpackConfig,
29
30
  all,
30
31
  cwd: (0, utils_1.resolvePath)(cwd),
31
32
  exclude,
32
33
  include,
33
34
  notTraversePaths,
34
- ignoreTypesImports
35
+ ignoreTypesImports,
36
+ includeNodeModules
35
37
  });
36
38
  const formatted = (0, formatResults_1.formatResults)({
37
39
  results,
38
40
  entryPoints: resolveEntryPoints,
39
41
  compactSummary,
40
- filePath
42
+ filePathOrNodeModuleName
41
43
  });
42
44
  console.log(formatted);
43
45
  });
@@ -7,4 +7,5 @@ export declare type InputParams = {
7
7
  printDependentCount?: boolean;
8
8
  all: boolean;
9
9
  notTraversePaths?: string[];
10
+ includeNodeModules?: boolean;
10
11
  };
@@ -1,2 +1,2 @@
1
1
  import { Node, MinimalDependencyTree } from './types';
2
- export declare const buildDepsGraph: (deps: MinimalDependencyTree, filePath?: string | undefined, notTraversePath?: string[] | undefined) => (entryPoint: string) => [Node, Node | null, Map<string, Node>];
2
+ export declare const buildDepsGraph: (deps: MinimalDependencyTree, filePathOrNodeModuleName?: string | undefined, notTraversePath?: string[] | undefined) => (entryPoint: string) => [Node, Node | null, Map<string, Node>];
@@ -5,9 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.buildDepsGraph = void 0;
7
7
  const minimatch_1 = __importDefault(require("minimatch"));
8
- const buildDepsGraph = (deps, filePath, notTraversePath) => (entryPoint) => {
8
+ const buildDepsGraph = (deps, filePathOrNodeModuleName, notTraversePath) => (entryPoint) => {
9
9
  const vertices = new Map();
10
- let fileNode = null;
10
+ let fileOrNodeModuleNode = null;
11
11
  const inner = (path, visited = new Set(), depth = 1, parent = null) => {
12
12
  const vertex = vertices.get(path);
13
13
  if (vertex) {
@@ -39,11 +39,11 @@ const buildDepsGraph = (deps, filePath, notTraversePath) => (entryPoint) => {
39
39
  !(notTraversePath === null || notTraversePath === void 0 ? void 0 : notTraversePath.some((pathToNotTraverse) => (0, minimatch_1.default)(path, pathToNotTraverse))))
40
40
  .map((path) => inner(path, localVisited, depth + 1, node));
41
41
  vertices.set(path, node);
42
- if (path === filePath) {
43
- fileNode = node;
42
+ if (path === filePathOrNodeModuleName) {
43
+ fileOrNodeModuleNode = node;
44
44
  }
45
45
  return node;
46
46
  };
47
- return [inner(entryPoint), fileNode, vertices];
47
+ return [inner(entryPoint), fileOrNodeModuleNode, vertices];
48
48
  };
49
49
  exports.buildDepsGraph = buildDepsGraph;
@@ -8,6 +8,7 @@ const is_builtin_module_1 = __importDefault(require("is-builtin-module"));
8
8
  const cleanupDpdmDeps = (deps, includeNodeModules = false) => {
9
9
  const newDeps = {};
10
10
  Object.entries(deps).forEach(([id, dependencies]) => {
11
+ const nodeModules = [];
11
12
  if (!(0, is_builtin_module_1.default)(id) &&
12
13
  !id.includes('node_modules') &&
13
14
  dependencies !== null) {
@@ -15,10 +16,22 @@ const cleanupDpdmDeps = (deps, includeNodeModules = false) => {
15
16
  .filter(({ id }) => id &&
16
17
  (includeNodeModules || !id.includes('node_modules')) &&
17
18
  !(0, is_builtin_module_1.default)(id))
18
- .map(({ id, request }) => ({
19
- id,
20
- request
21
- }));
19
+ .map(({ id, request }) => {
20
+ const shouldAddNodeModule = includeNodeModules && (id === null || id === void 0 ? void 0 : id.includes('node_modules'));
21
+ const idToAdd = shouldAddNodeModule ? request : id;
22
+ if (shouldAddNodeModule && idToAdd) {
23
+ nodeModules.push(idToAdd);
24
+ }
25
+ return {
26
+ id: idToAdd,
27
+ request
28
+ };
29
+ });
30
+ }
31
+ if (includeNodeModules) {
32
+ nodeModules.forEach((nodeModuleName) => {
33
+ newDeps[nodeModuleName] = [];
34
+ });
22
35
  }
23
36
  });
24
37
  return newDeps;
@@ -8,10 +8,11 @@ export declare const findEntryPointsInDepsTreeAndFilterOutIgnoredFiles: ({ cwd,
8
8
  include: string[] | undefined;
9
9
  cwd: string;
10
10
  }) => Promise<string[]>;
11
- export declare const getEntryPoints: ({ cwd, exclude, include, webpackConfigPath, ignoreTypesImports }: {
11
+ export declare const getEntryPoints: ({ cwd, exclude, include, webpackConfigPath, ignoreTypesImports, includeNodeModules }: {
12
12
  cwd: string;
13
13
  exclude?: string[] | undefined;
14
14
  include?: string[] | undefined;
15
15
  webpackConfigPath?: string | undefined;
16
16
  ignoreTypesImports?: boolean | undefined;
17
+ includeNodeModules?: boolean | undefined;
17
18
  }) => Promise<[string[], MinimalDependencyTree]>;
@@ -70,13 +70,13 @@ const findEntryPointsInDepsTreeAndFilterOutIgnoredFiles = async ({ cwd, depsTree
70
70
  return entryPointsWithoutIgnoredFiles;
71
71
  };
72
72
  exports.findEntryPointsInDepsTreeAndFilterOutIgnoredFiles = findEntryPointsInDepsTreeAndFilterOutIgnoredFiles;
73
- const getEntryPoints = async ({ cwd, exclude, include, webpackConfigPath, ignoreTypesImports }) => {
73
+ const getEntryPoints = async ({ cwd, exclude, include, webpackConfigPath, ignoreTypesImports, includeNodeModules }) => {
74
74
  const dirs = await (0, exports.getDirectoriesForEntryPointsSearch)(cwd);
75
75
  const globs = dirs
76
76
  .map((dirName) => path_1.default.relative(cwd, dirName))
77
77
  .map((dirName) => `${(0, glob_escape_1.default)(dirName)}/*`);
78
78
  const globsWithRoot = ['*', ...globs];
79
- const depsTree = await (0, getDepsTree_1.getDepsTree)(cwd, globsWithRoot, webpackConfigPath, ignoreTypesImports);
79
+ const depsTree = await (0, getDepsTree_1.getDepsTree)(cwd, globsWithRoot, webpackConfigPath, ignoreTypesImports, includeNodeModules);
80
80
  const entryPointsWithoutIgnoredFiles = await (0, exports.findEntryPointsInDepsTreeAndFilterOutIgnoredFiles)({ cwd, include, exclude, depsTree });
81
81
  return [entryPointsWithoutIgnoredFiles, depsTree];
82
82
  };
@@ -1,7 +1,7 @@
1
1
  import { MinimalDependencyTree } from './types';
2
2
  declare type ResolveParams = {
3
3
  entryPoints?: string[];
4
- filePath: string;
4
+ filePathOrNodeModuleName: string;
5
5
  webpackConfig?: string;
6
6
  cwd?: string;
7
7
  all: boolean;
@@ -9,6 +9,7 @@ declare type ResolveParams = {
9
9
  include?: string[];
10
10
  notTraversePaths?: string[];
11
11
  ignoreTypesImports?: boolean;
12
+ includeNodeModules?: boolean;
12
13
  };
13
- export declare const resolve: ({ entryPoints: _entryPoints, filePath, webpackConfig, cwd, all, include, exclude, notTraversePaths, ignoreTypesImports }: ResolveParams) => Promise<[string[][][], string[], MinimalDependencyTree]>;
14
+ export declare const resolve: ({ entryPoints: _entryPoints, filePathOrNodeModuleName, webpackConfig, cwd, all, include, exclude, notTraversePaths, ignoreTypesImports, includeNodeModules }: ResolveParams) => Promise<[string[][][], string[], MinimalDependencyTree]>;
14
15
  export {};
@@ -27,12 +27,12 @@ const resolvePathsToRoot = (node, all = false, resolvedPaths = [[]]) => {
27
27
  }
28
28
  return resolvePathsToRoot(node.parents[0], false, newPaths);
29
29
  };
30
- const resolve = async ({ entryPoints: _entryPoints, filePath, webpackConfig, cwd = process.cwd(), all, include, exclude, notTraversePaths, ignoreTypesImports }) => {
30
+ const resolve = async ({ entryPoints: _entryPoints, filePathOrNodeModuleName, webpackConfig, cwd = process.cwd(), all, include, exclude, notTraversePaths, ignoreTypesImports, includeNodeModules }) => {
31
31
  let deps, entryPoints;
32
32
  if (_entryPoints && (_entryPoints === null || _entryPoints === void 0 ? void 0 : _entryPoints.length) > 0) {
33
33
  entryPoints = _entryPoints;
34
34
  const sanitizedEntryPoints = (0, utils_1.sanitizeUserEntryPoints)(entryPoints);
35
- deps = await (0, getDepsTree_1.getDepsTree)(cwd, sanitizedEntryPoints, webpackConfig, ignoreTypesImports);
35
+ deps = await (0, getDepsTree_1.getDepsTree)(cwd, sanitizedEntryPoints, webpackConfig, ignoreTypesImports, includeNodeModules);
36
36
  }
37
37
  else {
38
38
  ;
@@ -41,12 +41,13 @@ const resolve = async ({ entryPoints: _entryPoints, filePath, webpackConfig, cwd
41
41
  exclude,
42
42
  include,
43
43
  webpackConfigPath: webpackConfig,
44
- ignoreTypesImports
44
+ ignoreTypesImports,
45
+ includeNodeModules
45
46
  });
46
47
  }
47
48
  const cleanedEntryPoints = entryPoints.map(utils_1.removeInitialDot);
48
- const cleanedFilePath = (0, utils_1.removeInitialDot)(filePath);
49
- const forest = cleanedEntryPoints.map((0, buildDepsGraph_1.buildDepsGraph)(deps, cleanedFilePath, notTraversePaths));
49
+ const cleanedFilePathOrNodeModuleName = (0, utils_1.removeInitialDot)(filePathOrNodeModuleName);
50
+ const forest = cleanedEntryPoints.map((0, buildDepsGraph_1.buildDepsGraph)(deps, cleanedFilePathOrNodeModuleName, notTraversePaths));
50
51
  const resolvedPaths = forest.reduce((allPaths, [_, fileNode]) => {
51
52
  if (!fileNode) {
52
53
  return [...allPaths, []];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rev-dep",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "Dependency debugging tool for JavaScript and TypeScript projects",
5
5
  "main": "dist/module.js",
6
6
  "bin": "bin.js",