Skip to content

Commit

Permalink
Include watch task in cli tool.
Browse files Browse the repository at this point in the history
  • Loading branch information
kalinchernev committed Dec 31, 2016
1 parent 20b9516 commit fd16962
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 40 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ app.post('/login', function(req, res) {

A model may be the same for multiple endpoints (Ex. User POST,PUT responses).
In place of writing (or copy and pasting) the same code into multiple locations,
which can be error prone when adding a new field to the schema. You can define
which can be error prone when adding a new field to the schema. You can define
a model and re-use it across multiple endpoints. You can also reference another
model and add fields.
```javascript
Expand Down Expand Up @@ -130,7 +130,7 @@ model and add fields.
* description: users
* schema:
* type: array
* items:
* items:
* $ref: '#/definitions/User'
*/
app.get('/users', function(req, res) {
Expand Down Expand Up @@ -171,7 +171,7 @@ model and add fields.
});
```

### Load external definitions
### Load external definitions

You can load external definitions or paths after ``swaggerJSDoc()`` function.
```javascript
Expand Down Expand Up @@ -213,3 +213,4 @@ Common usage:
- Specify a swagger definition file: `./bin/swagger-jsdoc -d example/swaggerDef.js` - could be any .js or .json file which will be `require()`-ed and parsed/validated as JSON.
- Specify files with documentation: `./bin/swagger-jsdoc example/routes.js example/routes2.js` - free form input, can be before or after definition
- Specify output file (optional): `./bin/swagger-jsdoc -o output.json` - swaggerSpec.json will be created if this is not set.
- Watch for changes: `./bin/swagger-jsdoc -d example/swaggerDef.js example/routes.js example/routes2.js -w` - this will add the definition file swaggerDef.js and its arguments routes.js and routes2.js in a watch process, re-generating swagger spec on changes.
111 changes: 80 additions & 31 deletions bin/swagger-jsdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,80 @@
/**
* Module dependencies.
*/

var program = require('commander');
var fs = require('fs');
var path = require('path');
var swaggerJSDoc = require('../');
var pkg = require('../package.json');
var watcher = require('chokidar');

// Useful input.
var input = process.argv.slice(2);
var output = 'swaggerSpec.json';
// The spec, following a convention.
var output = 'swagger.json';

/**
* Creates a swagger.json file from a definition and a set of files.
* @function
* @param {object} swaggerDefinition - The swagger definition object.
* @param {array} files - List of files with jsdoc comments.
*/
function createSpecification(swaggerDefinition, files) {
// Aggregate information about APIs.
var apis = [];
files.forEach(function(argument) {
// Try to resolve the argument:
var result = fs.lstatSync(path.resolve(argument));
if (result) {
if (result.isFile()) {
apis.push(argument);
}
}
});

// Options for the swagger docs
var options = {
// Import swaggerDefinitions
swaggerDefinition: swaggerDefinition,
// Path to the API docs
apis: apis,
};

// Initialize swagger-jsdoc -> returns validated swagger spec in json format
var swSpec = swaggerJSDoc(options);

// Delete existing files and recreate.
fs.exists(output, function(exists) {
if (exists) {
fs.unlink(output, function fileDeleted() {
console.log('Spec file to be updated');
// Create the output file with swagger specification.
fs.writeFile(output, JSON.stringify(swSpec, null, 2), function(err) {
if (err) {
throw err;
}
console.log('swagger.json updated.');
});
});
} else {
// Create the output file with swagger specification.
fs.writeFile(output, JSON.stringify(swSpec, null, 2), function(err) {
if (err) {
throw err;
}
console.log('swagger.json updated.');
});
}
});
}

program
.version(pkg.version)
.usage('[options] <path ...>')
.option('-d, --definition <swaggerDef.js>', 'Input swagger definition.')
.option('-o, --output [swaggerSpec.json]', 'Output swagger specification.')
.option('-w, --watch', 'Whether or not to listen for continous changes.')
.parse(process.argv);

// If no arguments provided, display help menu.
Expand Down Expand Up @@ -76,35 +135,25 @@ fs.readFile(program.definition, 'utf-8', function(err, data) {
if (!program.args.length) {
return console.log('You must provide arguments for reading APIs.');
}
// Aggregate information about APIs.
var apis = [];
program.args.forEach(function(argument) {
// Try to resolve the argument:
var result = fs.lstatSync(path.resolve(argument));
if (result) {
if (result.isFile()) {
apis.push(argument);
}
}
});

// Options for the swagger docs
var options = {
// Import swaggerDefinitions
swaggerDefinition: swaggerDefinition,
// Path to the API docs
apis: apis,
};

// Initialize swagger-jsdoc -> returns validated swagger spec in json format
var swaggerSpec = swaggerJSDoc(options);

// Create the output file with swagger specification.
fs.writeFile(output, JSON.stringify(swaggerSpec, null, 2), function(err) {
if (err) {
throw err;
}
console.log('Swagger specification created successfully.');
});

// If watch flag is turned on, listen for changes.
if (program.watch) {
watcher.watch([program.definition, program.args])
.on('ready', function startMessage() {
console.log('Listening for changes in definition and documentation.');
})
.on('error', function catchErr(err) {
console.error(err);
})
.on('add', function fileAdded(path) {
console.log('File added ' + path);
})
.on('all', function regenerateSpec() {
createSpecification(swaggerDefinition, program.args);
});
}
// Just create the specification.
else {
createSpecification(swaggerDefinition, program.args);
}
});
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"devDependencies": {
"body-parser": "^1.15.0",
"chai": "^3.5.0",
"chokidar": "^1.6.1",
"express": "^4.13.4",
"istanbul": "^0.4.2",
"jscs": "^3.0.0",
Expand All @@ -48,4 +49,4 @@
"mocha-jshint": "^2.3.1",
"supertest": "^2.0.1"
}
}
}
10 changes: 5 additions & 5 deletions test/cli-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ describe('command line interface', function () {
});
});

it('should create swaggerSpec.json by default when the API input is good', function (done) {
it('should create swagger.json by default when the API input is good', function (done) {
var goodInput = process.env.PWD + '/bin/swagger-jsdoc.js -d example/swaggerDef.js example/routes.js';
exec(goodInput, function (error, stdout, stderr) {
if (error) {
throw new Error(error, stderr);
}
expect(stdout).to.contain('Swagger specification created successfully.');
expect(stdout).to.contain('swagger.json updated.');
expect(stderr).to.not.contain('You are using properties to be deprecated');
var specification = fs.statSync('swaggerSpec.json');
var specification = fs.statSync('swagger.json');
// Check that the physical file was created.
expect(specification.nlink).to.be.above(0);
done();
Expand All @@ -106,7 +106,7 @@ describe('command line interface', function () {
if (error) {
throw new Error(error, stderr);
}
expect(stdout).to.contain('Swagger specification created successfully.');
expect(stdout).to.contain('swagger.json updated.');
var specification = fs.statSync('customSpec.json');
// Check that the physical file was created.
expect(specification.nlink).to.be.above(0);
Expand All @@ -116,7 +116,7 @@ describe('command line interface', function () {

// Cleanup test files if any.
after(function() {
var defaultSpecification = process.env.PWD + '/swaggerSpec.json';
var defaultSpecification = process.env.PWD + '/swagger.json';
var customSpecification = process.env.PWD + '/customSpec.json';
fs.unlinkSync(defaultSpecification);
fs.unlinkSync(customSpecification);
Expand Down

0 comments on commit fd16962

Please sign in to comment.