Rick Tracy
Detective Rick Tracy is a pluggable dependency graph array generator written in js.
This tool was designed to generated a very simple tree structure which I could use in a gulp workflow to look up the entry point js files from any level of dependency. How this differs from similar tools is that this is designed for projects that are mixed with ES6 imports and Common JS requires, it returns a usable final tree object, and it offers a lot of options for filtering and processing how modules are discovered.
Features
- Works with ES6
import
and Common JSrequire
mixed in the same source files. - Has similar options to module-deps for filtering, mapping, and post-resolution filtering ids.
- Uses a labeled stream splicer to allow total manipulation of the stream pipeline.
Installation
To install from NPM:
sudo npm install rick-tracy
Manually via git:
git clone https://github.com/jayzawrotny/rick-tracy.git
In node (ES5):
var RickTracy = require('rick-tracy');
In node (ES6):
import RickTracy from 'rick-tracy';
Usage
;;; let rickTracy = // the usual suspects ;) lineup: 'path/to/entry/points/**/*.js'; // Build the dependency graph and write to a writable streamrickTracy // Or get the tree from the complete handlerrickTracy ; // Or create your own stream pipelinerickTracy // Could also be replaced with any writable stream
Options
lineup (string | array)
'**/*.js'
['**/*.js', '!**/_*.js']
A glob string to find entry points relative to process.cwd()
. Used by vinyl-fs to send vinyl entry point files to the pipeline for tracing.
lineup: '**/*.js';
filter (function:boolean)
function (id)
A filter function to run against new module paths as they are discovered and before RickTracy uses nodeResolve to find its absolute path. The function must return a boolean.
trace: { return !id; // Nobody wants anything to do with Craiginald. }
The above example filters out any ids with the word 'craginald' in them.
postFilter (function:boolean)
function (id)
Another filter function to run against a resolved node module which may include an absolute path.
trace: { return !id; // Ignore any modules in the node_modules directory. } ;
map (function:string)
function (id) { return id }
The map function allows you to modify module ids after they have been filtered, but before they get resolved to an actual location.
trace: { return path; }
The above example prepends the dirname to the module id if you had something like require('myfile')
it would be mapped to /path/to/myfile
;
compileES6Modules (boolean:true)
Specify if you want to compile the ES6 import
statements to commonJS require
statements.
trace: compileES6Modules: false // Will speed up trace process if no ES6 imports are used.
ignorePackages (boolean:true)
Specify if you want Rick Tracy to ignore npm packages in the dependency graph. The default is true. The intended use case is to generate a graph for the app source and not the modules.
trace: ignorePackages: false // Will include node_module packages too
Customization
Pipeline
The pipeline is a labeled stream splicer generated with each new RickTracy
instance. Each pipe in the pipeline is a type of stream consumer either a duplex stream or a transform stream. The stream splicer allows the post creation manipulation of each step in the flow. For instance, you can add a transform stream before any input is sent to the tracer to filter or generate more files to trace. After tracing you could then add another step to affect what is sent to the store. Then after the store you could add another transform stream to affect what is output at the end. The main idea here is that any step can be replaced, removed, prepended or appended to at your discretion.
Below is an example for adding a basic logging step.
; let rickTracy = lineup: 'path/to/entry/points/**/*.js'; rickTracypipeline rickTracy ;
Trace
rickTracy.pipeline.get('trace')
Traces the input vinyl files through all their children and their children's dependencies. Emits each dependency that it finds.
Input: Vinyl file object
Output:
// Will be generated for each module it discovers and resolves suspect: '/entry/point/file.js' leads: '/sub/dependency/of/entry/point.js' '/sub/depdendency/of/entry/point.js' source: null // Used for sub dependencies of dependencies.
Store
rickTracy.pipeline.get('store')
Stores the module dependency in a flat array that it can then traverse later to build the final dependency tree.
Input:
suspect: '/entry/point/file.js' leads: '/sub/dependency/of/entry/point.js' '/sub/depdendency/of/entry/point.js' source: null // Used for sub dependencies of dependencies.
Output:
// Final dependency graph tree '/entry/point/file.js': '/sub/dep.js': '/sub/sub/dep.js': {} '/sub/dep2.js': {}
CLI
Currently I have not added any CLI functionality. If you would like me to implement it please let me know. If you really want CLI you can create a pull request 😄.
About
Credits
This tool was lovingly made for use at VenueBook.
License
BSD-3-Clause (c) 2016 VenueBook, Inc.