@ianwalter/blueline
Version:
Toolkit for converting API Blueprint files to JSON and consuming that JSON
117 lines (98 loc) • 3.19 kB
JavaScript
import { findNested, findAllNested } from '@ianwalter/find-nested';
import drafter from 'drafter.js';
class Blueprint {
constructor (json) {
this.json = json;
}
find (filter = 0, prop) {
let json = this.json;
// Filter the JSON schema using the filter parameter.
if (Number.isInteger(filter)) {
const found = findNested(json, prop) || json;
json = prop !== undefined ? found[filter] : found;
} else if (typeof filter === 'string') {
const val = i => {
if (Array.isArray(i)) {
return i.find(val)
} else if (i && typeof i === 'object') {
return obj(i)
} else {
return i === filter
}
};
const obj = i => Object.values(i).find(val);
const descriminator = i => i && Array.isArray(i) && i.find(obj);
json = (findNested(json, prop, descriminator) || json).find(obj);
}
// Return this instance so user can chain calls.
return new Blueprint(json)
}
group (filter) {
return this.find(filter)
}
resource (filter) {
return this.find(filter, 'resources')
}
action (filter) {
return this.find(filter, 'actions')
}
example (filter) {
return this.find(filter, 'examples')
}
request (filter) {
return this.find(filter, 'requests')
}
response (filter) {
return this.find(filter, 'responses')
}
body () {
return this.json.body
}
}
function parse (input) {
return new Promise((resolve, reject) => {
drafter.parse(input, { type: 'ast' }, (err, { ast }) => {
if (err) {
reject(err);
}
// If request/response headers contain 'json', parse the body strings.
const hasJsonBody = obj => obj.headers.some(h => h.value.includes('json'));
let results = findAllNested(ast.resourceGroups, undefined, hasJsonBody);
results.map(result => {
try {
result.body = JSON.parse(result.body);
} catch (err) {
// If there is a JSON.parse error, don't mutate the result.
return result
}
});
// Find all JSON schemas.
results = findAllNested(ast.resourceGroups, undefined, obj => obj.schema);
results.map(result => {
try {
const schema = JSON.parse(result.schema);
const requiredIsArray = schema && Array.isArray(schema.required);
if (requiredIsArray && schema.required.length === 0) {
// Delete the JSON Schema because it was not generated properly and
// is invalid.
delete result.schema;
} else if (schema) {
// De-duplicate required values since there is a bug in drafter.
if (requiredIsArray) {
schema.required = Array.from(new Set(schema.required));
}
// Save the parse schema back to the containing object so it's
// easier to read.
result.schema = schema;
}
return result
} catch (err) {
// If there is a JSON.parse error, don't mutate the result.
return result
}
});
resolve(ast.resourceGroups);
});
})
}
export { Blueprint, parse };