├── .coveralls.yml ├── .flowconfig ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── flow-typed └── deps-report │ └── index.js ├── greenkeeper.json ├── lib ├── cli.js ├── find-dependencies.js ├── find-dependents.js ├── index.js └── util.js ├── package.json └── tests ├── project-react-js-test ├── .flowconfig ├── .gitignore ├── README.md ├── package.json ├── project-react-js-test.sublime-workspace ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ └── registerServiceWorker.js ├── project-test ├── a.js ├── a.ts ├── a1.ts ├── b.ts ├── c.js ├── c.ts ├── c │ └── d.js ├── e │ └── b.js ├── src │ ├── templates │ │ ├── index.js │ │ ├── main.js │ │ └── package.json │ └── utilities │ │ ├── index.js │ │ ├── relative.js │ │ └── utilityA.js ├── webpack.config.js └── webpack2.config.js ├── test.js └── testResults.json /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-pro 2 | repo_token: iSNwmDqi0eD4yt97QvY0ppIGajXGDR6I7 -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /.je-project-settings/.* 3 | 4 | [include] 5 | 6 | [libs] 7 | 8 | [lints] 9 | 10 | [options] 11 | suppress_comment= \\(.\\|\n\\)*\\$Ignore 12 | 13 | [strict] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # misc 7 | .DS_Store 8 | /.nyc_output 9 | /.je-project-settings 10 | deps-report.sublime-* 11 | 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | 5 | cache: 6 | directories: 7 | - "node_modules" 8 | 9 | script: 10 | - npm test 11 | 12 | after_success: 13 | - npm run coverage 14 | 15 | notifications: 16 | email: false -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Lorenzo Pichilli 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deps-report 2 | 3 | ![node version](https://img.shields.io/node/v/deps-report.svg) 4 | [![npm downloads](https://img.shields.io/npm/dm/deps-report.svg)](https://www.npmjs.com/package/deps-report) 5 | [![deps-report version](https://img.shields.io/npm/v/deps-report.svg)](https://www.npmjs.com/package/deps-report) 6 | [![Travis](https://img.shields.io/travis/pichillilorenzo/deps-report.svg?branch=master)](https://travis-ci.org/pichillilorenzo/deps-report) 7 | [![Coverage Status](https://coveralls.io/repos/github/pichillilorenzo/deps-report/badge.svg?branch=master)](https://coveralls.io/github/pichillilorenzo/deps-report?branch=master) 8 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](/LICENSE.txt) 9 | [![Greenkeeper badge](https://badges.greenkeeper.io/pichillilorenzo/deps-report.svg)](https://greenkeeper.io/) 10 | [![Donate to this project using Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.me/LorenzoPichilli) 11 | [![Donate to this project using Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://www.patreon.com/bePatron?u=9269604) 12 | 13 | Generate reports about dependencies and dependents of your JavaScript/TypeScript files through an **AST**. It supports `import` and `require` statements. 14 | 15 | Parsers used: 16 | - [flow-parser](https://www.npmjs.com/package/flow-parser) for `.js` files 17 | - [typescript](https://github.com/Microsoft/TypeScript) for `.ts` files 18 | 19 | 20 | ## Install 21 | 22 | ``` 23 | npm install -g deps-report 24 | ``` 25 | 26 | ## Screenshots 27 | ![](https://drive.google.com/uc?authuser=0&id=1GHYVTXM6KSaAtjOvNqA-2Q-z5TKc-nQC&export=download) 28 | 29 | 30 | ## CLI Usage 31 | 32 | ``` 33 | Usage: deps-report [options] [command] 34 | 35 | Options: 36 | 37 | -V, --version output the version number 38 | -j, --json Output results in JSON format 39 | -p, --pretty Pretty-print JSON output (implies --json) 40 | -a, --abs-path Print absolute path of dependencies/dependents 41 | -e, --exclude-node-modules Don't consider node_modules dependencies 42 | -w, --webpack-config [webpackConfigFile] Webpack config file for resolving aliased modules 43 | -s, --specifiers Show specifiers imported by the dependency/dependent 44 | --no-color Display terminal output without colors 45 | -h, --help output usage information 46 | 47 | Commands: 48 | 49 | find-dependencies [options] [otherGlobs...] 50 | 51 | Usage: find-dependencies [options] [otherGlobs...] 52 | Options: 53 | 54 | -c, --circular Show if there are some circular dependencies 55 | --only-not-found Show all modules that have no dependencies 56 | --hide-not-found Hide all modules that have no dependencies 57 | --only-circular Show only circular dependencies 58 | -h, --help output usage information 59 | 60 | 61 | find-dependents [options] [otherGlobs...] 62 | 63 | Usage: find-dependents [options] [otherGlobs...] 64 | Options: 65 | 66 | -r, --root [root] Root folder from where to start the search. Default is the dirname of each glob entry 67 | -c, --circular Show if there are some circular dependencies 68 | --only-not-found Show all modules that no one is depending on 69 | --hide-not-found Hide all modules that no one is depending on 70 | --only-circular Show only circular dependencies 71 | -h, --help output usage information 72 | 73 | ``` 74 | 75 | 76 | ## Examples find-dependencies 77 | 78 | ``` 79 | $ deps-report find-dependencies tests/project-react-js-test/src/App.js 80 | 81 | Processed 1 file in 122.297ms. 82 | 83 | tests/project-react-js-test/src/App.js, found 3 dependencies: 84 | 1) react 85 | 2) ./logo.svg 86 | 3) ./App.css 87 | 88 | 89 | $ deps-report -s find-dependencies tests/project-react-js-test/src/App.js 90 | 91 | Processed 1 file in 127.538ms. 92 | 93 | tests/project-react-js-test/src/App.js, found 3 dependencies: 94 | 1) react, specifiers imported: default as React, Component 95 | 2) ./logo.svg, specifiers imported: default as logo 96 | 3) ./App.css 97 | 98 | 99 | $ deps-report -a find-dependencies 'tests/project-react-js-test/src/*.js' 100 | 101 | Processed 4 files in 149.446ms. 102 | 103 | tests/project-react-js-test/src/App.js, found 3 dependencies: 104 | 1) react 105 | 2) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/logo.svg 106 | 3) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.css 107 | 108 | tests/project-react-js-test/src/App.test.js, found 3 dependencies: 109 | 1) react 110 | 2) react-dom 111 | 3) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js 112 | 113 | tests/project-react-js-test/src/index.js, found 5 dependencies: 114 | 1) react 115 | 2) react-dom 116 | 3) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.css 117 | 4) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js 118 | 5) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js 119 | 120 | tests/project-react-js-test/src/registerServiceWorker.js, found 0 dependencies: 121 | No dependencies found! 122 | 123 | 124 | $ deps-report -ae find-dependencies 'tests/project-react-js-test/src/*.js' 125 | 126 | Processed 4 files in 139.507ms. 127 | 128 | tests/project-react-js-test/src/App.js, found 2 dependencies: 129 | 1) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/logo.svg 130 | 2) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.css 131 | 132 | tests/project-react-js-test/src/App.test.js, found 1 dependency: 133 | 1) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js 134 | 135 | tests/project-react-js-test/src/index.js, found 3 dependencies: 136 | 1) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.css 137 | 2) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js 138 | 3) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js 139 | 140 | tests/project-react-js-test/src/registerServiceWorker.js, found 0 dependencies: 141 | No dependencies found! 142 | 143 | 144 | $ deps-report -ae find-dependencies 'tests/project-react-js-test/src/*.js' '!tests/project-react-js-test/src/**/*.test.js' 145 | 146 | Processed 3 files in 141.737ms. 147 | 148 | tests/project-react-js-test/src/App.js, found 2 dependencies: 149 | 1) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/logo.svg 150 | 2) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.css 151 | 152 | tests/project-react-js-test/src/index.js, found 3 dependencies: 153 | 1) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.css 154 | 2) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js 155 | 3) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js 156 | 157 | tests/project-react-js-test/src/registerServiceWorker.js, found 0 dependencies: 158 | No dependencies found! 159 | 160 | 161 | $ deps-report -w tests/project-test/webpack.config.js find-dependencies tests/project-test/a.js 162 | 163 | Processed 1 file in 109.559ms. 164 | 165 | tests/project-test/a.js, found 12 dependencies: 166 | 1) path 167 | 2) fs 168 | 3) ./c/d.js 169 | 4) Utilities/index.js 170 | 5) UtilitiesRelativePath 171 | 6) Utilities/utilityA.js 172 | 7) Templates/main.js 173 | 8) TemplatesMain 174 | 9) MyPath 175 | 10) fs 176 | 11) ./e/b.js 177 | 12) ./c/d.js 178 | 179 | 180 | $ deps-report -w tests/project-test/webpack.config.js find-dependencies --only-circular tests/project-test/a.js 181 | 182 | Processed 1 file in 153.199ms. 183 | 184 | tests/project-test/a.js, found 2 dependencies: 185 | 1) ./c/d.js 186 | 2) ./c/d.js 187 | 188 | 189 | $ deps-report -ae -w tests/project-test/webpack.config.js find-dependencies tests/project-test/a.js 190 | 191 | Processed 1 file in 118.478ms. 192 | 193 | tests/project-test/a.js, found 8 dependencies: 194 | 1) /Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js 195 | 2) /Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/index.js 196 | 3) /Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/relative.js 197 | 4) /Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/utilityA.js 198 | 5) /Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js 199 | 6) /Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js 200 | 7) /Users/lorenzo/Desktop/deps-report/tests/project-test/e/b.js 201 | 8) /Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js 202 | 203 | 204 | $ deps-report -w tests/project-test/webpack.config.js find-dependencies --only-not-found "tests/project-test/*.ts" 205 | 206 | Processed 1 file in 42.623ms. 207 | 208 | tests/project-test/c.ts 209 | ``` 210 | 211 | JSON format example: 212 | 213 | ``` 214 | $ deps-report -jps find-dependencies -c tests/project-react-js-test/src/App.js 215 | 216 | { 217 | "tests/project-react-js-test/src/App.js": { 218 | "absolutePath": "/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js", 219 | "files": 3, 220 | "dependencies": [ 221 | { 222 | "importPath": "react", 223 | "importAbsolutePath": "react", 224 | "isCircularDependency": null, 225 | "isNodeModule": true, 226 | "specifiers": [ 227 | { 228 | "name": "React", 229 | "alias": "", 230 | "isDefault": true 231 | }, 232 | { 233 | "name": "Component", 234 | "alias": "", 235 | "isDefault": false 236 | } 237 | ] 238 | }, 239 | { 240 | "importPath": "./logo.svg", 241 | "importAbsolutePath": "/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/logo.svg", 242 | "isCircularDependency": false, 243 | "isNodeModule": false, 244 | "specifiers": [ 245 | { 246 | "name": "logo", 247 | "alias": "", 248 | "isDefault": true 249 | } 250 | ] 251 | }, 252 | { 253 | "importPath": "./App.css", 254 | "importAbsolutePath": "/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.css", 255 | "isCircularDependency": false, 256 | "isNodeModule": false, 257 | "specifiers": [] 258 | } 259 | ] 260 | } 261 | } 262 | ``` 263 | 264 | 265 | ## Examples find-dependents 266 | 267 | ``` 268 | $ deps-report find-dependents tests/project-react-js-test/src/App.js 269 | 270 | Processed 1 file in 199.088ms. 271 | 272 | tests/project-react-js-test/src/App.js, found 2 dependents: 273 | 1) tests/project-react-js-test/src/App.test.js 274 | 2) tests/project-react-js-test/src/index.js 275 | 276 | 277 | $ deps-report -s find-dependents tests/project-react-js-test/src/App.js 278 | 279 | Processed 1 file in 197.761ms. 280 | 281 | tests/project-react-js-test/src/App.js, found 2 dependents: 282 | 1) tests/project-react-js-test/src/App.test.js, specifiers imported: default as App 283 | 2) tests/project-react-js-test/src/index.js, specifiers imported: default as App 284 | 285 | 286 | $ deps-report -as find-dependents tests/project-react-js-test/src/App.js 287 | 288 | Processed 1 file in 199.046ms. 289 | 290 | tests/project-react-js-test/src/App.js, found 2 dependents: 291 | 1) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.test.js, specifiers imported: default as App 292 | 2) /Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.js, specifiers imported: default as App 293 | 294 | 295 | $ deps-report find-dependents tests/project-test/a1.ts 296 | 297 | Processed 1 file in 191.590ms. 298 | 299 | tests/project-test/a1.ts, found 0 dependents: 300 | No dependents found! 301 | 302 | 303 | $ deps-report find-dependents -c -r tests/project-test tests/project-test/c/d.js 304 | 305 | Processed 1 file in 218.268ms. 306 | 307 | tests/project-test/c/d.js, found 4 dependents: 308 | 1) tests/project-test/a.js, Circular Dependency 309 | 2) tests/project-test/e/b.js 310 | 3) tests/project-test/a.ts 311 | 4) tests/project-test/b.ts 312 | 313 | 314 | $ deps-report -es -w tests/project-test/webpack.config.js find-dependents -r tests/project-test/ tests/project-test/src/utilities/index.js tests/project-test/src/templates/main.js 315 | 316 | Processed 2 files in 852.220ms. 317 | 318 | tests/project-test/src/utilities/index.js, found 2 dependents: 319 | 1) tests/project-test/a.js, specifiers imported: default as Utilities 320 | 2) tests/project-test/a.ts, specifiers imported: default as Utilities 321 | 322 | tests/project-test/src/templates/main.js, found 3 dependents: 323 | 1) tests/project-test/a.js, specifiers imported: default as templates 324 | 2) tests/project-test/src/utilities/index.js, specifiers imported: default as templates 325 | 3) tests/project-test/a.ts, specifiers imported: default as templates 326 | ``` 327 | 328 | You can search also **images** and **css** files imported in your javascript files (such as in a React project): 329 | 330 | ``` 331 | $ deps-report -s find-dependents tests/project-react-js-test/src/logo.svg 332 | 333 | Processed 1 file in 218.263ms. 334 | 335 | tests/project-react-js-test/src/logo.svg, found 1 dependent: 336 | 1) tests/project-react-js-test/src/App.js, specifiers imported: default as logo 337 | 338 | 339 | $ deps-report find-dependents tests/project-react-js-test/src/App.css 340 | 341 | Processed 1 file in 213.301ms. 342 | 343 | tests/project-react-js-test/src/App.css, found 1 dependent: 344 | 1) tests/project-react-js-test/src/App.js 345 | ``` 346 | 347 | JSON format example: 348 | 349 | ``` 350 | $ deps-report -jps find-dependents -c tests/project-react-js-test/src/App.js 351 | 352 | { 353 | "tests/project-react-js-test/src/App.js": { 354 | "absolutePath": "/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js", 355 | "files": 2, 356 | "dependents": [ 357 | { 358 | "filePath": "tests/project-react-js-test/src/App.test.js", 359 | "fileAbsolutePath": "/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.test.js", 360 | "importPath": "./App.js", 361 | "importAbsolutePath": "/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js", 362 | "isCircularDependency": false, 363 | "specifiers": [ 364 | { 365 | "name": "App", 366 | "alias": "", 367 | "isDefault": true 368 | } 369 | ] 370 | }, 371 | { 372 | "filePath": "tests/project-react-js-test/src/index.js", 373 | "fileAbsolutePath": "/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.js", 374 | "importPath": "./App.js", 375 | "importAbsolutePath": "/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js", 376 | "isCircularDependency": false, 377 | "specifiers": [ 378 | { 379 | "name": "App", 380 | "alias": "", 381 | "isDefault": true 382 | } 383 | ] 384 | } 385 | ] 386 | } 387 | } 388 | ``` 389 | 390 | 391 | ## API Usage 392 | 393 | ```javascript 394 | const depsReport = require('deps-report') 395 | 396 | // find-dependencies command options 397 | 398 | let optionsFindDependencies = { 399 | circular: false, // if true, it will try to see if there are some circular dependencies with input files 400 | onlyCircular: false, // if true, it will return only dependecies with circular dependency with input files 401 | onlyNotFound: false, // if true, it will return all modules that have no dependencies 402 | hideNotFound: false, // used only for CLI output 403 | parent: { 404 | excludeNodeModules: false, // if true, it will exclude all node modules 405 | json: false, // used only for CLI output 406 | pretty: false, // used only for CLI output 407 | absPath: false, // used only for CLI output 408 | color: false, // used only for CLI output 409 | webpackConfig: 'tests/project-test/webpack.config.js', // used to resolve module aliases 410 | specifiers: false // if true, it will populate the specifiers imported by the dependency 411 | } 412 | } 413 | 414 | // see the corresponding JSON format example 415 | depsReport.findDependencies(["tests/project-test/a.js"], optionsFindDependencies) 416 | 417 | 418 | // find-dependents command options 419 | 420 | let optionsFindDependents = { 421 | root: 'tests/project-test', // Root folder from where to start the search of dependents 422 | circular: false, // if true, it will try to see if there are some circular dependencies with input files 423 | onlyCircular: false, // if true, it will return only dependents with circular dependency with input files 424 | onlyNotFound: false, // if true, it will return all modules that no one is depending on 425 | hideNotFound: false, // used only for CLI output 426 | parent: { 427 | excludeNodeModules: false, // if true, it will exclude all node modules 428 | json: false, // used only for CLI output 429 | pretty: false, // used only for CLI output 430 | absPath: false, // used only for CLI output 431 | color: false, // used only for CLI output 432 | webpackConfig: 'tests/project-test/webpack.config.js', // used to resolve module aliases 433 | specifiers: false // if true, it will populate the specifiers imported by the dependent 434 | } 435 | } 436 | 437 | // see the corresponding JSON format example 438 | depsReport.findDependents(["tests/project-test/src/templates/*.js", "tests/project-test/src/utilities/*.js"], optionsFindDependents) 439 | ``` 440 | 441 | ## Support 442 | 443 | ### Feature request/enhancement 444 | For feature requests/enhancement, create an issue! 445 | 446 | [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.me/LorenzoPichilli) 447 | [![Become a Patron](https://img.shields.io/badge/-Become%20a%20Patron!-red.svg?style=for-the-badge)](https://www.patreon.com/bePatron?u=9269604) 448 | 449 | 450 | ## License 451 | 452 | _MIT License_ -------------------------------------------------------------------------------- /flow-typed/deps-report/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | type DepsReportCommandOptions = { 4 | excludeNodeModules: boolean, 5 | json: boolean, 6 | pretty: boolean, 7 | absPath: boolean, 8 | webpackConfig: string, 9 | specifiers: boolean, 10 | color: boolean 11 | } 12 | 13 | type FindDependenciesCommandOptions = { 14 | circular: boolean, 15 | onlyCircular: boolean, 16 | onlyNotFound: boolean, 17 | hideNotFound: boolean, 18 | parent: DepsReportCommandOptions 19 | } 20 | 21 | type FindDependentsCommandOptions = { 22 | root: string, 23 | circular: boolean, 24 | onlyCircular: boolean, 25 | onlyNotFound: boolean, 26 | hideNotFound: boolean, 27 | parent: DepsReportCommandOptions 28 | } -------------------------------------------------------------------------------- /greenkeeper.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": { 3 | "default": { 4 | "packages": [ 5 | "package.json" 6 | ] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // @flow 4 | 5 | const commander = require('commander'), 6 | chalk = require('chalk'), 7 | findDependencies = require('./find-dependencies'), 8 | findDependents = require('./find-dependents'), 9 | packageJson = require('../package.json'), 10 | version = packageJson.version, 11 | NS_PER_SEC = 1e9, 12 | MS_PER_NS = 1e-6 13 | 14 | commander 15 | .version(version) 16 | .option('-j, --json', 'Output results in JSON format') 17 | .option('-p, --pretty', 'Pretty-print JSON output (implies --json)') 18 | .option('-a, --abs-path', 'Print absolute path of dependencies/dependents') 19 | .option('-e, --exclude-node-modules', 'Don\'t consider node_modules dependencies', false) 20 | .option('-w, --webpack-config [webpackConfigFile]', 'Webpack config file for resolving aliased modules') 21 | .option('-s, --specifiers', 'Show specifiers imported by the dependency/dependent', false) 22 | .option('--no-color', 'Display terminal output without colors') 23 | 24 | commander 25 | .command('find-dependencies [otherGlobs...]') 26 | .option('-c, --circular', 'Show if there are some circular dependencies') 27 | .option('--only-not-found', 'Show all modules that have no dependencies') 28 | .option('--hide-not-found', 'Hide all modules that have no dependencies') 29 | .option('--only-circular', 'Show only circular dependencies') 30 | .action((glob/*: string*/, otherGlobs/*: Array */, options/*: FindDependenciesCommandOptions*/) => { 31 | 32 | const time = process.hrtime() 33 | const result = findDependencies([glob, ...otherGlobs], options) 34 | const diff = process.hrtime(time) 35 | const processTime = ((diff[0] * NS_PER_SEC + diff[1]) * MS_PER_NS).toFixed(3) 36 | 37 | if (options.parent.json) { 38 | const jsonOutput = (options.parent.pretty) ? JSON.stringify(result, null, 2) : JSON.stringify(result) 39 | console.log(jsonOutput) 40 | } 41 | else { 42 | const lengthResult = Object.keys(result).length 43 | console.log(`\nProcessed ${ chalk.yellow.bold(lengthResult) } ${ (lengthResult == 1) ? 'file' : 'files' } in ${ chalk.yellow.bold( processTime + 'ms') }.`) 44 | if (options.onlyNotFound) 45 | console.log('') 46 | 47 | for (let entry in result) { 48 | if (options.onlyNotFound) { 49 | console.log( chalk.cyan.italic( (options.parent.absPath) ? result[entry].absolutePath : entry) ) 50 | } 51 | else { 52 | if (options.hideNotFound && !result[entry].files) 53 | continue 54 | 55 | let i = 0 56 | console.log('') 57 | console.log(chalk.cyan(chalk.bold.italic(entry) + ", found " + chalk.bold(result[entry].files) + " " + ( (result[entry].files == 1) ? "dependency" : "dependencies" ) + ":")) 58 | if (!result[entry].files) 59 | console.log(' ' + chalk.red.bold('No dependencies found!')) 60 | else 61 | for (let dependency of result[entry].dependencies) 62 | console.log( 63 | ( (i < 9) ? ' ' : '' ) + (++i) + ") " + chalk.green.bold( (options.parent.absPath) ? dependency.importAbsolutePath : dependency.importPath ) + 64 | ( (options.circular && dependency.isCircularDependency) ? ', ' + chalk.yellow.bold('Circular Dependency') : '' ) + 65 | ( (options.parent.specifiers && dependency.specifiers.length > 0) ? ", specifiers imported: " + chalk.italic( dependency.specifiers.map((specifier) => {return (specifier.alias) ? specifier.name + " as " + specifier.alias : ( (specifier.isDefault) ? "default as " + specifier.name : specifier.name )}).join(', ') ) : '' ) 66 | ) 67 | } 68 | } 69 | console.log('') 70 | } 71 | 72 | }) 73 | 74 | commander 75 | .command('find-dependents [otherGlobs...]') 76 | .option('-r, --root [root]', 'Root folder from where to start the search. Default is the dirname of each glob entry') 77 | .option('-c, --circular', 'Show if there are some circular dependencies') 78 | .option('--only-not-found', 'Show all modules that no one is depending on') 79 | .option('--hide-not-found', 'Hide all modules that no one is depending on') 80 | .option('--only-circular', 'Show only circular dependencies') 81 | .action((glob/*: string*/, otherGlobs/*: Array */, options/*: FindDependentsCommandOptions*/) => { 82 | 83 | const time = process.hrtime() 84 | const result = findDependents([glob, ...otherGlobs], options) 85 | const diff = process.hrtime(time) 86 | const processTime = ((diff[0] * NS_PER_SEC + diff[1]) * MS_PER_NS).toFixed(3) 87 | 88 | if (options.parent.json) { 89 | const jsonOutput = (options.parent.pretty) ? JSON.stringify(result, null, 2) : JSON.stringify(result) 90 | console.log(jsonOutput) 91 | } 92 | else { 93 | const lengthResult = Object.keys(result).length 94 | console.log(`\nProcessed ${ chalk.yellow.bold(lengthResult) } ${ (lengthResult == 1) ? 'file' : 'files' } in ${ chalk.yellow.bold( processTime + 'ms') }.`) 95 | if (options.onlyNotFound) 96 | console.log('') 97 | 98 | for (let entry in result) { 99 | if (options.onlyNotFound) { 100 | console.log( chalk.cyan.italic( (options.parent.absPath) ? result[entry].absolutePath : entry) ) 101 | } 102 | else { 103 | if (options.hideNotFound && !result[entry].files) 104 | continue 105 | 106 | let i = 0 107 | console.log('') 108 | console.log(chalk.cyan(chalk.bold.italic(entry) + ", found " + chalk.bold(result[entry].files) + " " + ( (result[entry].files == 1) ? "dependent" : "dependents" ) + ":")) 109 | 110 | if (!result[entry].files) 111 | console.log(' ' + chalk.red.bold('No dependents found!')) 112 | else 113 | for (let dependent of result[entry].dependents) 114 | console.log( 115 | ( (i < 9) ? ' ' : '' ) + (++i) + ") " + chalk.green.bold( (options.parent.absPath) ? dependent.fileAbsolutePath : dependent.filePath ) + 116 | ( (options.circular && dependent.isCircularDependency) ? ', ' + chalk.yellow.bold('Circular Dependency') : '' ) + 117 | ( (options.parent.specifiers && dependent.specifiers.length > 0) ? ", specifiers imported: " + chalk.italic( dependent.specifiers.map((specifier) => {return (specifier.alias) ? specifier.name + " as " + specifier.alias : ( (specifier.isDefault) ? "default as " + specifier.name : specifier.name )}).join(', ') ) : '' ) 118 | ) 119 | } 120 | 121 | } 122 | console.log('') 123 | } 124 | 125 | }) 126 | 127 | commander.parse(process.argv) -------------------------------------------------------------------------------- /lib/find-dependencies.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const util = require("./util.js"), 4 | path = require("path"), 5 | fs = require("fs"), 6 | globby = require("globby"), 7 | typescript = require("typescript"), 8 | flowParser = require('flow-parser') 9 | 10 | function findDependencies(globs/*: Array*/, options/*: FindDependenciesCommandOptions*/)/*: Object*/{ 11 | 12 | let inputFiles /*: Array*/= globby.sync(globs) 13 | let result = {} 14 | 15 | for (let inputFile of inputFiles) { 16 | 17 | let absPathInputFile = path.resolve(inputFile) 18 | let data = fs.readFileSync(inputFile, 'utf8') 19 | 20 | let ast = {} 21 | let imports = [] 22 | let dependencies = [] 23 | let isTS = false 24 | let hasNoDependency = true 25 | 26 | // initialize result 27 | result[inputFile] = { 28 | absolutePath: absPathInputFile, 29 | files: dependencies.length, 30 | dependencies 31 | } 32 | 33 | // Apply a first filter to exclude some files: 34 | // Don't consider js files where there is no import/require of inputFile 35 | if ( data.indexOf('require(') == -1 && data.indexOf('import ') == -1 ) 36 | continue 37 | 38 | if (inputFile.trim().endsWith(".ts")) { 39 | isTS = true 40 | ast = typescript.createSourceFile(inputFile, data) 41 | imports = util.typescriptTraverseAST('kind', [typescript.SyntaxKind.VariableDeclaration, typescript.SyntaxKind.ImportDeclaration], ast) 42 | } 43 | else { 44 | ast = flowParser.parse(data) 45 | imports = util.flowTraverseAST('type', ['VariableDeclarator', 'ImportDeclaration'], ast) 46 | } 47 | 48 | for (let imp /*: Object*/ of imports) { 49 | let dependency = { 50 | importPath: '', 51 | importAbsolutePath: '', 52 | isCircularDependency: null, 53 | isNodeModule: false, 54 | specifiers: [] 55 | } 56 | 57 | if (isTS) { 58 | if ( util.isRequireStatement(imp, true) ) { 59 | dependency.importPath = imp.initializer.arguments[0].text 60 | if (options.parent.specifiers && imp.name) { 61 | if (imp.name.kind == typescript.SyntaxKind.Identifier) { 62 | dependency.specifiers.push({ 63 | name: imp.name.escapedText, 64 | alias: '', 65 | isDefault: true 66 | }) 67 | } 68 | else if (imp.name.kind == typescript.SyntaxKind.ObjectBindingPattern) { 69 | for (let element /*: Object*/ of imp.name.elements) { 70 | dependency.specifiers.push({ 71 | name: element.name.escapedText, 72 | alias: '', 73 | isDefault: false 74 | }) 75 | } 76 | } 77 | } 78 | } 79 | else if ( util.isImportStatement(imp, true) ) { 80 | dependency.importPath = imp.moduleSpecifier.text 81 | if (options.parent.specifiers && imp.importClause) { 82 | if (imp.importClause.name) { 83 | dependency.specifiers.push({ 84 | name: imp.importClause.name.escapedText, 85 | alias: '', 86 | isDefault: true 87 | }) 88 | } 89 | if (imp.importClause.namedBindings) { 90 | for (let element /*: Object*/ of imp.importClause.namedBindings.elements) { 91 | dependency.specifiers.push({ 92 | name: (element.propertyName) ? element.propertyName.escapedText : element.name.escapedText, 93 | alias: (element.propertyName) ? element.name.escapedText : '', 94 | isDefault: false 95 | }) 96 | } 97 | } 98 | } 99 | } 100 | } 101 | else { 102 | if ( util.isRequireStatement(imp, false) ) { 103 | dependency.importPath = imp.init.arguments[0].value 104 | if (imp.id) { 105 | if (imp.id.type == 'Identifier') { 106 | dependency.specifiers.push({ 107 | name: imp.id.name, 108 | alias: '', 109 | isDefault: true 110 | }) 111 | } 112 | else if (imp.id.type == 'ObjectPattern') { 113 | for (let property /*: Object*/ of imp.id.properties) { 114 | dependency.specifiers.push({ 115 | name: property.key.name, 116 | alias: '', 117 | isDefault: false 118 | }) 119 | } 120 | } 121 | } 122 | } 123 | else if ( util.isImportStatement(imp, false) ) { 124 | dependency.importPath = imp.source.value 125 | for (let specifier /*: Object*/ of imp.specifiers) { 126 | dependency.specifiers.push({ 127 | name: (specifier.imported) ? specifier.imported.name : specifier.local.name, 128 | alias: (specifier.imported && specifier.imported.name != specifier.local.name) ? specifier.local.name : '', 129 | isDefault: specifier.type == 'ImportDefaultSpecifier' 130 | }) 131 | } 132 | } 133 | } 134 | 135 | if (dependency.importPath) { 136 | let webpackAliasResolved = {} 137 | 138 | if (options.parent.webpackConfig) { 139 | webpackAliasResolved = util.webpackAliasResolver(dependency.importPath, options.parent.webpackConfig) 140 | dependency.importPath = webpackAliasResolved.module 141 | dependency.importAbsolutePath = webpackAliasResolved.moduleAbsPath 142 | } 143 | 144 | if (webpackAliasResolved.isWebpackError) 145 | continue 146 | 147 | dependency.importAbsolutePath = (!dependency.importAbsolutePath) ? path.resolve(path.join(path.dirname(inputFile), dependency.importPath)) : dependency.importAbsolutePath 148 | 149 | if ( !path.extname(dependency.importAbsolutePath) || !fs.existsSync(dependency.importAbsolutePath) ) { 150 | if ( isTS && fs.existsSync( dependency.importAbsolutePath + '.ts' ) ) { 151 | dependency.importAbsolutePath += '.ts' 152 | } 153 | else if (fs.existsSync(dependency.importAbsolutePath + '.js')) { 154 | dependency.importAbsolutePath += '.js' 155 | } 156 | else if ( !isTS && fs.existsSync( dependency.importAbsolutePath + '.ts' ) ) { 157 | // importing .ts file in .js file is an error, so skip it 158 | continue 159 | } 160 | 161 | if (!webpackAliasResolved.keepRelative && !path.extname(dependency.importPath) && fs.existsSync(dependency.importAbsolutePath) ) 162 | dependency.importPath += path.extname(dependency.importAbsolutePath) 163 | } 164 | 165 | if ( (dependency.importAbsolutePath.indexOf("node_modules") == -1 && fs.existsSync(dependency.importAbsolutePath)) ) { 166 | if (options.circular || options.onlyCircular) 167 | dependency.isCircularDependency = isCircularDependency(dependency.importAbsolutePath, absPathInputFile, options) 168 | 169 | if (options.onlyCircular && dependency.isCircularDependency) { 170 | if (options.onlyNotFound) { 171 | hasNoDependency = false 172 | break 173 | } 174 | dependencies.push(dependency) 175 | } 176 | else if (!options.onlyCircular) { 177 | if (options.onlyNotFound) { 178 | hasNoDependency = false 179 | break 180 | } 181 | dependencies.push(dependency) 182 | } 183 | } 184 | else if ( !options.onlyCircular && ((dependency.importAbsolutePath.indexOf("node_modules") >= 0 || !fs.existsSync(dependency.importAbsolutePath)) && !options.parent.excludeNodeModules) ) { 185 | if (options.onlyNotFound) { 186 | hasNoDependency = false 187 | break 188 | } 189 | dependency.isNodeModule = true 190 | dependency.importAbsolutePath = dependency.importPath 191 | dependencies.push(dependency) 192 | } 193 | } 194 | } 195 | 196 | if (options.onlyNotFound && !hasNoDependency) { 197 | delete result[inputFile] 198 | continue 199 | } 200 | 201 | result[inputFile] = { 202 | absolutePath: absPathInputFile, 203 | files: dependencies.length, 204 | dependencies 205 | } 206 | 207 | } 208 | return result 209 | } 210 | 211 | function isCircularDependency(mod/*: string */, absolutePath/*: string */, options/*: FindDependenciesCommandOptions*/)/*: boolean */ { 212 | // clone 213 | let opts = Object.assign({}, options) 214 | opts.circular = false 215 | opts.onlyCircular = false 216 | const deps = findDependencies([mod], opts) 217 | 218 | for (let dependency of deps[mod].dependencies) { 219 | if (dependency.importAbsolutePath == absolutePath) { 220 | return true 221 | } 222 | } 223 | 224 | return false 225 | } 226 | 227 | module.exports = findDependencies -------------------------------------------------------------------------------- /lib/find-dependents.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const util = require("./util.js"), 4 | path = require("path"), 5 | fs = require("fs"), 6 | globby = require("globby"), 7 | findDependencies = require("./find-dependencies"), 8 | typescript = require("typescript"), 9 | flowParser = require('flow-parser') 10 | 11 | function findDependents(globs/*: Array*/, options/*: FindDependentsCommandOptions*/)/*: Object*/{ 12 | 13 | let inputFiles /*: Array*/= globby.sync(globs) 14 | let result = {} 15 | 16 | for (let inputFile of inputFiles) { 17 | let dependents = [] 18 | const dirname = (!options.root) ? path.dirname(inputFile) : options.root 19 | const baseName = path.basename(inputFile) 20 | const baseNameNoExt = path.basename(inputFile, path.extname(inputFile)) 21 | const absPathInputFile = path.resolve(inputFile) 22 | const isTS = baseName.endsWith(".ts") 23 | let hasNoDepentents = true 24 | let aliasName = "" 25 | if (options.parent.webpackConfig) { 26 | aliasName = util.webpackFindAlias(inputFile, options.parent.webpackConfig) 27 | } 28 | 29 | // initialize result 30 | result[inputFile] = { 31 | absolutePath: absPathInputFile, 32 | files: dependents.length, 33 | dependents 34 | } 35 | 36 | const entries = globby.sync([ 37 | path.join(dirname, "**", "*.js"), 38 | path.join(dirname, "**", "*.ts"), 39 | "!"+inputFile, 40 | "!"+path.join(dirname, "**", "*.spec.js"), 41 | "!"+path.join(dirname, "**", "*.d.ts"), 42 | "!"+path.join("node_modules", "**", "*"), 43 | ]) 44 | 45 | for (let entry of entries) { 46 | 47 | if (options.onlyNotFound && !hasNoDepentents) 48 | break 49 | 50 | let data /*: string */ = fs.readFileSync(entry, 'utf8') 51 | 52 | // Apply a first filter to exclude some files: 53 | // Don't consider js files where there is no import/require of inputFile 54 | if ( data.indexOf('require(') == -1 && data.indexOf('import ') == -1 && 55 | (data.indexOf(baseName+'\"') == -1 && data.indexOf(baseNameNoExt+'\"') == -1 && 56 | data.indexOf(baseName+'\'') == -1 && data.indexOf(baseNameNoExt+'\'') == -1 && 57 | data.indexOf(baseName+'\`') == -1 && data.indexOf(baseNameNoExt+'\`') == -1) && 58 | (aliasName && (data.indexOf('\"'+aliasName) == -1 && 59 | data.indexOf('\''+aliasName) == -1 && 60 | data.indexOf('\`'+aliasName) == -1)) ) { 61 | continue 62 | } 63 | 64 | let ast = {} 65 | let imports = [] 66 | let isEntryTS = false 67 | 68 | if (entry.trim().endsWith(".ts")) { 69 | isEntryTS = true 70 | try { 71 | ast = typescript.createSourceFile(inputFile, data) 72 | } catch(e) { 73 | console.log(e) 74 | continue 75 | } 76 | imports = util.typescriptTraverseAST('kind', [typescript.SyntaxKind.VariableDeclaration, typescript.SyntaxKind.ImportDeclaration], ast) 77 | } 78 | else { 79 | try { 80 | ast = ast = flowParser.parse(data) 81 | } catch(e) { 82 | console.log(e) 83 | continue 84 | } 85 | imports = util.flowTraverseAST('type', ['VariableDeclarator', 'ImportDeclaration'], ast) 86 | } 87 | 88 | for (let imp /*: Object*/ of imports) { 89 | let dependent = { 90 | filePath: entry, 91 | fileAbsolutePath: path.resolve(entry), 92 | importPath: '', 93 | importAbsolutePath: '', 94 | isCircularDependency: null, 95 | specifiers: [] 96 | } 97 | 98 | if (isEntryTS) { 99 | if ( util.isRequireStatement(imp, true) ) { 100 | dependent.importPath = imp.initializer.arguments[0].text 101 | if (options.parent.specifiers && imp.name) { 102 | if (imp.name.kind == typescript.SyntaxKind.Identifier) { 103 | dependent.specifiers.push({ 104 | name: imp.name.escapedText, 105 | alias: '', 106 | isDefault: true 107 | }) 108 | } 109 | else if (imp.name.kind == typescript.SyntaxKind.ObjectBindingPattern) { 110 | for (let element /*: Object*/ of imp.name.elements) { 111 | dependent.specifiers.push({ 112 | name: element.name.escapedText, 113 | alias: '', 114 | isDefault: false 115 | }) 116 | } 117 | } 118 | } 119 | } 120 | else if ( util.isImportStatement(imp, true) ) { 121 | dependent.importPath = imp.moduleSpecifier.text 122 | if (options.parent.specifiers && imp.importClause) { 123 | if (imp.importClause.name) { 124 | dependent.specifiers.push({ 125 | name: imp.importClause.name.escapedText, 126 | alias: '', 127 | isDefault: true 128 | }) 129 | } 130 | if (imp.importClause.namedBindings) { 131 | for (let element /*: Object*/ of imp.importClause.namedBindings.elements) { 132 | dependent.specifiers.push({ 133 | name: (element.propertyName) ? element.propertyName.escapedText : element.name.escapedText, 134 | alias: (element.propertyName) ? element.name.escapedText : '', 135 | isDefault: false 136 | }) 137 | } 138 | } 139 | } 140 | } 141 | } 142 | else { 143 | if ( util.isRequireStatement(imp, false) ) { 144 | dependent.importPath = imp.init.arguments[0].value 145 | if (imp.id) { 146 | if (imp.id.type == 'Identifier') { 147 | dependent.specifiers.push({ 148 | name: imp.id.name, 149 | alias: '', 150 | isDefault: true 151 | }) 152 | } 153 | else if (imp.id.type == 'ObjectPattern') { 154 | for (let property /*: Object*/ of imp.id.properties) { 155 | dependent.specifiers.push({ 156 | name: property.key.name, 157 | alias: '', 158 | isDefault: false 159 | }) 160 | } 161 | } 162 | } 163 | } 164 | else if ( util.isImportStatement(imp, false) ) { 165 | dependent.importPath = imp.source.value 166 | for (let specifier /*: Object*/ of imp.specifiers) { 167 | dependent.specifiers.push({ 168 | name: (specifier.imported) ? specifier.imported.name : specifier.local.name, 169 | alias: (specifier.imported && specifier.imported.name != specifier.local.name) ? specifier.local.name : '', 170 | isDefault: specifier.type == 'ImportDefaultSpecifier' 171 | }) 172 | } 173 | } 174 | } 175 | 176 | if (dependent.importPath) { 177 | let webpackAliasResolved = {} 178 | 179 | if (options.parent.webpackConfig) { 180 | webpackAliasResolved = util.webpackAliasResolver(dependent.importPath, options.parent.webpackConfig) 181 | dependent.importPath = webpackAliasResolved.module 182 | dependent.importAbsolutePath = webpackAliasResolved.moduleAbsPath 183 | } 184 | 185 | if (webpackAliasResolved.isWebpackError) 186 | continue 187 | 188 | dependent.importAbsolutePath = (!dependent.importAbsolutePath) ? path.resolve(path.join(path.dirname(entry), dependent.importPath)) : dependent.importAbsolutePath 189 | 190 | if (!path.extname(dependent.importAbsolutePath) || !fs.existsSync(dependent.importAbsolutePath)) { 191 | // if isTS and isEntryTS are true, then the dependent can't be a .js file 192 | if (isTS && isEntryTS) { 193 | if ( fs.existsSync( dependent.importAbsolutePath + '.ts' ) ) { 194 | dependent.importAbsolutePath += '.ts' 195 | } 196 | } 197 | else if (!isTS && isEntryTS && fs.existsSync( dependent.importAbsolutePath + '.ts' )) { 198 | // if entry is a typescript file, but inputFile is a javascript, then if the entry has: 199 | // 200 | // import file from './inputFile' 201 | // 202 | // without specifying the extension, then the './inputFile' is considered a typescript file (if it exists) 203 | continue 204 | } 205 | else if (!isTS && fs.existsSync(dependent.importAbsolutePath + '.js')) { 206 | dependent.importAbsolutePath += '.js' 207 | } 208 | if (!webpackAliasResolved.keepRelative && !path.extname(dependent.importPath) && fs.existsSync(dependent.importAbsolutePath) ) 209 | dependent.importPath += path.extname(dependent.importAbsolutePath) 210 | } 211 | } 212 | 213 | if (dependent.importAbsolutePath == absPathInputFile) { 214 | if (options.onlyNotFound) { 215 | hasNoDepentents = false 216 | break 217 | } 218 | 219 | if (options.circular || options.onlyCircular) { 220 | // $Ignore 221 | dependent.isCircularDependency = isCircularDependency(absPathInputFile, dependent.fileAbsolutePath, options) 222 | } 223 | 224 | if (options.onlyCircular && dependent.isCircularDependency) 225 | dependents.push(dependent) 226 | else if (!options.onlyCircular) 227 | dependents.push(dependent) 228 | 229 | break 230 | } 231 | } 232 | 233 | } 234 | 235 | if (options.onlyNotFound && !hasNoDepentents) { 236 | delete result[inputFile] 237 | continue 238 | } 239 | 240 | result[inputFile] = { 241 | absolutePath: absPathInputFile, 242 | files: dependents.length, 243 | dependents 244 | } 245 | 246 | } 247 | 248 | return result 249 | } 250 | 251 | function isCircularDependency(mod/*: string */, absolutePath/*: string */, options/*: FindDependentsCommandOptions*/)/*: boolean */ { 252 | // clone 253 | let opts = Object.assign({}, options) 254 | opts.circular = false 255 | opts.onlyCircular = false 256 | delete opts.root 257 | const deps = findDependencies([mod], opts) 258 | 259 | for (let dependency of deps[mod].dependencies) { 260 | if (dependency.importAbsolutePath == absolutePath) { 261 | return true 262 | } 263 | } 264 | 265 | return false 266 | } 267 | 268 | module.exports = findDependents -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | module.exports = { 4 | findDependencies: require('./find-dependencies.js'), 5 | findDependents: require('./find-dependents.js'), 6 | util: require('./util.js') 7 | } -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const typescript = require('typescript'), 4 | fs = require('fs'), 5 | path = require('path') 6 | 7 | function flowTraverseAST(key/*: string*/, values/*: Array*/, doc/* : Object*/, wild/*: boolean*/=false, return_parent/*: Object | boolean*/=false, results/*: Array*/=[])/*: Array*/{ 8 | 9 | if (doc) { 10 | if (Array.isArray(doc)) { 11 | for (let d of doc) { 12 | flowTraverseAST(key, values, d, wild, (return_parent) ? doc : false, results) 13 | } 14 | } 15 | 16 | if (!Array.isArray(doc) && typeof doc == "object"){ 17 | for (let k in doc) { 18 | let v = doc[k] 19 | if ( values && values.indexOf(v) >= 0 && ( key == k || ( wild && k.toLowerCase().indexOf(key.toLowerCase()) >= 0 ) ) ) { 20 | results.push((!return_parent) ? doc : return_parent) 21 | } 22 | else if (!values && key == k || ( wild && k.toLowerCase().indexOf(key.toLowerCase()) >= 0 ) ) { 23 | results.push((!return_parent) ? doc : return_parent) 24 | } 25 | else if (!Array.isArray(v)) { 26 | flowTraverseAST(key, values, v, wild, (return_parent) ? doc : false, results) 27 | } 28 | else if (Array.isArray(v)) { 29 | for (let d of v) { 30 | flowTraverseAST(key, values, d, wild, (return_parent) ? doc : false, results) 31 | } 32 | } 33 | } 34 | } 35 | } 36 | 37 | return results 38 | } 39 | 40 | function typescriptTraverseAST(key/*: string*/, values/*: Array*/, doc/* : Object*/, wild/*: boolean*/=false, return_parent/*: Object | boolean*/=false, results/*: Array*/=[])/*: Array*/{ 41 | 42 | if (doc) { 43 | for (let k in doc) { 44 | let v = doc[k] 45 | if ( values && values.indexOf(v) >= 0 && ( key == k || ( wild && k.toLowerCase().indexOf(key.toLowerCase()) >= 0 ) ) ) { 46 | results.push((!return_parent) ? doc : return_parent) 47 | } 48 | else if (!values && key == k || ( wild && k.toLowerCase().indexOf(key.toLowerCase()) >= 0 ) ) { 49 | results.push((!return_parent) ? doc : return_parent) 50 | } 51 | } 52 | 53 | typescript.forEachChild(doc, (node) => {typescriptTraverseAST(key, values, node, wild, (return_parent) ? doc : false, results)}) 54 | } 55 | 56 | return results 57 | } 58 | 59 | function webpackAliasResolver(mod/*: string */, webpackConfigFile/*: string*/)/*: {webpackConfig: {}, isWebpackError: boolean, keepRelative: boolean, module: string, moduleAbsPath: string}*/ { 60 | let result = { 61 | webpackConfig: {}, 62 | isWebpackError: false, 63 | keepRelative: false, 64 | module: mod, 65 | moduleAbsPath: '' 66 | } 67 | 68 | if (!fs.existsSync(webpackConfigFile)) { 69 | throw new Error(webpackConfigFile + ' webpack config file doesn\'t exists.') 70 | } 71 | 72 | // $Ignore 73 | result.webpackConfig = require(path.resolve(webpackConfigFile)) 74 | 75 | if (result.webpackConfig.resolve && result.webpackConfig.resolve.alias) { 76 | for (let alias /*: string*/ in result.webpackConfig.resolve.alias) { 77 | let aliasAbsPath = webpackAliasResolveAbsPath(alias, webpackConfigFile) 78 | let normalizedAliasName = (alias[alias.length - 1] == "$") ? alias.substring(0, alias.length - 1) : alias 79 | let isExactMatch = mod == alias.substring(0, alias.length - 1) 80 | 81 | if (isExactMatch || mod == alias || (mod+path.sep).indexOf(normalizedAliasName+path.sep) >= 0 ) { 82 | result.moduleAbsPath = path.normalize(mod.replace(normalizedAliasName, aliasAbsPath)) 83 | if (mod == alias && path.extname(aliasAbsPath)) { 84 | result.keepRelative = true 85 | } 86 | 87 | // check if alias resolver results in an error 88 | if (path.extname(path.parse(result.moduleAbsPath).dir)) { 89 | result.isWebpackError = true 90 | break 91 | } 92 | 93 | if (fs.existsSync(result.moduleAbsPath) && fs.lstatSync(result.moduleAbsPath).isDirectory()) { 94 | // points to main attribute of package.json, default is index.js 95 | let mainAttrPackageJson = 'index.js' 96 | let packageJsonModule = path.join(result.moduleAbsPath, 'package.json') 97 | packageJsonModule = (fs.existsSync(packageJsonModule)) ? JSON.parse(fs.readFileSync(packageJsonModule, 'utf8')) : null 98 | if (packageJsonModule && packageJsonModule.main) { 99 | mainAttrPackageJson = packageJsonModule.main 100 | } 101 | result.moduleAbsPath = path.join(result.moduleAbsPath, mainAttrPackageJson) 102 | result.module = path.join(mod, mainAttrPackageJson) 103 | } 104 | break 105 | } 106 | 107 | } 108 | } 109 | 110 | return result 111 | } 112 | 113 | function webpackFindAlias(modulePath/*: string*/, webpackConfigFile/*: string*/)/*: string*/ { 114 | 115 | if (!fs.existsSync(webpackConfigFile)) { 116 | throw new Error(webpackConfigFile + ' webpack config file doesn\'t exists.') 117 | } 118 | 119 | let moduleAbsPath = path.resolve(modulePath) 120 | 121 | // $Ignore 122 | let result = require(path.resolve(webpackConfigFile)) 123 | if (result.resolve && result.resolve.alias) { 124 | for (let alias /*: string*/ in result.resolve.alias) { 125 | let aliasAbsPath = webpackAliasResolveAbsPath(alias, webpackConfigFile) 126 | 127 | if (fs.existsSync(aliasAbsPath) && fs.lstatSync(aliasAbsPath).isDirectory()) { 128 | // points to main attribute of package.json, default is index.js 129 | let mainAttrPackageJson = 'index.js' 130 | let packageJsonModule = path.join(aliasAbsPath, 'package.json') 131 | packageJsonModule = (fs.existsSync(packageJsonModule)) ? JSON.parse(fs.readFileSync(packageJsonModule, 'utf8')) : null 132 | if (packageJsonModule && packageJsonModule.main) { 133 | mainAttrPackageJson = packageJsonModule.main 134 | } 135 | aliasAbsPath = path.join(aliasAbsPath, mainAttrPackageJson) 136 | } 137 | 138 | if (moduleAbsPath == aliasAbsPath) { 139 | let normalizedAliasName = (alias[alias.length - 1] == "$") ? alias.substring(0, alias.length - 1) : alias 140 | return normalizedAliasName 141 | } 142 | } 143 | } 144 | 145 | return "" 146 | } 147 | 148 | function webpackAliasResolveAbsPath(alias/*: string*/, webpackConfigFile/*: string*/)/*: string*/ { 149 | let aliasAbsPath = "" 150 | // $Ignore 151 | let webpackConfig = require(path.resolve(webpackConfigFile)) 152 | if (path.isAbsolute(webpackConfig.resolve.alias[alias])) { 153 | aliasAbsPath = webpackConfig.resolve.alias[alias] 154 | } 155 | else { 156 | if (webpackConfig.resolve.modules) { 157 | for (let mod /*: string*/ of webpackConfig.resolve.modules) { 158 | let modPath = (path.isAbsolute(mod)) ? mod : path.resolve(mod) 159 | if (fs.existsSync(modPath)) { 160 | aliasAbsPath = path.join( modPath, webpackConfig.resolve.alias[alias] ) 161 | break 162 | } 163 | } 164 | } 165 | else { 166 | aliasAbsPath = path.join(path.dirname(path.resolve(webpackConfigFile)), webpackConfig.resolve.alias[alias]) 167 | } 168 | } 169 | return aliasAbsPath 170 | } 171 | 172 | function isRequireStatement(imp/*: Object */, isTS/*: boolean */ = false) /* : boolean */ { 173 | return (isTS) 174 | ? (imp.kind == typescript.SyntaxKind.VariableDeclaration && imp.initializer && imp.initializer.expression && imp.initializer.expression.escapedText == "require") 175 | : (imp.type == 'VariableDeclarator' && imp.init && imp.init.type == "CallExpression" && imp.init.callee.name == "require") 176 | } 177 | 178 | function isImportStatement(imp/*: Object */, isTS/*: boolean */ = false) /* : boolean */ { 179 | return (isTS) 180 | ? (imp.kind == typescript.SyntaxKind.ImportDeclaration) 181 | : (imp.type == 'ImportDeclaration') 182 | } 183 | 184 | module.exports = { 185 | flowTraverseAST, 186 | typescriptTraverseAST, 187 | webpackAliasResolver, 188 | webpackFindAlias, 189 | isRequireStatement, 190 | isImportStatement 191 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deps-report", 3 | "version": "0.5.0", 4 | "description": "Generate reports about dependencies and dependents of your JavaScript/TypeScript files through an AST. It supports import and require statements.", 5 | "keywords": [ 6 | "dependencies", 7 | "dependents", 8 | "packages", 9 | "report", 10 | "reporter", 11 | "usage", 12 | "tracking", 13 | "module", 14 | "dependency", 15 | "dependent", 16 | "exports", 17 | "require", 18 | "flow", 19 | "typescript", 20 | "ast", 21 | "abstract-syntax-tree" 22 | ], 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/pichillilorenzo/deps-report" 26 | }, 27 | "license": "MIT", 28 | "files": [ 29 | "lib" 30 | ], 31 | "author": { 32 | "name": "Lorenzo Pichilli", 33 | "email": "pichillilorenzo@gmail.com", 34 | "url": "https://github.com/pichillilorenzo" 35 | }, 36 | "dependencies": { 37 | "chalk": "^2.4.1", 38 | "commander": "2.16.0", 39 | "flow-parser": "0.76.0", 40 | "globby": "8.0.1", 41 | "typescript": "2.9.2" 42 | }, 43 | "devDependencies": { 44 | "ava": "1.0.0-beta.6", 45 | "coveralls": "^3.0.1", 46 | "nyc": "^12.0.2" 47 | }, 48 | "engines": { 49 | "node": ">=6.0.0" 50 | }, 51 | "scripts": { 52 | "start": "node ./lib/cli.js", 53 | "start-json": "node ./lib/cli.js --json --pretty", 54 | "start-json-abs": "node ./lib/cli.js --json --pretty --abs-path", 55 | "start-json-exclude": "node ./lib/cli.js --json --pretty --exclude-node-modules", 56 | "start-json-root": "node ./lib/cli.js --json --pretty --root ./tests/project-test", 57 | "start-help": "node ./lib/cli.js --help", 58 | "test": "nyc ava", 59 | "coverage": "nyc report --reporter=text-lcov | coveralls" 60 | }, 61 | "bin": { 62 | "deps-report": "lib/cli.js" 63 | }, 64 | "main": "lib/index.js", 65 | "ava": { 66 | "files": [ 67 | "./tests/**/*.js", 68 | "!tests/project-*/**/*.js" 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/project-react-js-test/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /.je-project-settings/.* 3 | 4 | [include] 5 | 6 | [libs] 7 | 8 | [lints] 9 | 10 | [options] 11 | 12 | [strict] 13 | -------------------------------------------------------------------------------- /tests/project-react-js-test/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /tests/project-react-js-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^16.4.1", 7 | "react-dom": "^16.4.1", 8 | "react-scripts": "1.1.4" 9 | }, 10 | "scripts": { 11 | "start": "react-scripts start", 12 | "build": "react-scripts build", 13 | "test": "react-scripts test --env=jsdom", 14 | "eject": "react-scripts eject" 15 | } 16 | } -------------------------------------------------------------------------------- /tests/project-react-js-test/project-react-js-test.sublime-workspace: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /tests/project-react-js-test/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pichillilorenzo/deps-report/c02513d1a9d8f4d412e002d8ff955801e223b1ec/tests/project-react-js-test/public/favicon.ico -------------------------------------------------------------------------------- /tests/project-react-js-test/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /tests/project-react-js-test/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /tests/project-react-js-test/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /tests/project-react-js-test/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | logo 11 |

Welcome to React

12 |
13 |

14 | To get started, edit src/App.js and save to reload. 15 |

16 |
17 | ); 18 | } 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /tests/project-react-js-test/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /tests/project-react-js-test/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /tests/project-react-js-test/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import registerServiceWorker from './registerServiceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | registerServiceWorker(); 9 | -------------------------------------------------------------------------------- /tests/project-react-js-test/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /tests/project-react-js-test/src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | const isLocalhost = Boolean( 12 | window.location.hostname === 'localhost' || 13 | // [::1] is the IPv6 localhost address. 14 | window.location.hostname === '[::1]' || 15 | // 127.0.0.1/8 is considered localhost for IPv4. 16 | window.location.hostname.match( 17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 18 | ) 19 | ); 20 | 21 | export default function register() { 22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 23 | // The URL constructor is available in all browsers that support SW. 24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location); 25 | if (publicUrl.origin !== window.location.origin) { 26 | // Our service worker won't work if PUBLIC_URL is on a different origin 27 | // from what our page is served on. This might happen if a CDN is used to 28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 29 | return; 30 | } 31 | 32 | window.addEventListener('load', () => { 33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 34 | 35 | if (isLocalhost) { 36 | // This is running on localhost. Lets check if a service worker still exists or not. 37 | checkValidServiceWorker(swUrl); 38 | 39 | // Add some additional logging to localhost, pointing developers to the 40 | // service worker/PWA documentation. 41 | navigator.serviceWorker.ready.then(() => { 42 | console.log( 43 | 'This web app is being served cache-first by a service ' + 44 | 'worker. To learn more, visit https://goo.gl/SC7cgQ' 45 | ); 46 | }); 47 | } else { 48 | // Is not local host. Just register service worker 49 | registerValidSW(swUrl); 50 | } 51 | }); 52 | } 53 | } 54 | 55 | function registerValidSW(swUrl) { 56 | navigator.serviceWorker 57 | .register(swUrl) 58 | .then(registration => { 59 | registration.onupdatefound = () => { 60 | const installingWorker = registration.installing; 61 | installingWorker.onstatechange = () => { 62 | if (installingWorker.state === 'installed') { 63 | if (navigator.serviceWorker.controller) { 64 | // At this point, the old content will have been purged and 65 | // the fresh content will have been added to the cache. 66 | // It's the perfect time to display a "New content is 67 | // available; please refresh." message in your web app. 68 | console.log('New content is available; please refresh.'); 69 | } else { 70 | // At this point, everything has been precached. 71 | // It's the perfect time to display a 72 | // "Content is cached for offline use." message. 73 | console.log('Content is cached for offline use.'); 74 | } 75 | } 76 | }; 77 | }; 78 | }) 79 | .catch(error => { 80 | console.error('Error during service worker registration:', error); 81 | }); 82 | } 83 | 84 | function checkValidServiceWorker(swUrl) { 85 | // Check if the service worker can be found. If it can't reload the page. 86 | fetch(swUrl) 87 | .then(response => { 88 | // Ensure service worker exists, and that we really are getting a JS file. 89 | if ( 90 | response.status === 404 || 91 | response.headers.get('content-type').indexOf('javascript') === -1 92 | ) { 93 | // No service worker found. Probably a different app. Reload the page. 94 | navigator.serviceWorker.ready.then(registration => { 95 | registration.unregister().then(() => { 96 | window.location.reload(); 97 | }); 98 | }); 99 | } else { 100 | // Service worker found. Proceed as normal. 101 | registerValidSW(swUrl); 102 | } 103 | }) 104 | .catch(() => { 105 | console.log( 106 | 'No internet connection found. App is running in offline mode.' 107 | ); 108 | }); 109 | } 110 | 111 | export function unregister() { 112 | if ('serviceWorker' in navigator) { 113 | navigator.serviceWorker.ready.then(registration => { 114 | registration.unregister(); 115 | }); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /tests/project-test/a.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import 'path' 4 | 5 | import fs, { readFileSync, readFile as readFileAsync } from 'fs' 6 | 7 | import d from './c/d.js' 8 | 9 | // $Ignore 10 | import Utilities from 'Utilities' 11 | // $Ignore 12 | import UtilitiesRelativePath from 'UtilitiesRelativePath' 13 | // $Ignore 14 | import utilityA from 'Utilities/utilityA' 15 | // $Ignore 16 | import templates from 'Templates' 17 | // $Ignore 18 | import templatesMain from 'TemplatesMain' 19 | // $Ignore, this is a webpack resolve error 20 | import TemplatesMainJS from 'TemplatesMain/main.js' 21 | // $Ignore 22 | import MyPath from 'MyPath' 23 | 24 | const fs1 = require('fs'), 25 | b_folder_e = require('./e/b'), 26 | {d1, d2} = require('./c/d.js') 27 | 28 | module.exports = {} -------------------------------------------------------------------------------- /tests/project-test/a.ts: -------------------------------------------------------------------------------- 1 | import 'path' 2 | 3 | import fs, { readFileSync, readFile as readFileAsync } from 'fs' 4 | 5 | import d from './c/d.js' 6 | 7 | import b from './b' 8 | 9 | import Utilities from 'Utilities' 10 | import UtilitiesRelativePath from 'UtilitiesRelativePath' 11 | import utilityA from 'Utilities/utilityA' 12 | import templates from 'Templates' 13 | import templatesMain from 'TemplatesMain' 14 | // this is a webpack resolve error 15 | import TemplatesMainJS from 'TemplatesMain/main.js' 16 | import MyPath from 'MyPath' 17 | 18 | const fs1 = require('fs'), 19 | b_folder_e = require('./e/b'), 20 | {d1, d2} = require('./c/d.js') 21 | 22 | export default function () { 23 | return null 24 | } -------------------------------------------------------------------------------- /tests/project-test/a1.ts: -------------------------------------------------------------------------------- 1 | import fs, { readFileSync } from 'fs' 2 | 3 | const fs1 = require('fs'), 4 | // $FlowFixMe because of .ts extension 5 | b_TS = require('./b'), 6 | b_folder_e = require('./e/b') 7 | 8 | module.exports = {} -------------------------------------------------------------------------------- /tests/project-test/b.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | 3 | import d from './c/d' 4 | 5 | import a from './a' 6 | 7 | const fs = require('fs'), 8 | path1 = require('path') 9 | 10 | export default function () { 11 | return null 12 | } -------------------------------------------------------------------------------- /tests/project-test/c.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pichillilorenzo/deps-report/c02513d1a9d8f4d412e002d8ff955801e223b1ec/tests/project-test/c.js -------------------------------------------------------------------------------- /tests/project-test/c.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pichillilorenzo/deps-report/c02513d1a9d8f4d412e002d8ff955801e223b1ec/tests/project-test/c.ts -------------------------------------------------------------------------------- /tests/project-test/c/d.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const fs = require('fs'), 4 | // $Ignore, ../b.js doesn't exist, only ../b.ts so it is wrong in this case 5 | b = require('../b'), 6 | a = require('../a') 7 | 8 | module.exports = { 9 | d1: 1, 10 | d2: 2 11 | } -------------------------------------------------------------------------------- /tests/project-test/e/b.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import d from '../c/d.js' 4 | 5 | module.exports = {} -------------------------------------------------------------------------------- /tests/project-test/src/templates/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | module.exports = {} -------------------------------------------------------------------------------- /tests/project-test/src/templates/main.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | module.exports = {} -------------------------------------------------------------------------------- /tests/project-test/src/templates/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "main.js" 3 | } -------------------------------------------------------------------------------- /tests/project-test/src/utilities/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // $Ignore 4 | import templates from 'Templates' 5 | 6 | module.exports = {} -------------------------------------------------------------------------------- /tests/project-test/src/utilities/relative.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | module.exports = {} -------------------------------------------------------------------------------- /tests/project-test/src/utilities/utilityA.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | module.exports = {} -------------------------------------------------------------------------------- /tests/project-test/webpack.config.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | const path = require("path") 3 | 4 | module.exports = { 5 | resolve: { 6 | alias: { 7 | Utilities: path.resolve(__dirname, path.join('src','utilities')), 8 | UtilitiesRelativePath: path.join('src','utilities', 'relative.js'), 9 | Templates: path.resolve(__dirname, path.join('src','templates')), 10 | TemplatesMain: path.resolve(__dirname, path.join('src','templates', 'main.js')), 11 | TemplatesMain$: path.resolve(__dirname, path.join('src','templates', 'main.js')), 12 | MyPath: 'path' 13 | } 14 | } 15 | }; -------------------------------------------------------------------------------- /tests/project-test/webpack2.config.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | const path = require("path") 3 | 4 | module.exports = { 5 | resolve: { 6 | alias: { 7 | Utilities: path.join('src','utilities'), 8 | UtilitiesRelativePath: path.join('src','utilities', 'relative.js'), 9 | Templates: path.join('src','templates'), 10 | TemplatesMain: path.join('src','templates', 'main.js'), 11 | TemplatesMain$: path.join('src','templates', 'main.js'), 12 | MyPath: 'path' 13 | }, 14 | modules: [ 15 | path.resolve(__dirname), 16 | 'node_modules' 17 | ] 18 | } 19 | }; -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import test from 'ava' 4 | import findDependencies from '../lib/find-dependencies' 5 | import findDependents from '../lib/find-dependents' 6 | 7 | const path = require("path"), 8 | depsReportPath = path.resolve(path.join(__dirname, '..')) 9 | 10 | let testResults = JSON.stringify(require("./testResults.json")) 11 | // prepare testResult 12 | testResults = JSON.parse(testResults.replace(/\/Users\/lorenzo\/Desktop\/deps\-report/g, depsReportPath)) 13 | 14 | /* 15 | project-test folder 16 | */ 17 | 18 | test('Test find-dependencies in project-test folder', t => { 19 | 20 | // ./lib/cli.js -s -w tests/project-test/webpack.config.js find-dependencies "tests/project-test/a.js" 21 | // ./lib/cli.js -js -w tests/project-test/webpack.config.js find-dependencies "tests/project-test/a.js" 22 | let optionsFindDependencies = {circular: false, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 23 | t.deepEqual(findDependencies(["tests/project-test/a.js"], optionsFindDependencies), testResults[0]) 24 | 25 | // ./lib/cli.js -se -w tests/project-test/webpack.config.js find-dependencies "tests/project-test/a.js" 26 | // ./lib/cli.js -jse -w tests/project-test/webpack.config.js find-dependencies "tests/project-test/a.js" 27 | optionsFindDependencies = {circular: false, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: true, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 28 | t.deepEqual(findDependencies(["tests/project-test/a.js"], optionsFindDependencies), testResults[1]) 29 | 30 | // ./lib/cli.js -s -w tests/project-test/webpack.config.js find-dependencies -c "tests/project-test/*.ts" 31 | // ./lib/cli.js -js -w tests/project-test/webpack.config.js find-dependencies -c "tests/project-test/*.ts" 32 | optionsFindDependencies = {circular: true, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 33 | t.deepEqual(findDependencies(["tests/project-test/*.ts"], optionsFindDependencies), testResults[2]) 34 | 35 | // ./lib/cli.js -s -w tests/project-test/webpack.config.js find-dependencies --only-circular "tests/project-test/*.ts" 36 | // ./lib/cli.js -js -w tests/project-test/webpack.config.js find-dependencies --only-circular "tests/project-test/*.ts" 37 | optionsFindDependencies = {circular: false, onlyCircular: true, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 38 | t.deepEqual(findDependencies(["tests/project-test/*.ts"], optionsFindDependencies), testResults[3]) 39 | 40 | // ./lib/cli.js -w tests/project-test/webpack.config.js find-dependencies --only-not-found "tests/project-test/*.ts" 41 | // ./lib/cli.js -j -w tests/project-test/webpack.config.js find-dependencies --only-not-found "tests/project-test/*.ts" 42 | optionsFindDependencies = {circular: false, onlyCircular: false, onlyNotFound: true, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: false, color: false} } 43 | t.deepEqual(findDependencies(["tests/project-test/*.ts"], optionsFindDependencies), testResults[4]) 44 | 45 | // ./lib/cli.js -se -w tests/project-test/webpack.config.js find-dependencies "tests/project-test/b.ts" 46 | // ./lib/cli.js -jse -w tests/project-test/webpack.config.js find-dependencies "tests/project-test/b.ts" 47 | optionsFindDependencies = {circular: false, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: true, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 48 | t.deepEqual(findDependencies(["tests/project-test/b.ts"], optionsFindDependencies), testResults[5]) 49 | 50 | }) 51 | 52 | test('Test find-dependents in project-test folder', t => { 53 | 54 | // ./lib/cli.js -s -w tests/project-test/webpack.config.js find-dependents "tests/project-test/b.ts" 55 | // ./lib/cli.js -js -w tests/project-test/webpack.config.js find-dependents "tests/project-test/b.ts" 56 | let optionsFindDependents = {root: '', circular: false, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 57 | t.deepEqual(findDependents(["tests/project-test/b.ts"], optionsFindDependents), testResults[6]) 58 | 59 | // ./lib/cli.js -s -w tests/project-test/webpack.config.js find-dependents "tests/project-test/a.js" 60 | // ./lib/cli.js -js -w tests/project-test/webpack.config.js find-dependents "tests/project-test/a.js" 61 | t.deepEqual(findDependents(["tests/project-test/a.js"], optionsFindDependents), testResults[7]) 62 | 63 | // ./lib/cli.js -s -w tests/project-test/webpack.config.js find-dependents --only-circular -r "tests/project-test" "tests/project-test/c/d.js" 64 | // ./lib/cli.js -js -w tests/project-test/webpack.config.js find-dependents --only-circular -r "tests/project-test" "tests/project-test/c/d.js" 65 | optionsFindDependents = {root: 'tests/project-test', circular: false, onlyCircular: true, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 66 | t.deepEqual(findDependents(["tests/project-test/c/d.js"], optionsFindDependents), testResults[8]) 67 | 68 | // ./lib/cli.js -s -w tests/project-test/webpack.config.js find-dependents -c -r "tests/project-test" "tests/project-test/c/d.js" 69 | // ./lib/cli.js -js -w tests/project-test/webpack.config.js find-dependents -c -r "tests/project-test" "tests/project-test/c/d.js" 70 | optionsFindDependents = {root: 'tests/project-test', circular: true, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 71 | t.deepEqual(findDependents(["tests/project-test/c/d.js"], optionsFindDependents), testResults[9]) 72 | 73 | // ./lib/cli.js -s -w tests/project-test/webpack.config.js find-dependents -r "tests/project-test" "tests/project-test/src/templates/*.js" "tests/project-test/src/utilities/*.js" 74 | // ./lib/cli.js -js -w tests/project-test/webpack.config.js find-dependents -r "tests/project-test" "tests/project-test/src/templates/*.js" "tests/project-test/src/utilities/*.js" 75 | optionsFindDependents = {root: 'tests/project-test', circular: false, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: true, color: false} } 76 | t.deepEqual(findDependents(["tests/project-test/src/templates/*.js", "tests/project-test/src/utilities/*.js"], optionsFindDependents), testResults[10]) 77 | 78 | // ./lib/cli.js -s -w tests/project-test/webpack2.config.js find-dependents -r "tests/project-test" "tests/project-test/src/templates/*.js" "tests/project-test/src/utilities/*.js" 79 | // ./lib/cli.js -js -w tests/project-test/webpack2.config.js find-dependents -r "tests/project-test" "tests/project-test/src/templates/*.js" "tests/project-test/src/utilities/*.js" 80 | optionsFindDependents = {root: 'tests/project-test', circular: false, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack2.config.js', specifiers: true, color: false} } 81 | t.deepEqual(findDependents(["tests/project-test/src/templates/*.js", "tests/project-test/src/utilities/*.js"], optionsFindDependents), testResults[10]) 82 | 83 | // ./lib/cli.js -w tests/project-test/webpack.config.js find-dependents --only-not-found -r "tests/project-test" "tests/project-test/src/templates/*.js" "tests/project-test/src/utilities/*.js" 84 | // ./lib/cli.js -j -w tests/project-test/webpack.config.js find-dependents --only-not-found -r "tests/project-test" "tests/project-test/src/templates/*.js" "tests/project-test/src/utilities/*.js" 85 | optionsFindDependents = {root: 'tests/project-test', circular: false, onlyCircular: false, onlyNotFound: true, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: 'tests/project-test/webpack.config.js', specifiers: false, color: false} } 86 | t.deepEqual(findDependents(["tests/project-test/src/templates/*.js", "tests/project-test/src/utilities/*.js"], optionsFindDependents), testResults[11]) 87 | 88 | }) 89 | 90 | // /* 91 | // project-react-js-test folder 92 | // */ 93 | 94 | test('Test find-dependencies in project-react-js-test folder', t => { 95 | 96 | // ./lib/cli.js -s find-dependencies -c "tests/project-react-js-test/src/*.js" '!tests/project-react-js-test/src/*.test.js' 97 | // ./lib/cli.js -js find-dependencies -c "tests/project-react-js-test/src/*.js" '!tests/project-react-js-test/src/*.test.js' 98 | let optionsFindDependencies = {circular: true, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: '', specifiers: true, color: false} } 99 | t.deepEqual(findDependencies(["tests/project-react-js-test/src/*.js", "!tests/project-react-js-test/src/*.test.js"], optionsFindDependencies), testResults[12]) 100 | 101 | // ./lib/cli.js -se find-dependencies "tests/project-react-js-test/src/*.js" 102 | // ./lib/cli.js -jse find-dependencies "tests/project-react-js-test/src/*.js" 103 | optionsFindDependencies = {circular: false, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: true, json: false, pretty: false, absPath: false, webpackConfig: '', specifiers: true, color: false} } 104 | t.deepEqual(findDependencies(["tests/project-react-js-test/src/*.js"], optionsFindDependencies), testResults[13]) 105 | 106 | }) 107 | 108 | test('Test find-dependents in project-react-js-test folder', t => { 109 | 110 | // ./lib/cli.js -s find-dependents "tests/project-react-js-test/src/*.js" 111 | // ./lib/cli.js -js find-dependents "tests/project-react-js-test/src/*.js" 112 | let optionsFindDependents = {root: '', circular: false, onlyCircular: false, onlyNotFound: false, hideNotFound: false, parent: {excludeNodeModules: false, json: false, pretty: false, absPath: false, webpackConfig: '', specifiers: true, color: false} } 113 | t.deepEqual(findDependents(["tests/project-react-js-test/src/*.js"], optionsFindDependents), testResults[14]) 114 | 115 | }) -------------------------------------------------------------------------------- /tests/testResults.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"tests/project-test/a.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","files":12,"dependencies":[{"importPath":"path","importAbsolutePath":"path","isCircularDependency":null,"isNodeModule":true,"specifiers":[]},{"importPath":"fs","importAbsolutePath":"fs","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"fs","alias":"","isDefault":true},{"name":"readFileSync","alias":"","isDefault":false},{"name":"readFile","alias":"readFileAsync","isDefault":false}]},{"importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"d","alias":"","isDefault":true}]},{"importPath":"Utilities/index.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/index.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"Utilities","alias":"","isDefault":true}]},{"importPath":"UtilitiesRelativePath","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/relative.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"UtilitiesRelativePath","alias":"","isDefault":true}]},{"importPath":"Utilities/utilityA.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/utilityA.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"utilityA","alias":"","isDefault":true}]},{"importPath":"Templates/main.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"templates","alias":"","isDefault":true}]},{"importPath":"TemplatesMain","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"templatesMain","alias":"","isDefault":true}]},{"importPath":"MyPath","importAbsolutePath":"MyPath","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"MyPath","alias":"","isDefault":true}]},{"importPath":"fs","importAbsolutePath":"fs","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"fs1","alias":"","isDefault":true}]},{"importPath":"./e/b.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/e/b.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"b_folder_e","alias":"","isDefault":true}]},{"importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"d1","alias":"","isDefault":false},{"name":"d2","alias":"","isDefault":false}]}]}}, 3 | {"tests/project-test/a.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","files":8,"dependencies":[{"importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"d","alias":"","isDefault":true}]},{"importPath":"Utilities/index.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/index.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"Utilities","alias":"","isDefault":true}]},{"importPath":"UtilitiesRelativePath","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/relative.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"UtilitiesRelativePath","alias":"","isDefault":true}]},{"importPath":"Utilities/utilityA.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/utilityA.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"utilityA","alias":"","isDefault":true}]},{"importPath":"Templates/main.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"templates","alias":"","isDefault":true}]},{"importPath":"TemplatesMain","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"templatesMain","alias":"","isDefault":true}]},{"importPath":"./e/b.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/e/b.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"b_folder_e","alias":"","isDefault":true}]},{"importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"d1","alias":"","isDefault":false},{"name":"d2","alias":"","isDefault":false}]}]}}, 4 | {"tests/project-test/a.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","files":13,"dependencies":[{"importPath":"path","importAbsolutePath":"path","isCircularDependency":null,"isNodeModule":true,"specifiers":[]},{"importPath":"fs","importAbsolutePath":"fs","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"fs","alias":"","isDefault":true},{"name":"readFileSync","alias":"","isDefault":false},{"name":"readFile","alias":"readFileAsync","isDefault":false}]},{"importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"d","alias":"","isDefault":true}]},{"importPath":"./b.ts","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","isCircularDependency":true,"isNodeModule":false,"specifiers":[{"name":"b","alias":"","isDefault":true}]},{"importPath":"Utilities/index.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/index.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"Utilities","alias":"","isDefault":true}]},{"importPath":"UtilitiesRelativePath","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/relative.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"UtilitiesRelativePath","alias":"","isDefault":true}]},{"importPath":"Utilities/utilityA.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/utilityA.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"utilityA","alias":"","isDefault":true}]},{"importPath":"Templates/main.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"templates","alias":"","isDefault":true}]},{"importPath":"TemplatesMain","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"templatesMain","alias":"","isDefault":true}]},{"importPath":"MyPath","importAbsolutePath":"MyPath","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"MyPath","alias":"","isDefault":true}]},{"importPath":"fs","importAbsolutePath":"fs","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"fs1","alias":"","isDefault":true}]},{"importPath":"./e/b.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/e/b.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"b_folder_e","alias":"","isDefault":true}]},{"importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"d1","alias":"","isDefault":false},{"name":"d2","alias":"","isDefault":false}]}]},"tests/project-test/a1.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a1.ts","files":4,"dependencies":[{"importPath":"fs","importAbsolutePath":"fs","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"fs","alias":"","isDefault":true},{"name":"readFileSync","alias":"","isDefault":false}]},{"importPath":"fs","importAbsolutePath":"fs","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"fs1","alias":"","isDefault":true}]},{"importPath":"./b.ts","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"b_TS","alias":"","isDefault":true}]},{"importPath":"./e/b.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/e/b.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"b_folder_e","alias":"","isDefault":true}]}]},"tests/project-test/b.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","files":5,"dependencies":[{"importPath":"path","importAbsolutePath":"path","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"path","alias":"","isDefault":true}]},{"importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"d","alias":"","isDefault":true}]},{"importPath":"./a.ts","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","isCircularDependency":true,"isNodeModule":false,"specifiers":[{"name":"a","alias":"","isDefault":true}]},{"importPath":"fs","importAbsolutePath":"fs","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"fs","alias":"","isDefault":true}]},{"importPath":"path","importAbsolutePath":"path","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"path1","alias":"","isDefault":true}]}]},"tests/project-test/c.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c.ts","files":0,"dependencies":[]}}, 5 | {"tests/project-test/a.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","files":1,"dependencies":[{"importPath":"./b.ts","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","isCircularDependency":true,"isNodeModule":false,"specifiers":[{"name":"b","alias":"","isDefault":true}]}]},"tests/project-test/a1.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a1.ts","files":0,"dependencies":[]},"tests/project-test/b.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","files":1,"dependencies":[{"importPath":"./a.ts","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","isCircularDependency":true,"isNodeModule":false,"specifiers":[{"name":"a","alias":"","isDefault":true}]}]},"tests/project-test/c.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c.ts","files":0,"dependencies":[]}}, 6 | {"tests/project-test/c.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c.ts","files":0,"dependencies":[]}}, 7 | {"tests/project-test/b.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","files":2,"dependencies":[{"importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"d","alias":"","isDefault":true}]},{"importPath":"./a.ts","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"a","alias":"","isDefault":true}]}]}}, 8 | {"tests/project-test/b.ts":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","files":2,"dependents":[{"filePath":"tests/project-test/a.ts","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","importPath":"./b.ts","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","isCircularDependency":null,"specifiers":[{"name":"b","alias":"","isDefault":true}]},{"filePath":"tests/project-test/a1.ts","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a1.ts","importPath":"./b.ts","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","isCircularDependency":null,"specifiers":[{"name":"b_TS","alias":"","isDefault":true}]}]}}, 9 | {"tests/project-test/a.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","files":1,"dependents":[{"filePath":"tests/project-test/c/d.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","importPath":"../a.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","isCircularDependency":null,"specifiers":[{"name":"a","alias":"","isDefault":true}]}]}}, 10 | {"tests/project-test/c/d.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","files":1,"dependents":[{"filePath":"tests/project-test/a.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":true,"specifiers":[{"name":"d","alias":"","isDefault":true}]}]}}, 11 | {"tests/project-test/c/d.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","files":4,"dependents":[{"filePath":"tests/project-test/a.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":true,"specifiers":[{"name":"d","alias":"","isDefault":true}]},{"filePath":"tests/project-test/e/b.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/e/b.js","importPath":"../c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":false,"specifiers":[{"name":"d","alias":"","isDefault":true}]},{"filePath":"tests/project-test/a.ts","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":false,"specifiers":[{"name":"d","alias":"","isDefault":true}]},{"filePath":"tests/project-test/b.ts","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/b.ts","importPath":"./c/d.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/c/d.js","isCircularDependency":false,"specifiers":[{"name":"d","alias":"","isDefault":true}]}]}}, 12 | {"tests/project-test/src/templates/index.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/index.js","files":0,"dependents":[]},"tests/project-test/src/templates/main.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","files":3,"dependents":[{"filePath":"tests/project-test/a.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","importPath":"Templates/main.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":null,"specifiers":[{"name":"templates","alias":"","isDefault":true}]},{"filePath":"tests/project-test/src/utilities/index.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/index.js","importPath":"Templates/main.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":null,"specifiers":[{"name":"templates","alias":"","isDefault":true}]},{"filePath":"tests/project-test/a.ts","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","importPath":"Templates/main.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/main.js","isCircularDependency":null,"specifiers":[{"name":"templates","alias":"","isDefault":true}]}]},"tests/project-test/src/utilities/index.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/index.js","files":2,"dependents":[{"filePath":"tests/project-test/a.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","importPath":"Utilities/index.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/index.js","isCircularDependency":null,"specifiers":[{"name":"Utilities","alias":"","isDefault":true}]},{"filePath":"tests/project-test/a.ts","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","importPath":"Utilities/index.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/index.js","isCircularDependency":null,"specifiers":[{"name":"Utilities","alias":"","isDefault":true}]}]},"tests/project-test/src/utilities/relative.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/relative.js","files":2,"dependents":[{"filePath":"tests/project-test/a.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","importPath":"UtilitiesRelativePath","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/relative.js","isCircularDependency":null,"specifiers":[{"name":"UtilitiesRelativePath","alias":"","isDefault":true}]},{"filePath":"tests/project-test/a.ts","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","importPath":"UtilitiesRelativePath","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/relative.js","isCircularDependency":null,"specifiers":[{"name":"UtilitiesRelativePath","alias":"","isDefault":true}]}]},"tests/project-test/src/utilities/utilityA.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/utilityA.js","files":2,"dependents":[{"filePath":"tests/project-test/a.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.js","importPath":"Utilities/utilityA.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/utilityA.js","isCircularDependency":null,"specifiers":[{"name":"utilityA","alias":"","isDefault":true}]},{"filePath":"tests/project-test/a.ts","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/a.ts","importPath":"Utilities/utilityA.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/utilities/utilityA.js","isCircularDependency":null,"specifiers":[{"name":"utilityA","alias":"","isDefault":true}]}]}}, 13 | {"tests/project-test/src/templates/index.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-test/src/templates/index.js","files":0,"dependents":[]}}, 14 | {"tests/project-react-js-test/src/App.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js","files":3,"dependencies":[{"importPath":"react","importAbsolutePath":"react","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"React","alias":"","isDefault":true},{"name":"Component","alias":"","isDefault":false}]},{"importPath":"./logo.svg","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/logo.svg","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"logo","alias":"","isDefault":true}]},{"importPath":"./App.css","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.css","isCircularDependency":false,"isNodeModule":false,"specifiers":[]}]},"tests/project-react-js-test/src/index.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.js","files":5,"dependencies":[{"importPath":"react","importAbsolutePath":"react","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"React","alias":"","isDefault":true}]},{"importPath":"react-dom","importAbsolutePath":"react-dom","isCircularDependency":null,"isNodeModule":true,"specifiers":[{"name":"ReactDOM","alias":"","isDefault":true}]},{"importPath":"./index.css","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.css","isCircularDependency":false,"isNodeModule":false,"specifiers":[]},{"importPath":"./App.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"App","alias":"","isDefault":true}]},{"importPath":"./registerServiceWorker.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js","isCircularDependency":false,"isNodeModule":false,"specifiers":[{"name":"registerServiceWorker","alias":"","isDefault":true}]}]},"tests/project-react-js-test/src/registerServiceWorker.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js","files":0,"dependencies":[]}}, 15 | {"tests/project-react-js-test/src/App.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js","files":2,"dependencies":[{"importPath":"./logo.svg","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/logo.svg","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"logo","alias":"","isDefault":true}]},{"importPath":"./App.css","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.css","isCircularDependency":null,"isNodeModule":false,"specifiers":[]}]},"tests/project-react-js-test/src/App.test.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.test.js","files":1,"dependencies":[{"importPath":"./App.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"App","alias":"","isDefault":true}]}]},"tests/project-react-js-test/src/index.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.js","files":3,"dependencies":[{"importPath":"./index.css","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.css","isCircularDependency":null,"isNodeModule":false,"specifiers":[]},{"importPath":"./App.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"App","alias":"","isDefault":true}]},{"importPath":"./registerServiceWorker.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js","isCircularDependency":null,"isNodeModule":false,"specifiers":[{"name":"registerServiceWorker","alias":"","isDefault":true}]}]},"tests/project-react-js-test/src/registerServiceWorker.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js","files":0,"dependencies":[]}}, 16 | {"tests/project-react-js-test/src/App.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js","files":2,"dependents":[{"filePath":"tests/project-react-js-test/src/App.test.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.test.js","importPath":"./App.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js","isCircularDependency":null,"specifiers":[{"name":"App","alias":"","isDefault":true}]},{"filePath":"tests/project-react-js-test/src/index.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.js","importPath":"./App.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.js","isCircularDependency":null,"specifiers":[{"name":"App","alias":"","isDefault":true}]}]},"tests/project-react-js-test/src/App.test.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/App.test.js","files":0,"dependents":[]},"tests/project-react-js-test/src/index.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.js","files":0,"dependents":[]},"tests/project-react-js-test/src/registerServiceWorker.js":{"absolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js","files":1,"dependents":[{"filePath":"tests/project-react-js-test/src/index.js","fileAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/index.js","importPath":"./registerServiceWorker.js","importAbsolutePath":"/Users/lorenzo/Desktop/deps-report/tests/project-react-js-test/src/registerServiceWorker.js","isCircularDependency":null,"specifiers":[{"name":"registerServiceWorker","alias":"","isDefault":true}]}]}} 17 | ] --------------------------------------------------------------------------------