rev-dep 1.0.0-alpha.1 → 1.0.0-alpha.4

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
@@ -133,9 +133,8 @@ rev-dep resolve <filePath> [entryPoints...] [options]
133
133
 
134
134
  - `-wc, --webpackConfig <path>` - path to webpack config to enable webpack aliases support (_optional_)
135
135
  - `--cwd <path>` - path to a directory that should be used as a resolution root (_optional_)
136
- - `--rr reexportRewire <value>` - resolve actual dependencies for "export \* from" statements (_optional_)
137
- - `-i include <globs...>` - A list of globs to determine files included in entry points search (_optional_)
138
- - `-e exclude <globs...>` - A list of globs to determine files excluded in entry points search (_optional_)
136
+ - `-i --include <globs...>` - A list of globs to determine files included in entry points search (_optional_)
137
+ - `-e --exclude <globs...>` - A list of globs to determine files excluded in entry points search (_optional_)
139
138
  - `-cs, --compactSummary` - print a compact summary of reverse resolution with a count of found paths (_optional_)
140
139
  - `-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_)
141
140
 
@@ -153,9 +152,8 @@ rev-dep entry-points [options]
153
152
 
154
153
  - `-wc, --webpackConfig <path>` - path to webpack config to enable webpack aliases support (_optional_)
155
154
  - `--cwd <path>` - path to a directory that should be used as a resolution root (_optional_)
156
- - `--rr reexportRewire <value>` - resolve actual dependencies for "export \* from" statements (_optional_)
157
- - `-i include <globs...>` - A list of globs to determine files included in entry points search (_optional_)
158
- - `-e exclude <globs...>` - A list of globs to determine files excluded in entry points search (_optional_)
155
+ - `-i --include <globs...>` - A list of globs to determine files included in entry points search (_optional_)
156
+ - `-e --exclude <globs...>` - A list of globs to determine files excluded in entry points search (_optional_)
159
157
  - `-pdc, --printDependenciesCount` - print count of entry point dependencies (_optional_)
160
158
  - `-c, --count` - print just count of found entry points (_optional_)
161
159
 
@@ -177,7 +175,6 @@ rev-dep files <entryPoint> [options]
177
175
 
178
176
  - `-wc, --webpackConfig <path>` - path to webpack config to enable webpack aliases support (_optional_)
179
177
  - `--cwd <path>` - path to a directory that should be used as a resolution root (_optional_)
180
- - `--rr reexportRewire <value>` - resolve actual dependencies for "export \* from" statements (_optional_)
181
178
  - `-c, --count` - print only count of entry point dependencies (_optional_)
182
179
 
183
180
  ### Command `docs`
package/babel.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/babel/index.js')
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+ /*eslint-disable @typescript-eslint/no-var-requires */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const node_path = require('path');
5
+ const fs = require('fs');
6
+ const parser = require('@babel/parser');
7
+ const template = require('@babel/template').default;
8
+ const utils_1 = require("../lib/utils");
9
+ const SKIP = Symbol('SKIP');
10
+ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsConfig)() }) {
11
+ const tsConfig = require(tsConfigPath);
12
+ const aliases = tsConfig.compilerOptions.paths;
13
+ const aliasesKeys = Object.keys(aliases);
14
+ const aliasesRegexes = Object.keys(aliases).map((alias) => {
15
+ return new RegExp(`^${alias.replace('*', '(.)+')}$`);
16
+ });
17
+ const cache = new Map();
18
+ const getFile = (original, paths) => {
19
+ if (paths.length === 0) {
20
+ throw new Error('Cannot resolve import ' + original);
21
+ }
22
+ const path = paths[0];
23
+ try {
24
+ return [path, fs.readFileSync(path).toString()];
25
+ }
26
+ catch (e) {
27
+ return getFile(original, paths.slice(1));
28
+ }
29
+ };
30
+ const isPathRelativeOrAliased = (path) => {
31
+ const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(path));
32
+ const isRelative = path.startsWith('./') || path.startsWith('../');
33
+ return aliasRegexIdx > -1 || isRelative;
34
+ };
35
+ const cacheKey = (identifier, filePath) => `${identifier}-${filePath}`;
36
+ const lookup = (identifier, filePath, cwd) => {
37
+ const cached = cache.get(cacheKey(identifier, filePath));
38
+ if (cached) {
39
+ return cached;
40
+ }
41
+ const withExtension = /(\.ts|\.tsx)$/.test(filePath)
42
+ ? [filePath]
43
+ : [
44
+ `${filePath}.ts`,
45
+ `${filePath}.tsx`,
46
+ `${filePath}/index.ts`,
47
+ `${filePath}/index.tsx`,
48
+ `${filePath}.js`,
49
+ `${filePath}.jsx`,
50
+ `${filePath}/index.js`,
51
+ `${filePath}/index.jsx`
52
+ ];
53
+ const [resolvedFilePath, file] = getFile(filePath, withExtension);
54
+ const ast = parser.parse(file, {
55
+ sourceType: 'module',
56
+ plugins: [
57
+ 'jsx',
58
+ 'typescript',
59
+ 'objectRestSpread',
60
+ 'classProperties',
61
+ 'asyncGenerators',
62
+ 'decorators-legacy'
63
+ ]
64
+ });
65
+ /**
66
+ * {
67
+ * identifier?: string,
68
+ * source: string
69
+ * }
70
+ */
71
+ const toLookup = [];
72
+ let resolvedAs = null;
73
+ ast.program.body.forEach((declaration) => {
74
+ var _a;
75
+ if (resolvedAs === null) {
76
+ if (types.isExportNamedDeclaration(declaration)) {
77
+ if (types.isVariableDeclaration(declaration.declaration)) {
78
+ const hasIdentifier = declaration.declaration.declarations.find((declarator) => {
79
+ return declarator.id.name === identifier;
80
+ });
81
+ if (hasIdentifier) {
82
+ resolvedAs = {
83
+ type: 'named',
84
+ identifier,
85
+ source: filePath
86
+ };
87
+ }
88
+ }
89
+ else if (types.isFunctionDeclaration(declaration.declaration) ||
90
+ types.isClassDeclaration(declaration.declaration)) {
91
+ if (declaration.declaration.id.name === identifier) {
92
+ resolvedAs = {
93
+ type: 'named',
94
+ identifier,
95
+ source: filePath
96
+ };
97
+ }
98
+ }
99
+ else {
100
+ const source = (_a = declaration.source) === null || _a === void 0 ? void 0 : _a.value;
101
+ declaration.specifiers.forEach((specifier) => {
102
+ if (types.isExportSpecifier(specifier)) {
103
+ if (specifier.exported.name === identifier) {
104
+ if (specifier.local.name === 'default' && source) {
105
+ resolvedAs = {
106
+ type: 'default',
107
+ identifier,
108
+ source: getModulePath(source, resolvedFilePath, cwd)
109
+ };
110
+ }
111
+ else if (source === undefined) {
112
+ resolvedAs = {
113
+ type: 'named',
114
+ identifier,
115
+ source: filePath
116
+ };
117
+ }
118
+ else if (isPathRelativeOrAliased(source)) {
119
+ toLookup.push({
120
+ identifier: specifier.exported.local,
121
+ source: getModulePath(source, resolvedFilePath, cwd)
122
+ });
123
+ }
124
+ }
125
+ }
126
+ });
127
+ }
128
+ }
129
+ else if (types.isExportAllDeclaration(declaration) &&
130
+ isPathRelativeOrAliased(declaration.source.value)) {
131
+ toLookup.push({
132
+ identifier,
133
+ source: getModulePath(declaration.source.value, resolvedFilePath, cwd)
134
+ });
135
+ }
136
+ }
137
+ });
138
+ if (resolvedAs) {
139
+ return resolvedAs;
140
+ }
141
+ const nestedResult = toLookup
142
+ .map(({ identifier, source }) => lookup(identifier, source, cwd))
143
+ .filter(Boolean);
144
+ return nestedResult[0];
145
+ };
146
+ const getModulePath = (sourcePath, fileName, cwd) => {
147
+ var _a;
148
+ const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(sourcePath));
149
+ const relativeFileName = node_path.relative(cwd, fileName);
150
+ const aliasKey = aliasesKeys[aliasRegexIdx];
151
+ const alias = (_a = aliases[aliasKey]) === null || _a === void 0 ? void 0 : _a[0];
152
+ let modulePath = '';
153
+ if (alias) {
154
+ let relative = alias;
155
+ if (aliasKey.endsWith('*')) {
156
+ const aliasKeyPrefix = aliasKey.replace('*', '');
157
+ relative = alias.replace('*', sourcePath.replace(aliasKeyPrefix, ''));
158
+ }
159
+ modulePath = node_path.resolve(cwd, relative);
160
+ }
161
+ else {
162
+ // we need ../ to skip current file name
163
+ modulePath = node_path.resolve(relativeFileName, '../' + sourcePath);
164
+ }
165
+ return modulePath;
166
+ };
167
+ return {
168
+ visitor: {
169
+ ImportDeclaration(path, { filename, cwd }) {
170
+ const sourceRelative = (source) => {
171
+ const rel = node_path.relative(node_path.dirname(filename), source);
172
+ return rel.startsWith('.') ? rel : './' + rel;
173
+ };
174
+ const node = path.node;
175
+ const source = node.source;
176
+ if (source.type !== 'StringLiteral') {
177
+ return;
178
+ }
179
+ const shouldSkip = node[SKIP] || !isPathRelativeOrAliased(source.value);
180
+ if (shouldSkip) {
181
+ return;
182
+ }
183
+ const modulePath = getModulePath(source.value, filename, cwd);
184
+ const defaultSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier');
185
+ const namespaceSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportNamespaceSpecifier');
186
+ const specifiers = node.specifiers.filter((specifier) => specifier.type === 'ImportSpecifier');
187
+ const results = specifiers.map((specifier) => {
188
+ const importedName = specifier.imported.name;
189
+ const result = lookup(importedName, modulePath, cwd);
190
+ if (!result) {
191
+ return {
192
+ identifier: importedName,
193
+ local: specifier.local.name,
194
+ source: source.value
195
+ };
196
+ }
197
+ cache.set(cacheKey(importedName, modulePath), result);
198
+ return {
199
+ ...result,
200
+ source: sourceRelative(result.source),
201
+ local: specifier.local.name
202
+ };
203
+ });
204
+ const defaultResult = defaultSpecifier
205
+ ? lookup('default', modulePath, cwd)
206
+ : null;
207
+ if (defaultResult) {
208
+ cache.set(cacheKey('default', modulePath), defaultResult);
209
+ }
210
+ const buildNamed = template(`
211
+ import { %%IMPORT_NAME%% } from %%SOURCE%%;
212
+ `);
213
+ const buildNamedWithAlias = template(`
214
+ import { %%IMPORTED_NAME%% as %%LOCAL_NAME%% } from %%SOURCE%%;
215
+ `);
216
+ const buildDefault = template(`
217
+ import %%IMPORT_NAME%% from %%SOURCE%%;
218
+ `);
219
+ const buildNamespace = template(`
220
+ import * as %%IMPORT_NAME%% from %%SOURCE%%;
221
+ `);
222
+ const defaultImport = defaultResult
223
+ ? [
224
+ buildDefault({
225
+ IMPORT_NAME: types.identifier(defaultSpecifier.local.name),
226
+ SOURCE: types.stringLiteral(sourceRelative(defaultResult.source))
227
+ })
228
+ ]
229
+ : defaultSpecifier
230
+ ? [
231
+ buildDefault({
232
+ IMPORT_NAME: types.identifier(defaultSpecifier.local.name),
233
+ SOURCE: types.stringLiteral(source.value)
234
+ })
235
+ ]
236
+ : [];
237
+ const namespaceImport = namespaceSpecifier
238
+ ? [
239
+ buildNamespace({
240
+ IMPORT_NAME: types.identifier(namespaceSpecifier.local.name),
241
+ SOURCE: types.stringLiteral(source.value)
242
+ })
243
+ ]
244
+ : [];
245
+ const named = results.map(({ type, identifier, local, source }) => {
246
+ if (type === 'default') {
247
+ return buildDefault({
248
+ IMPORT_NAME: types.identifier(identifier),
249
+ SOURCE: types.stringLiteral(source)
250
+ });
251
+ }
252
+ else if (identifier !== local) {
253
+ return buildNamedWithAlias({
254
+ IMPORTED_NAME: types.identifier(identifier),
255
+ LOCAL_NAME: types.identifier(local),
256
+ SOURCE: types.stringLiteral(source)
257
+ });
258
+ }
259
+ else {
260
+ return buildNamed({
261
+ IMPORT_NAME: types.identifier(identifier),
262
+ SOURCE: types.stringLiteral(source)
263
+ });
264
+ }
265
+ });
266
+ const newImports = [...namespaceImport, ...defaultImport, ...named].map((node) => {
267
+ node[SKIP] = true;
268
+ return node;
269
+ });
270
+ path.replaceWithMultiple(newImports);
271
+ }
272
+ }
273
+ };
274
+ };
@@ -11,14 +11,14 @@ exports.cwdOption = [
11
11
  process.cwd()
12
12
  ];
13
13
  exports.reexportRewireOption = [
14
- '--rr reexportRewire <value>',
14
+ '-rr --reexportRewire <value>',
15
15
  'resolve actual dependencies for "export * from" statements'
16
16
  ];
17
17
  exports.includeOption = [
18
- '-i include <globs...>',
18
+ '-i --include <globs...>',
19
19
  'A list of globs to determine files included in entry points search'
20
20
  ];
21
21
  exports.excludeOption = [
22
- '-e exclude <globs...>',
22
+ '-e --exclude <globs...>',
23
23
  'A list of globs to determine files excluded in entry points search'
24
24
  ];
@@ -10,7 +10,7 @@ function createEntryPoints(program) {
10
10
  .description('Print list of entry points in current directory')
11
11
  .option(...commonOptions_1.webpackConfigOption)
12
12
  .option(...commonOptions_1.cwdOption)
13
- .option(...commonOptions_1.reexportRewireOption)
13
+ // .option(...reexportRewireOption)
14
14
  .option(...commonOptions_1.includeOption)
15
15
  .option(...commonOptions_1.excludeOption)
16
16
  .option('-pdc, --printDependenciesCount', 'print count of entry point dependencies', false)
@@ -11,7 +11,7 @@ function createFiles(program) {
11
11
  })
12
12
  .option(...commonOptions_1.webpackConfigOption)
13
13
  .option(...commonOptions_1.cwdOption)
14
- .option(...commonOptions_1.reexportRewireOption)
14
+ // .option(...reexportRewireOption)
15
15
  .option('-c, --count', 'print only count of entry point dependencies', false)
16
16
  .action(async (entryPoint, data) => {
17
17
  const { webpackConfig: webpackConfigPath, cwd, count } = data;
@@ -13,16 +13,15 @@ function createResolve(program) {
13
13
  })
14
14
  .option(...commonOptions_1.webpackConfigOption)
15
15
  .option(...commonOptions_1.cwdOption)
16
- .option(...commonOptions_1.reexportRewireOption)
16
+ // .option(...reexportRewireOption)
17
17
  .option(...commonOptions_1.includeOption)
18
18
  .option(...commonOptions_1.excludeOption)
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
  .action(async (filePath, entryPoints, data) => {
22
22
  const { compactSummary, webpackConfig, all, cwd, exclude, include } = data;
23
- const sanitizedEntryPoints = (0, utils_1.sanitizeUserEntryPoints)(entryPoints);
24
23
  const [results, resolveEntryPoints] = await (0, find_1.resolve)({
25
- entryPoints: sanitizedEntryPoints,
24
+ entryPoints,
26
25
  filePath,
27
26
  webpackConfig,
28
27
  all,
@@ -12,7 +12,7 @@ const cleanupDpdmDeps = (deps) => {
12
12
  !id.includes('node_modules') &&
13
13
  dependencies !== null) {
14
14
  newDeps[id] = dependencies
15
- .filter(({ id }) => id && !id.includes('node_modules'))
15
+ .filter(({ id }) => id && !id.includes('node_modules') && !(0, is_builtin_module_1.default)(id))
16
16
  .map(({ id, request }) => ({
17
17
  id,
18
18
  request
package/dist/lib/find.js CHANGED
@@ -24,7 +24,8 @@ const resolve = async ({ entryPoints: _entryPoints, filePath, webpackConfig, cwd
24
24
  let deps, entryPoints;
25
25
  if (_entryPoints.length > 0) {
26
26
  entryPoints = _entryPoints;
27
- deps = await (0, getDepsTree_1.getDepsTree)(cwd, entryPoints, webpackConfig);
27
+ const sanitizedEntryPoints = (0, utils_1.sanitizeUserEntryPoints)(entryPoints);
28
+ deps = await (0, getDepsTree_1.getDepsTree)(cwd, sanitizedEntryPoints, webpackConfig);
28
29
  }
29
30
  else {
30
31
  ;
@@ -10,6 +10,7 @@ const promises_1 = __importDefault(require("fs/promises"));
10
10
  const utils_1 = require("./utils");
11
11
  const getDepsTree_1 = require("./getDepsTree");
12
12
  const ignore_1 = __importDefault(require("ignore"));
13
+ const glob_escape_1 = __importDefault(require("glob-escape"));
13
14
  const getDirectoriesForEntryPointsSearch = async (dir) => {
14
15
  const entries = await promises_1.default.readdir(dir);
15
16
  const directories = await (0, utils_1.asyncFilter)(entries, async (pathName) => {
@@ -48,7 +49,7 @@ const getEntryPoints = async ({ cwd, exclude, include, webpackConfigPath }) => {
48
49
  const dirs = await (0, exports.getDirectoriesForEntryPointsSearch)(cwd);
49
50
  const globs = dirs
50
51
  .map((dirName) => path_1.default.relative(cwd, dirName))
51
- .map((dirName) => `${dirName}/*`);
52
+ .map((dirName) => `${(0, glob_escape_1.default)(dirName)}/*`);
52
53
  const globsWithRoot = ['*', ...globs];
53
54
  const depsTree = await (0, getDepsTree_1.getDepsTree)(cwd, globsWithRoot, webpackConfigPath);
54
55
  const possibleEntryPoints = (0, exports.findEntryPointsInDepsTree)(depsTree, exclude, include);
package/dist/lib/utils.js CHANGED
@@ -3,8 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.resolvePath = exports.sanitizeUserEntryPoints = exports.asyncFilter = exports.createResolveAbsolutePath = exports.removeInitialDot = void 0;
6
+ exports.findTsConfig = exports.resolvePath = exports.sanitizeUserEntryPoints = exports.asyncFilter = exports.createResolveAbsolutePath = exports.removeInitialDot = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
8
9
  const glob_escape_1 = __importDefault(require("glob-escape"));
9
10
  const removeInitialDot = (path) => path.replace(/^\.\//, '');
10
11
  exports.removeInitialDot = removeInitialDot;
@@ -27,3 +28,17 @@ const resolvePath = (p) => {
27
28
  return path_1.default.resolve(p);
28
29
  };
29
30
  exports.resolvePath = resolvePath;
31
+ const findTsConfig = (cwd = process.cwd()) => {
32
+ try {
33
+ const tsconfig = path_1.default.join(cwd, 'tsconfig.json');
34
+ const stat = fs_1.default.statSync(tsconfig);
35
+ if (stat.isFile()) {
36
+ return tsconfig;
37
+ }
38
+ }
39
+ catch {
40
+ /**/
41
+ }
42
+ return undefined;
43
+ };
44
+ exports.findTsConfig = findTsConfig;
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "rev-dep",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.4",
4
4
  "description": "Reverse dependency resolution tool built with dependency-cruiser",
5
5
  "main": "lib/find.js",
6
6
  "bin": "bin.js",
7
7
  "files": [
8
8
  "dist/**",
9
9
  "lib/**",
10
- "bin.js"
10
+ "bin.js",
11
+ "babel.js"
11
12
  ],
12
13
  "author": "Jakub Mazurek @jayu",
13
14
  "license": "MIT",
@@ -31,6 +32,8 @@
31
32
  "typecheck": "tsc --noEmit"
32
33
  },
33
34
  "dependencies": {
35
+ "@babel/parser": "^7.17.8",
36
+ "@babel/template": "^7.16.7",
34
37
  "@types/dedent": "^0.7.0",
35
38
  "colorette": "^2.0.16",
36
39
  "commander": "^6.1.0",
@@ -43,6 +46,7 @@
43
46
  "minimatch": "^5.0.1"
44
47
  },
45
48
  "devDependencies": {
49
+ "@babel/types": "^7.17.0",
46
50
  "@typescript-eslint/eslint-plugin": "^5.16.0",
47
51
  "@typescript-eslint/parser": "^5.16.0",
48
52
  "eslint": "^7.11.0",
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getMaxDepth = void 0;
4
- const getMaxDepth = (depth = 1, path = [], vertices = new Map()) => {
5
- return (tree) => {
6
- const depthFromCache = vertices.get(tree.path);
7
- if (depthFromCache) {
8
- return depthFromCache;
9
- }
10
- const newPath = [...path, tree.path];
11
- if (tree.children.length === 0) {
12
- return [depth, newPath];
13
- }
14
- const results = tree.children.map((0, exports.getMaxDepth)(depth + 1, newPath, vertices));
15
- const maxChildDepth = Math.max(...results.map(([depth]) => depth));
16
- const itemWithMaxDepth = results.find(([depth]) => depth === maxChildDepth);
17
- vertices.set(tree.path, itemWithMaxDepth);
18
- return itemWithMaxDepth;
19
- };
20
- };
21
- exports.getMaxDepth = getMaxDepth;