Skip to content

Commit

Permalink
Merge pull request #29 from wework/bug/verbose
Browse files Browse the repository at this point in the history
Fix verbosity for lint and serve
  • Loading branch information
Phil Sturgeon committed Mar 21, 2018
2 parents c2b18ce + 78d0682 commit 2804314
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 81 deletions.
36 changes: 18 additions & 18 deletions lib/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ function readFileAsync(filename, encoding) {
});
}

function readSpecFile(file) {
function readSpecFile(file, options) {
if (options.verbose) {
console.log('GET ' + file);
}
if (file && file.startsWith('http')) {
return fetch(file).then(res => {
if (res.status !== 200) {
Expand All @@ -36,13 +39,14 @@ function readSpecFile(file) {
})
}
else {
// TODO error handlers?
return readFileAsync(file, 'utf8').then(data => data);
}
}

const readOrError = async (file) => {
const readOrError = async (file, options = {}) => {
try {
return await loadSpec(file, { resolve: true });
return await loadSpec(file, options);
}
catch (error) {
if (error instanceof OpenError) {
Expand All @@ -58,26 +62,22 @@ const readOrError = async (file) => {
}
}

const resolveContent = (openapi, source) => {
const options = {
const resolveContent = (openapi, options) => {
return resolver.resolve({
...options,
resolve: true,
cache: [],
externals: [],
externalRefs: {},
rewriteRefs: true,
origin: source,
source: source
};

options.openapi = openapi;

return resolver.resolve(options);
openapi: openapi,
});
}

const loadSpec = async (source, opts = {}) => {
const { resolve = false } = opts;

return await readSpecFile(source)
const loadSpec = async (source, options = {}) => {
options.source = source;
options.origin = source;
return await readSpecFile(source, options)
.then(content => {
try {
return yaml.load(content, { json: true });
Expand All @@ -88,8 +88,8 @@ const loadSpec = async (source, opts = {}) => {
}, err => { throw new OpenError(err.message) })
.then(async unresolved => {
let resolved = unresolved;
if (resolve === true) {
resolved = (await resolveContent(unresolved, source)).openapi;
if (options.resolve === true) {
resolved = (await resolveContent(unresolved, options)).openapi;
}
return resolved;
}, err => { throw err });
Expand Down
17 changes: 10 additions & 7 deletions lib/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ function resolveAllInternal(obj, context, src, parentPath, base, options) {
if (obj[key].startsWith('#')) {
if (!seen[obj[key]] && !obj.$fixed) {
let target = common.clone(jptr(context, obj[key]));
if (options.verbose>1) console.log((target === false ? red : green)+'Internal resolution', obj[key], normal);
if (options.verbose>1) {
console.log((target === false ? red : green)+'Internal resolution', obj[key], normal);
}

/*
ResolutionCase:A is where there is a local reference in an externally
Expand Down Expand Up @@ -114,10 +116,9 @@ function resolveExternal(root, pointer, options, callback) {
}
base = base.join('/');

let u2 = url.parse(pointer);
let effectiveProtocol = (u2.protocol ? u2.protocol : (u.protocol ? u.protocol : 'file:'));

let target = url.resolve(base ? base + '/' : '', pointer)
const u2 = url.parse(pointer);
const effectiveProtocol = (u2.protocol ? u2.protocol : (u.protocol ? u.protocol : 'file:'));
const target = url.resolve(base ? base + '/' : '', pointer)

if (options.cache[target]) {
if (options.verbose) console.log('CACHED', target, fragment);
Expand All @@ -126,7 +127,7 @@ function resolveExternal(root, pointer, options, callback) {
resolutionSource:A this is where we have cached the externally-referenced document from a
file, http or custom handler
*/
let context = common.clone(options.cache[target]);
const context = common.clone(options.cache[target]);
let data = context;
if (fragment) {
data = jptr(data, fragment);
Expand All @@ -137,7 +138,9 @@ function resolveExternal(root, pointer, options, callback) {
return Promise.resolve(data);
}

if (options.verbose) console.log('GET', target, fragment);
if (options.verbose) {
console.log('GET', target, fragment);
}

if (options.handlers && options.handlers[effectiveProtocol]) {
return options.handlers[effectiveProtocol](base, pointer, fragment, options)
Expand Down
6 changes: 3 additions & 3 deletions lib/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -1234,15 +1234,15 @@ function setupOptions(options,openapi) {
}

function validate(openapi, options, callback) {
setupOptions(options,openapi);
setupOptions(options, openapi);

var actions = [];
const actions = [];
if (options.resolve) {
findExternalRefs(openapi, options, actions);
}

co(function* () {
for (var promise of actions) {
for (const promise of actions) {
yield promise; // because we mutate the array
}
options.context = [];
Expand Down
49 changes: 25 additions & 24 deletions lint.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,31 @@ ${colors.reset + error.message}
}

const command = async (file, cmd) => {
const spec = await loader.readOrError(file);
const options = { openapi: spec };

linter.loadRules(cmd.rules, cmd.skip);

validator.validate(options.openapi, options, (err, options) => {
if (err) {
console.error(colors.red + 'Specification schema is invalid.' + colors.reset);
const output = formatSchemaError(err, options.context);
console.error(output);
process.exit(1);
}

const lintResults = options.lintResults;
if (lintResults.length) {
console.error(colors.red + 'Specification contains lint errors: ' + lintResults.length + colors.reset);
const output = formatLintResults(lintResults);
console.warn(output)
process.exit(1);
}

console.log(colors.green + 'Specification is valid, with 0 lint errors' + colors.reset)
process.exit(0);
});
const verbose = cmd.quiet ? 1 : cmd.verbose;
const spec = await loader.readOrError(file, { verbose, resolve: true });

linter.loadRules(cmd.rules, cmd.skip);

validator.validate(spec, { verbose }, (err, _options) => {
const { context, lintResults } = _options;

if (err) {
console.error(colors.red + 'Specification schema is invalid.' + colors.reset);
const output = formatSchemaError(err, context);
console.error(output);
process.exit(1);
}

if (lintResults.length) {
console.error(colors.red + 'Specification contains lint errors: ' + lintResults.length + colors.reset);
const output = formatLintResults(lintResults);
console.warn(output)
process.exit(1);
}

console.log(colors.green + 'Specification is valid, with 0 lint errors' + colors.reset)
process.exit(0);
});
};

module.exports = { command }
50 changes: 22 additions & 28 deletions resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
const fs = require('fs');
const yaml = require('js-yaml');
const fetch = require('node-fetch');

const resolver = require('./lib/resolver.js');

const options = {
Expand All @@ -20,45 +19,40 @@ const options = {
const main = (str, output) => {
options.openapi = yaml.safeLoad(str,{json:true});
resolver.resolve(options)
.then(function(){
options.status = 'resolved';
fs.writeFileSync(output, yaml.safeDump(options.openapi,{lineWidth:-1}),'utf8');
console.log('Resolved to ' + output);
process.exit(0);
})
.catch(function(err){
options.status = 'rejected';
console.warn(err);
});
.then(function(){
fs.writeFileSync(output, yaml.safeDump(options.openapi,{lineWidth:-1}),'utf8');
console.log('Resolved to ' + output);
process.exit(0);
})
.catch(function(err){
console.warn(err);
});
};

const command = (filespec, cmd) => {
options.verbose = cmd.verbose;
options.origin = filespec;
options.source = filespec;
if (cmd.quiet) {
options.verbose = 1;
}
const command = (file, cmd) => {
options.origin = file;
options.source = file;
options.verbose = cmd.quiet ? 1 : cmd.verbose;

if (filespec && filespec.startsWith('http')) {
console.log('GET ' + filespec);
fetch(filespec, {agent:options.agent}).then(function (res) {
if (file && file.startsWith('http')) {
if (options.verbose) {
console.log('GET ' + file);
}
fetch(file, { agent:options.agent }).then(res => {
if (res.status !== 200) throw new Error(`Received status code ${res.status}`);
return res.text();
}).then(function (body) {
}).then(body => {
main(body, cmd.output);
}).catch(function (err) {
}).catch(err => {
console.warn(err);
});
}
else {
fs.readFile(filespec,'utf8',function(err,data){
if (err) {
fs.readFile(file, 'utf8', (err,data) => {
if (err)
console.warn(err);
}
else {
else
main(data, cmd.output);
}
});
}
};
Expand Down
7 changes: 6 additions & 1 deletion serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ const loader = require('./lib/loader.js');
const command = async (file, cmd) => {
const app = express();
const port = cmd.port;
const verbose = cmd.quiet ? 1 : cmd.verbose

const bundleDir = path.dirname(require.resolve('redoc'));
const html = server.loadHTML(file);
const spec = await loader.readOrError(file);
const spec = await loader.readOrError(file, {
resolve: true,
verbose
});

app.use('/assets/redoc', express.static(bundleDir));
app.get('/spec.json', (req, res) => {
Expand Down
4 changes: 4 additions & 0 deletions speccy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ program

program
.command('lint <file-or-url>')
.option('-q, --quiet', 'reduce verbosity')
.option('-r, --rules [ruleFile]', 'Provide multiple rules files', collect, [])
.option('-s, --skip [ruleName]', 'Provide multiple rules to skip', collect, [])
.option('-v, --verbose', 'increase verbosity', 2)
.action(lint.command);

program
Expand All @@ -36,6 +38,8 @@ program
.command('serve <file-or-url>')
.description('View specifications in beautiful human readable documentation')
.option('-p, --port [value]', 'port on which the server will listen', 5000)
.option('-q, --quiet', 'reduce verbosity')
.option('-v, --verbose', 'increase verbosity', 2)
.option('-w, --watch', 'reloding browser on spec file changes')
.action(serve.command);

Expand Down

0 comments on commit 2804314

Please sign in to comment.