rev-dep 0.3.0 → 1.0.0-alpha.2

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.
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getEntryPoints = exports.findEntryPointsInDepsTree = exports.getDirectoriesForEntryPointsSearch = void 0;
7
+ const minimatch_1 = __importDefault(require("minimatch"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const promises_1 = __importDefault(require("fs/promises"));
10
+ const utils_1 = require("./utils");
11
+ const getDepsTree_1 = require("./getDepsTree");
12
+ const ignore_1 = __importDefault(require("ignore"));
13
+ const getDirectoriesForEntryPointsSearch = async (dir) => {
14
+ const entries = await promises_1.default.readdir(dir);
15
+ const directories = await (0, utils_1.asyncFilter)(entries, async (pathName) => {
16
+ if (pathName === 'node_modules' || pathName.startsWith('.')) {
17
+ return false;
18
+ }
19
+ const stat = await promises_1.default.lstat(path_1.default.resolve(dir, pathName));
20
+ return stat.isDirectory();
21
+ });
22
+ const joinedWithDir = directories.map((pathName) => path_1.default.join(dir, pathName));
23
+ return [
24
+ ...joinedWithDir,
25
+ ...(await Promise.all(joinedWithDir.map(exports.getDirectoriesForEntryPointsSearch))).flat(1)
26
+ ];
27
+ };
28
+ exports.getDirectoriesForEntryPointsSearch = getDirectoriesForEntryPointsSearch;
29
+ const findEntryPointsInDepsTree = (deps, exclude = [], include = undefined) => {
30
+ const referencedIds = new Set();
31
+ Object.values(deps).forEach((entry) => {
32
+ if (entry !== null) {
33
+ entry.forEach(({ id }) => referencedIds.add(id));
34
+ }
35
+ });
36
+ return Object.keys(deps)
37
+ .filter((id) => /\.(ts|tsx|mjs|js|jsx)$/.test(id) &&
38
+ !/node_modules/.test(id) &&
39
+ !referencedIds.has(id))
40
+ .filter((id) => exclude.reduce((result, pattern) => result && !(0, minimatch_1.default)(id, pattern), true))
41
+ .filter((id) => include
42
+ ? include.reduce((result, pattern) => result || (0, minimatch_1.default)(id, pattern), false)
43
+ : true)
44
+ .sort();
45
+ };
46
+ exports.findEntryPointsInDepsTree = findEntryPointsInDepsTree;
47
+ const getEntryPoints = async ({ cwd, exclude, include, webpackConfigPath }) => {
48
+ const dirs = await (0, exports.getDirectoriesForEntryPointsSearch)(cwd);
49
+ const globs = dirs
50
+ .map((dirName) => path_1.default.relative(cwd, dirName))
51
+ .map((dirName) => `${dirName}/*`);
52
+ const globsWithRoot = ['*', ...globs];
53
+ const depsTree = await (0, getDepsTree_1.getDepsTree)(cwd, globsWithRoot, webpackConfigPath);
54
+ const possibleEntryPoints = (0, exports.findEntryPointsInDepsTree)(depsTree, exclude, include);
55
+ const ignoreInstance = (0, ignore_1.default)();
56
+ let gitignore = '';
57
+ try {
58
+ gitignore = (await promises_1.default.readFile(path_1.default.join(cwd, '.gitignore'))).toString();
59
+ const lines = gitignore.split('\n');
60
+ const nonCommentedNonEmptyLines = lines
61
+ .filter((line) => !/^(\s*)#/.test(line))
62
+ .filter((line) => !/^(\s*)$/.test(line));
63
+ gitignore = nonCommentedNonEmptyLines.join('\n');
64
+ }
65
+ catch (e) {
66
+ e;
67
+ }
68
+ ignoreInstance.add(gitignore);
69
+ return [ignoreInstance.filter(possibleEntryPoints), depsTree];
70
+ };
71
+ exports.getEntryPoints = getEntryPoints;
@@ -0,0 +1,21 @@
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;
@@ -0,0 +1,21 @@
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;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.findTsConfig = exports.resolvePath = exports.sanitizeUserEntryPoints = exports.asyncFilter = exports.createResolveAbsolutePath = exports.removeInitialDot = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const glob_escape_1 = __importDefault(require("glob-escape"));
10
+ const removeInitialDot = (path) => path.replace(/^\.\//, '');
11
+ exports.removeInitialDot = removeInitialDot;
12
+ const createResolveAbsolutePath = (cwd) => (p) => (typeof p === 'string' ? path_1.default.resolve(cwd, p) : p);
13
+ exports.createResolveAbsolutePath = createResolveAbsolutePath;
14
+ const asyncFilter = async (arr, predicate) => {
15
+ const results = await Promise.all(arr.map(predicate));
16
+ return arr.filter((_v, index) => results[index]);
17
+ };
18
+ exports.asyncFilter = asyncFilter;
19
+ const sanitizeUserEntryPoints = (entryPoints) => {
20
+ const globEscapedEntryPoints = entryPoints.map(glob_escape_1.default);
21
+ return globEscapedEntryPoints;
22
+ };
23
+ exports.sanitizeUserEntryPoints = sanitizeUserEntryPoints;
24
+ const resolvePath = (p) => {
25
+ if (!p || path_1.default.isAbsolute(p)) {
26
+ return p;
27
+ }
28
+ return path_1.default.resolve(p);
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": "0.3.0",
3
+ "version": "1.0.0-alpha.2",
4
4
  "description": "Reverse dependency resolution tool built with dependency-cruiser",
5
- "main": "find.js",
6
- "bin": "cli.js",
5
+ "main": "lib/find.js",
6
+ "bin": "bin.js",
7
7
  "files": [
8
- "find.js",
9
- "cli.js",
10
- "getDepsSet.js"
8
+ "dist/**",
9
+ "lib/**",
10
+ "bin.js",
11
+ "babel.js"
11
12
  ],
12
13
  "author": "Jakub Mazurek @jayu",
13
14
  "license": "MIT",
@@ -20,28 +21,43 @@
20
21
  "node": ">=10"
21
22
  },
22
23
  "scripts": {
23
- "lint": "eslint *.js",
24
- "lint:fix": "eslint --fix *.js",
25
- "format": "prettier --check *.js",
26
- "format:fix": "prettier --write *.js",
27
- "cli": "node cli.js",
24
+ "lint": "eslint --ext .js,.ts src",
25
+ "lint:fix": "yarn lint --fix",
26
+ "docs-gen": "node ./scripts/addDocsToReadme.js",
27
+ "dev": "node bin",
28
28
  "test": "jest",
29
- "release": "release-it"
29
+ "release": "release-it",
30
+ "build": "tsc",
31
+ "build:watch": "tsc --watch",
32
+ "typecheck": "tsc --noEmit"
30
33
  },
31
34
  "dependencies": {
35
+ "@babel/parser": "^7.17.8",
36
+ "@babel/template": "^7.16.7",
37
+ "@types/dedent": "^0.7.0",
38
+ "colorette": "^2.0.16",
32
39
  "commander": "^6.1.0",
40
+ "dedent": "^0.7.0",
33
41
  "dependency-cruiser": "9.23.0",
34
42
  "dpdm": "^3.8.0",
35
- "glob-escape": "^0.0.2"
43
+ "glob-escape": "^0.0.2",
44
+ "ignore": "^5.2.0",
45
+ "is-builtin-module": "^3.1.0",
46
+ "minimatch": "^5.0.1"
36
47
  },
37
48
  "devDependencies": {
49
+ "@babel/types": "^7.17.0",
50
+ "@typescript-eslint/eslint-plugin": "^5.16.0",
51
+ "@typescript-eslint/parser": "^5.16.0",
38
52
  "eslint": "^7.11.0",
39
- "eslint-config-prettier": "^6.13.0",
53
+ "eslint-config-prettier": "^8.5.0",
40
54
  "eslint-plugin-jest": "^24.1.0",
41
55
  "eslint-plugin-node": "^11.1.0",
56
+ "eslint-plugin-prettier": "^4.0.0",
42
57
  "jest": "^26.5.3",
43
58
  "mock-fs": "^4.13.0",
44
59
  "prettier": "^2.1.2",
45
- "release-it": "^14.2.1"
60
+ "release-it": "^14.2.1",
61
+ "typescript": "^4.6.2"
46
62
  }
47
63
  }
package/cli.js DELETED
@@ -1,69 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const package = require('./package.json')
4
- const { Command } = require('commander')
5
-
6
- const { find } = require('./find')
7
- const program = new Command('rev-dep')
8
- program.version(package.version, '-v, --version')
9
-
10
- const pathToString = (str, f, i) => {
11
- return `${str ? `${str}\n` : ''}${' '.repeat(i)} ➞ ${f}`
12
- }
13
-
14
- program
15
- .command('resolve <filePath> <entryPoints...>')
16
- .option(
17
- '-cs, --compactSummary',
18
- 'print a compact summary of reverse resolution with a count of found paths'
19
- )
20
- .option('--verbose', 'print current action information')
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
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
- }
44
- console.log('Results:\n')
45
- if (compactSummary) {
46
- const maxEntryLength = entryPoints.reduce((maxLength, entryPoint) => {
47
- return entryPoint.length > maxLength ? entryPoint.length : maxLength
48
- }, 0)
49
- let total = 0
50
- entryPoints.forEach((entry, index) => {
51
- console.log(`${entry.padEnd(maxEntryLength)} :`, results[index].length)
52
- total += results[index].length
53
- })
54
- console.log('\nTotal:', total)
55
- } else {
56
- results.forEach((entryPointResults, index) => {
57
- entryPointResults.forEach((path) => {
58
- console.log(path.reduce(pathToString, ''), '\n')
59
- })
60
- if (index < results.length - 1) {
61
- console.log('_'.repeat(process.stdout.columns))
62
- }
63
- })
64
- }
65
-
66
-
67
- })
68
-
69
- program.parse(process.argv)
package/find.js DELETED
@@ -1,119 +0,0 @@
1
- const path = require('path')
2
- const getDepsSet = require('./getDepsSet')
3
- const { parseDependencyTree } = require('dpdm');
4
- const escapeGlob = require('glob-escape');
5
-
6
- const buildTree = (deps) => (entryPoint) => {
7
- const inner = (path) => {
8
- const dep = deps.find((d) => d.source === path)
9
- if (dep === undefined) {
10
- throw new Error(`Dependency '${path}' not found!`)
11
- }
12
-
13
- return {
14
- path,
15
- children: dep.dependencies.map((d) => {
16
- if (d.circular) {
17
- return { path: 'CIRCULAR', children: [] }
18
- }
19
- return inner(d.resolved)
20
- })
21
- }
22
- }
23
- return inner(entryPoint)
24
- }
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
-
59
- const traverse = (file) => (tree) => {
60
- if (tree.path === file) {
61
- return [[file]]
62
- } else {
63
- return tree.children
64
- .map(traverse(file)) // [ [[]],[[]],[[]] ]
65
- .filter((p) => p.length > 0)
66
- .map((pathsArr) => pathsArr.filter((p) => p.length > 0))
67
- .reduce((flat, subPath) => {
68
- return [...flat, ...subPath]
69
- }, [])
70
- .map((p) => [tree.path, ...p])
71
- }
72
- }
73
-
74
- const removeInitialDot = (path) => path.replace(/^\.\//, '')
75
-
76
- const _resolveAbsolutePath = (cwd) => (p) => typeof p === 'string' ? path.resolve(cwd, p) : p
77
-
78
- const find = async ({
79
- entryPoints,
80
- filePath,
81
- skipRegex,
82
- verbose,
83
- webpackConfig,
84
- typescriptConfig,
85
- cwd = process.cwd()
86
- }) => {
87
- const resolveAbsolutePath = _resolveAbsolutePath(cwd)
88
- const absoluteEntryPoints = entryPoints.map(resolveAbsolutePath)
89
- const globEscapedEntryPoints = entryPoints.map(escapeGlob);
90
-
91
- if (verbose) {
92
- console.log('Entry points:')
93
- console.log(absoluteEntryPoints)
94
- console.log('Getting dependency set for entry points...')
95
- }
96
- const deps = typescriptConfig ? await parseDependencyTree(globEscapedEntryPoints, { context: process.cwd() }) : getDepsSet(
97
- absoluteEntryPoints,
98
- skipRegex,
99
- resolveAbsolutePath(webpackConfig),
100
- resolveAbsolutePath(typescriptConfig)
101
- )
102
-
103
- const cleanedEntryPoints = entryPoints.map(removeInitialDot)
104
- const cleanedFilePath = removeInitialDot(filePath)
105
- if (verbose) {
106
- console.log('Building dependency trees for entry points...')
107
- }
108
- const forest = cleanedEntryPoints.map(typescriptConfig ? buildTreeDpdm(deps) : buildTree(deps))
109
- if (verbose) {
110
- console.log('Finding paths in dependency trees...')
111
- }
112
- const resolvedPaths = forest.reduce((allPaths, tree) => {
113
- const paths = traverse(cleanedFilePath)(tree)
114
- return [...allPaths, paths]
115
- }, [])
116
- return resolvedPaths
117
- }
118
-
119
- module.exports = { find }
package/getDepsSet.js DELETED
@@ -1,21 +0,0 @@
1
- const depcruise = require('dependency-cruiser').cruise
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) => {
7
- const skip =
8
- skipRegex || '(node_modules|/__tests__|/__test__|/__mockContent__|.scss)'
9
- const webpackResolveOptions = webpackConfigPath ? resolveWebpackConfig(webpackConfigPath) : null
10
- const tsConfigOptions = tsConfigPath ? resolveTsConfig(tsConfigPath) : null
11
-
12
- const result = depcruise(entryPoints, {
13
- exclude: skip,
14
- doNotFollow: { path: skip },
15
- tsPreCompilationDeps: true,
16
-
17
- }, webpackResolveOptions, tsConfigOptions)
18
- return result.output.modules
19
- }
20
-
21
- module.exports = getDepsSet