rev-dep 0.1.1 → 0.3.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 +18 -5
- package/cli.js +26 -8
- package/find.js +53 -9
- package/getDepsSet.js +12 -8
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ Results:
|
|
|
46
46
|
➞ getDepsSet.js
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
Which says that `getDepsSet.js` file is used in `cli.js` entry point and is required through `find.js`
|
|
50
50
|
|
|
51
51
|
## About
|
|
52
52
|
|
|
@@ -54,7 +54,7 @@ The tool was created to determine places in the project where a particular file
|
|
|
54
54
|
|
|
55
55
|
It's especially useful in JS world without TypeScript or tests coverage.
|
|
56
56
|
|
|
57
|
-
Except the reverse dependency resolution path, it can print statistics about how many times a particular module is required in the project, which might be helpful for
|
|
57
|
+
Except the reverse dependency resolution path, it can print statistics about how many times a particular module is required in the project, which might be helpful for code-splitting planning.
|
|
58
58
|
|
|
59
59
|
## Usage
|
|
60
60
|
|
|
@@ -67,13 +67,14 @@ Avaliable commands:
|
|
|
67
67
|
#### `resolve`
|
|
68
68
|
|
|
69
69
|
```sh
|
|
70
|
-
rev-dep resolve <
|
|
70
|
+
rev-dep resolve <filePath> <entryPoints...>
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
Available options are
|
|
74
74
|
|
|
75
75
|
- `-cs or --compactSummary` - instead of file paths print a compact summary of reverse resolution with a count of found paths
|
|
76
76
|
- `--verbose` - log currently performed operation
|
|
77
|
+
- `-wc, --webpackConfig <path>` - path to webpack config to enable webpack aliases support
|
|
77
78
|
|
|
78
79
|
### Module
|
|
79
80
|
|
|
@@ -84,7 +85,7 @@ import { find } from 'rev-dep'
|
|
|
84
85
|
|
|
85
86
|
const path = find({
|
|
86
87
|
entryPoints: ['index.js'],
|
|
87
|
-
|
|
88
|
+
filePath: 'utils.js'
|
|
88
89
|
})
|
|
89
90
|
|
|
90
91
|
console.log(path)
|
|
@@ -93,10 +94,22 @@ console.log(path)
|
|
|
93
94
|
#### `find` Options
|
|
94
95
|
|
|
95
96
|
- `entryPoints (Array)` - Array of entry points to build a tree for search. Usually it will be one entry point, but project can have many of them, eg. next.js application. **Required**
|
|
96
|
-
- `
|
|
97
|
+
- `filePath (String)` - A file that we want to find path for. **Required**
|
|
97
98
|
- `skipRegex (String | RegExp)` - If a file path matches the pattern, we stop to traverse it's dependencies and do not include that file in the search tree. _Optional_, default: `'(node_modules|/__tests__|/__test__|/__mockContent__|.scss)'`
|
|
98
99
|
- `verbose (Boolean)` - when set to true, will print current operation performed by find function. _Optional_, default: `false`
|
|
99
100
|
- `cwd` - root for resolved files, must be an absolute path. _Optional_, default: `process.cwd()`
|
|
101
|
+
- `webpackConfig (String)` - path to webpack config to enable webpack aliases support
|
|
102
|
+
|
|
103
|
+
### Additional setup may be required
|
|
104
|
+
|
|
105
|
+
#### Resolving implicit file extensions
|
|
106
|
+
|
|
107
|
+
A vast amount of JS/TS projects are configured in a way that allows (or even forces) to skip file extensions in import statements. Rev-dep is strongly based on [dependency-cruiser](https://github.com/sverweij/dependency-cruiser) which by default support implicit file extensions for `*.js, *.cjs, *.mjs, *.jsx` files (check [source](https://github.com/sverweij/dependency-cruiser/blob/96e34d0cf158034f2b7c8cafe9cec72dd74d8c45/src/extract/transpile/meta.js)).
|
|
108
|
+
In order to resolve implicit extensions for other JS based languages it look for available corresponding compiler in `package.json`. If compiler is available, then extension is supported.
|
|
109
|
+
|
|
110
|
+
If you installed `rev-dep` **globally**, you will have appropriate compiler installed **globally** as well. If you use it as a module, your project has to have compiler in it's package.json.
|
|
111
|
+
|
|
112
|
+
For example, to support `*.ts` and `*.tsx` implicit extensions in globally installed `rev-dep`, you have to also install globally `typescript` package (see [source](https://github.com/sverweij/dependency-cruiser/blob/96e34d0cf158034f2b7c8cafe9cec72dd74d8c45/src/extract/transpile/typescript-wrap.js))
|
|
100
113
|
|
|
101
114
|
## Contributing
|
|
102
115
|
|
package/cli.js
CHANGED
|
@@ -12,19 +12,35 @@ const pathToString = (str, f, i) => {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
program
|
|
15
|
-
.command('resolve <
|
|
15
|
+
.command('resolve <filePath> <entryPoints...>')
|
|
16
16
|
.option(
|
|
17
17
|
'-cs, --compactSummary',
|
|
18
18
|
'print a compact summary of reverse resolution with a count of found paths'
|
|
19
19
|
)
|
|
20
20
|
.option('--verbose', 'print current action information')
|
|
21
|
-
.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
.option(
|
|
22
|
+
'-wc, --webpackConfig <path>',
|
|
23
|
+
'path to webpack config to enable webpack aliases support'
|
|
24
|
+
)
|
|
25
|
+
.option(
|
|
26
|
+
'-tc, --typescriptConfig <path>',
|
|
27
|
+
'path to TypeScript config to enable TS aliases support'
|
|
28
|
+
)
|
|
29
|
+
.action(async (filePath, entryPoints, data) => {
|
|
30
|
+
const { compactSummary, verbose, webpackConfig, typescriptConfig } = data
|
|
31
|
+
|
|
32
|
+
const results = await find({
|
|
33
|
+
entryPoints,
|
|
34
|
+
filePath,
|
|
35
|
+
verbose,
|
|
36
|
+
webpackConfig,
|
|
37
|
+
typescriptConfig
|
|
27
38
|
})
|
|
39
|
+
const hasAnyResults = results.some((paths) => paths.length > 0)
|
|
40
|
+
if (!hasAnyResults) {
|
|
41
|
+
console.log('No results found for', filePath, 'in', entryPoints)
|
|
42
|
+
return
|
|
43
|
+
}
|
|
28
44
|
console.log('Results:\n')
|
|
29
45
|
if (compactSummary) {
|
|
30
46
|
const maxEntryLength = entryPoints.reduce((maxLength, entryPoint) => {
|
|
@@ -39,13 +55,15 @@ program
|
|
|
39
55
|
} else {
|
|
40
56
|
results.forEach((entryPointResults, index) => {
|
|
41
57
|
entryPointResults.forEach((path) => {
|
|
42
|
-
console.log(path.reduce(pathToString, ''))
|
|
58
|
+
console.log(path.reduce(pathToString, ''), '\n')
|
|
43
59
|
})
|
|
44
60
|
if (index < results.length - 1) {
|
|
45
61
|
console.log('_'.repeat(process.stdout.columns))
|
|
46
62
|
}
|
|
47
63
|
})
|
|
48
64
|
}
|
|
65
|
+
|
|
66
|
+
|
|
49
67
|
})
|
|
50
68
|
|
|
51
69
|
program.parse(process.argv)
|
package/find.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
2
|
const getDepsSet = require('./getDepsSet')
|
|
3
|
+
const { parseDependencyTree } = require('dpdm');
|
|
4
|
+
const escapeGlob = require('glob-escape');
|
|
3
5
|
|
|
4
6
|
const buildTree = (deps) => (entryPoint) => {
|
|
5
7
|
const inner = (path) => {
|
|
@@ -21,6 +23,39 @@ const buildTree = (deps) => (entryPoint) => {
|
|
|
21
23
|
return inner(entryPoint)
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
const buildTreeDpdm = (_deps) => (entryPoint) => {
|
|
27
|
+
|
|
28
|
+
const deps = Object.entries(_deps).reduce((deps, [id, data]) => {
|
|
29
|
+
if (!id.includes('node_modules')) {
|
|
30
|
+
return Object.assign({}, deps, { [id]: data ? data.filter(({ id }) => id && !id.includes('node_modules')) : data })
|
|
31
|
+
}
|
|
32
|
+
return deps
|
|
33
|
+
}, {})
|
|
34
|
+
|
|
35
|
+
const inner = (path, visited = new Set()) => {
|
|
36
|
+
if (visited.has(path)) {
|
|
37
|
+
return {
|
|
38
|
+
path,
|
|
39
|
+
children: []
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
visited.add(path);
|
|
43
|
+
const dep = deps[path]
|
|
44
|
+
if (dep === undefined) {
|
|
45
|
+
throw new Error(`Dependency '${path}' not found!`)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
path,
|
|
50
|
+
children: (dep || [])
|
|
51
|
+
.map(d => d.id)
|
|
52
|
+
.filter(path => path && !path.includes('node_modules'))
|
|
53
|
+
.map((path) => inner(path, visited))
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return inner(entryPoint)
|
|
57
|
+
}
|
|
58
|
+
|
|
24
59
|
const traverse = (file) => (tree) => {
|
|
25
60
|
if (tree.path === file) {
|
|
26
61
|
return [[file]]
|
|
@@ -38,35 +73,44 @@ const traverse = (file) => (tree) => {
|
|
|
38
73
|
|
|
39
74
|
const removeInitialDot = (path) => path.replace(/^\.\//, '')
|
|
40
75
|
|
|
41
|
-
const
|
|
76
|
+
const _resolveAbsolutePath = (cwd) => (p) => typeof p === 'string' ? path.resolve(cwd, p) : p
|
|
42
77
|
|
|
43
|
-
const find = ({
|
|
78
|
+
const find = async ({
|
|
44
79
|
entryPoints,
|
|
45
|
-
|
|
80
|
+
filePath,
|
|
46
81
|
skipRegex,
|
|
47
82
|
verbose,
|
|
83
|
+
webpackConfig,
|
|
84
|
+
typescriptConfig,
|
|
48
85
|
cwd = process.cwd()
|
|
49
86
|
}) => {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
)
|
|
87
|
+
const resolveAbsolutePath = _resolveAbsolutePath(cwd)
|
|
88
|
+
const absoluteEntryPoints = entryPoints.map(resolveAbsolutePath)
|
|
89
|
+
const globEscapedEntryPoints = entryPoints.map(escapeGlob);
|
|
53
90
|
|
|
54
91
|
if (verbose) {
|
|
55
92
|
console.log('Entry points:')
|
|
56
93
|
console.log(absoluteEntryPoints)
|
|
57
94
|
console.log('Getting dependency set for entry points...')
|
|
58
95
|
}
|
|
59
|
-
const deps =
|
|
96
|
+
const deps = typescriptConfig ? await parseDependencyTree(globEscapedEntryPoints, { context: process.cwd() }) : getDepsSet(
|
|
97
|
+
absoluteEntryPoints,
|
|
98
|
+
skipRegex,
|
|
99
|
+
resolveAbsolutePath(webpackConfig),
|
|
100
|
+
resolveAbsolutePath(typescriptConfig)
|
|
101
|
+
)
|
|
102
|
+
|
|
60
103
|
const cleanedEntryPoints = entryPoints.map(removeInitialDot)
|
|
104
|
+
const cleanedFilePath = removeInitialDot(filePath)
|
|
61
105
|
if (verbose) {
|
|
62
106
|
console.log('Building dependency trees for entry points...')
|
|
63
107
|
}
|
|
64
|
-
const forest = cleanedEntryPoints.map(buildTree(deps))
|
|
108
|
+
const forest = cleanedEntryPoints.map(typescriptConfig ? buildTreeDpdm(deps) : buildTree(deps))
|
|
65
109
|
if (verbose) {
|
|
66
110
|
console.log('Finding paths in dependency trees...')
|
|
67
111
|
}
|
|
68
112
|
const resolvedPaths = forest.reduce((allPaths, tree) => {
|
|
69
|
-
const paths = traverse(
|
|
113
|
+
const paths = traverse(cleanedFilePath)(tree)
|
|
70
114
|
return [...allPaths, paths]
|
|
71
115
|
}, [])
|
|
72
116
|
return resolvedPaths
|
package/getDepsSet.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
const depcruise = require('dependency-cruiser').cruise
|
|
2
|
-
|
|
3
|
-
const
|
|
2
|
+
// eslint-disable-next-line
|
|
3
|
+
const resolveWebpackConfig = require('dependency-cruiser/config-utl/extract-webpack-resolve-config')
|
|
4
|
+
// eslint-disable-next-line
|
|
5
|
+
const resolveTsConfig = require('dependency-cruiser/config-utl/extract-ts-config')
|
|
6
|
+
const getDepsSet = (entryPoints, skipRegex, webpackConfigPath, tsConfigPath) => {
|
|
4
7
|
const skip =
|
|
5
8
|
skipRegex || '(node_modules|/__tests__|/__test__|/__mockContent__|.scss)'
|
|
9
|
+
const webpackResolveOptions = webpackConfigPath ? resolveWebpackConfig(webpackConfigPath) : null
|
|
10
|
+
const tsConfigOptions = tsConfigPath ? resolveTsConfig(tsConfigPath) : null
|
|
6
11
|
|
|
7
|
-
const
|
|
12
|
+
const result = depcruise(entryPoints, {
|
|
8
13
|
exclude: skip,
|
|
9
14
|
doNotFollow: { path: skip },
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return dependencies.modules
|
|
15
|
+
tsPreCompilationDeps: true,
|
|
16
|
+
|
|
17
|
+
}, webpackResolveOptions, tsConfigOptions)
|
|
18
|
+
return result.output.modules
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
module.exports = getDepsSet
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rev-dep",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Reverse dependency resolution tool built with dependency-cruiser",
|
|
5
5
|
"main": "find.js",
|
|
6
6
|
"bin": "cli.js",
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"commander": "^6.1.0",
|
|
33
|
-
"dependency-cruiser": "
|
|
33
|
+
"dependency-cruiser": "9.23.0",
|
|
34
|
+
"dpdm": "^3.8.0",
|
|
35
|
+
"glob-escape": "^0.0.2"
|
|
34
36
|
},
|
|
35
37
|
"devDependencies": {
|
|
36
38
|
"eslint": "^7.11.0",
|