Skip to content

Commit

Permalink
Use promises in API
Browse files Browse the repository at this point in the history
  • Loading branch information
pahen committed Aug 17, 2016
1 parent 2869b44 commit dbad4b6
Show file tree
Hide file tree
Showing 11 changed files with 346 additions and 217 deletions.
107 changes: 56 additions & 51 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,56 +55,61 @@ if (!program.color) {
config.edgeColor = '#757575';
}

const res = madge(program.args[0], config);

if (program.list || (!program.summary && !program.circular && !program.depends && !program.image && !program.dot && !program.json)) {
printResult.list(res.obj(), {
colors: program.color,
output: program.output
});
}

if (program.summary) {
printResult.summary(res.obj(), {
colors: program.color,
output: program.output
});
}

if (program.json) {
process.stdout.write(JSON.stringify(res.tree) + '\n');
}

if (program.circular) {
const circular = res.circular();

printResult.circular(circular, {
colors: program.color,
output: program.output
});

if (circular.length) {
process.exit(1);
}
}

if (program.depends) {
printResult.depends(res.depends(program.depends), {
colors: program.color,
output: program.output
});
}

if (program.image) {
res.image((image) => {
fs.writeFile(program.image, image, (err) => {
if (err) {
throw err;
madge(program.args[0], config)
.then((res) => {
if (program.list || (!program.summary && !program.circular && !program.depends && !program.image && !program.dot && !program.json)) {
printResult.list(res.obj(), {
colors: program.color,
output: program.output
});
}

if (program.summary) {
printResult.summary(res.obj(), {
colors: program.color,
output: program.output
});
}

if (program.json) {
process.stdout.write(JSON.stringify(res.tree) + '\n');
}

if (program.circular) {
const circular = res.circular();

printResult.circular(circular, {
colors: program.color,
output: program.output
});

if (circular.length) {
process.exit(1);
}
});
}

if (program.depends) {
printResult.depends(res.depends(program.depends), {
colors: program.color,
output: program.output
});
}

if (program.image) {
return res.image().then((image) => {
fs.writeFile(program.image, image, (err) => {
if (err) {
throw err;
}
});
});
}

if (program.dot) {
process.stdout.write(res.dot());
}
})
.catch((err) => {
console.log(err);
process.exit(1);
});
}

if (program.dot) {
process.stdout.write(res.dot());
}
8 changes: 5 additions & 3 deletions lib/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ function createGraphvizOptions(config) {
* Creates a PNG image from the module dependency graph.
* @param {Object} modules
* @param {Object} config
* @param {Function} callback
* @return {Promise}
*/
module.exports.image = function (modules, config, callback) {
module.exports.image = function (modules, config) {
const g = graphviz.digraph('G');
const nodes = {};

Expand Down Expand Up @@ -85,7 +85,9 @@ module.exports.image = function (modules, config, callback) {
});
});

g.output(createGraphvizOptions(config), callback);
return new Promise((resolve) => {
g.output(createGraphvizOptions(config), resolve);
});
};

/**
Expand Down
65 changes: 42 additions & 23 deletions lib/madge.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const fs = require('fs');
const path = require('path');
const fs = require('mz/fs');
const dependencyTree = require('dependency-tree');
const cyclic = require('./cyclic');
const graph = require('./graph');
Expand All @@ -27,7 +27,7 @@ class Madge {
* Class constructor.
* @constructor
* @api public
* @param {String|Object} filename
* @param {String} filename
* @param {Object} config
*/
constructor(filename, config) {
Expand All @@ -38,26 +38,43 @@ class Madge {
this.config = Object.assign({}, defaultConfig, config);
debug('using config', this.config);

this.filename = filename;
this.excludeRegex = this.config.exclude ? new RegExp(this.config.exclude) : false;
this.rootDirectory = this.config.directory ? path.resolve(this.config.directory) : path.dirname(filename);
}

if (typeof filename === 'object') {
this.tree = filename;
} else {
if (!fs.statSync(filename).isFile()) { // eslint-disable-line no-sync
throw new Error('Directory not supported');
}

this.tree = this.convertDependencyTree(dependencyTree({
filename: filename,
directory: this.rootDirectory,
requireConfig: this.config.requireConfig,
webpackConfig: this.config.webpackConfig,
filter: this.pathFilter.bind(this)
}));
}

this.sortDependencies();
/**
* Will start parsing filename and compute dependencies.
* @return {Promise}
*/
parse() {
return fs
.exists(this.filename)
.then((exists) => {
if (!exists) {
throw new Error('Filename ' + this.filename + ' does not exists');
}

return fs.stat(this.filename);
})
.then((stats) => {
if (!stats.isFile()) {
throw new Error('Filename ' + this.filename + ' is not a file');
}
})
.then(() => {
this.tree = this.convertDependencyTree(dependencyTree({
filename: this.filename,
directory: this.rootDirectory,
requireConfig: this.config.requireConfig,
webpackConfig: this.config.webpackConfig,
filter: this.pathFilter.bind(this)
}));

this.sortDependencies();

return this;
});
}

/**
Expand Down Expand Up @@ -176,11 +193,13 @@ class Madge {
/**
* Return the module dependency graph as a PNG image.
* @api public
* @param {Function} callback
* @return {Promise}
*/
image(callback) {
graph.image(this.tree, this.config, callback);
image() {
return graph.image(this.tree, this.config);
}
}

module.exports = (filename, config) => new Madge(filename, config);
module.exports = (filename, config) => {
return new Madge(filename, config).parse();
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"debug": "^2.2.0",
"dependency-tree": "^5.4.1",
"graphviz": "^0.0.8",
"mz": "^2.4.0",
"rc": "^1.1.6"
},
"devDependencies": {
Expand Down
99 changes: 61 additions & 38 deletions test/amd.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,65 +7,88 @@ require('should');
describe('AMD', () => {
const dir = __dirname + '/files/amd';

it('should find recursive dependencies', () => {
madge(dir + '/ok/a.js').obj().should.eql({
'a': ['sub/b'],
'sub/b': ['sub/c'],
'sub/c': ['d'],
'd': []
});
it('should find recursive dependencies', (done) => {
madge(dir + '/ok/a.js').then((res) => {
res.obj().should.eql({
'a': ['sub/b'],
'sub/b': ['sub/c'],
'sub/c': ['d'],
'd': []
});
done();
}).catch(done);
});

it('should ignore plugins', () => {
madge(dir + '/plugin.js').obj().should.eql({
'plugin': ['ok/d'],
'ok/d': []
});
it('should ignore plugins', (done) => {
madge(dir + '/plugin.js').then((res) => {
res.obj().should.eql({
'plugin': ['ok/d'],
'ok/d': []
});
done();
}).catch(done);
});

it('should find nested dependencies', () => {
madge(dir + '/nested/main.js').obj().should.eql({
'a': [],
'b': [],
'main': [
'a',
'b'
]
});
it('should find nested dependencies', (done) => {
madge(dir + '/nested/main.js').then((res) => {
res.obj().should.eql({
'a': [],
'b': [],
'main': [
'a',
'b'
]
});
done();
}).catch(done);
});

it('should find circular dependencies', () => {
madge(dir + '/circular/main.js').circular().should.eql([
['a', 'c'],
['f', 'g', 'h']
]);
it('should find circular dependencies', (done) => {
madge(dir + '/circular/main.js').then((res) => {
res.circular().should.eql([
['a', 'c'],
['f', 'g', 'h']
]);
done();
}).catch(done);
});

it('should find circular dependencies with relative paths', () => {
madge(dir + '/circularRelative/a.js').circular().should.eql([['a', 'foo/b']]);
it('should find circular dependencies with relative paths', (done) => {
madge(dir + '/circularRelative/a.js').then((res) => {
res.circular().should.eql([['a', 'foo/b']]);
done();
}).catch(done);
});

it('should find circular dependencies with alias', () => {
it('should find circular dependencies with alias', (done) => {
madge(dir + '/circularAlias/dos.js', {
requireConfig: dir + '/circularAlias/config.js'
}).circular().should.eql([['dos', 'x86']]);
}).then((res) => {
res.circular().should.eql([['dos', 'x86']]);
done();
}).catch(done);
});

it('should work for files with ES6 code inside', () => {
madge(dir + '/amdes6.js')
.obj().should.eql({
it('should work for files with ES6 code inside', (done) => {
madge(dir + '/amdes6.js').then((res) => {
res.obj().should.eql({
'amdes6': ['ok/d'],
'ok/d': []
});
done();
}).catch(done);
});

it('should use paths found in RequireJS config', () => {
it('should use paths found in RequireJS config', (done) => {
madge(dir + '/requirejs/a.js', {
requireConfig: dir + '/requirejs/config.js'
}).obj().should.eql({
'a': ['vendor/jquery-2.0.3'],
'vendor/jquery-2.0.3': []
});
}).then((res) => {
res.obj().should.eql({
'a': ['vendor/jquery-2.0.3'],
'vendor/jquery-2.0.3': []
});
done();
}).catch(done);
});

it.skip('should compile coffeescript on-the-fly', () => {
Expand Down
Loading

0 comments on commit dbad4b6

Please sign in to comment.