Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
64 additions
and
160 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,25 @@ | ||
const parse = require('./parse'); | ||
const compileFromApiElements = require('./compile'); | ||
|
||
function createParserErrorCompilationResult(message) { | ||
return { | ||
mediaType: null, | ||
transactions: [], | ||
annotations: [{ | ||
type: 'error', component: 'apiDescriptionParser', message, location: [[0, 1]], | ||
}], | ||
}; | ||
} | ||
|
||
function compile(source, filename, callback) { | ||
// All regular parser-related or compilation-related annotations | ||
// should be returned in the "compilation result". Callback should get | ||
// an error only in case of unexpected crash. | ||
function compile(apiDescription, filename, callback) { | ||
parse(apiDescription, (err, parseResult) => { | ||
// Shouldn't happen, 'parse' turns all parser crashes into annotations | ||
if (err) { callback(err); return; } | ||
|
||
parse(source, (err, parseResult) => { | ||
// If 'apiElements' isn't empty, then we don't need to care about 'err' | ||
// as it should be represented by annotation inside 'apiElements' | ||
// and compilation should be able to deal with it and to propagate it. | ||
// Should always set annotations and never throw, try/catch deals only | ||
// with unexpected compiler crashes | ||
let compilationResult; | ||
if (!(parseResult ? parseResult.apiElements : undefined)) { | ||
if (err) { return callback(null, createParserErrorCompilationResult(err.message)); } | ||
|
||
const message = 'The API description parser was unable to provide a valid parse result'; | ||
return callback(null, createParserErrorCompilationResult(message)); | ||
} | ||
|
||
// The try/catch is just to deal with unexpected crash. Compilation passes | ||
// all errors as part of the 'result' and it should not throw anything | ||
// in any case. | ||
try { | ||
const { mediaType, apiElements } = parseResult; | ||
compilationResult = compileFromApiElements(mediaType, apiElements, filename); | ||
} catch (error) { | ||
return callback(error); | ||
} catch (syncErr) { | ||
callback(syncErr); | ||
return; | ||
} | ||
|
||
return callback(null, compilationResult); | ||
callback(null, compilationResult); | ||
}); | ||
} | ||
|
||
|
||
module.exports = { compile }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,58 @@ | ||
const fury = require('fury'); | ||
|
||
|
||
fury.use(require('fury-adapter-apib-parser')); | ||
fury.use(require('fury-adapter-swagger')); | ||
fury.use(require('fury-adapter-oas3-parser')); | ||
|
||
function createWarning(message) { | ||
const annotationElement = new fury.minim.elements.Annotation(message); | ||
annotationElement.classes.push('warning'); | ||
annotationElement.attributes.set('sourceMap', [ | ||
new fury.minim.elements.SourceMap([[0, 1]]), | ||
const { Annotation, SourceMap, ParseResult } = fury.minim.elements; | ||
|
||
|
||
function createAnnotation(type, message) { | ||
const element = new Annotation(message); | ||
element.classes.push(type); | ||
element.attributes.set('sourceMap', [ | ||
new SourceMap([[0, 1]]), | ||
]); | ||
return annotationElement; | ||
return element; | ||
} | ||
|
||
function parse(source, callback) { | ||
let mediaType; | ||
let warningElement = null; | ||
const adapters = fury.detect(source); | ||
|
||
function detectMediaType(apiDescription) { | ||
const adapters = fury.detect(apiDescription); | ||
if (adapters.length) { | ||
[mediaType] = adapters[0].mediaTypes; | ||
} else { | ||
mediaType = 'text/vnd.apiblueprint'; | ||
warningElement = createWarning( | ||
'Could not recognize API description format.' | ||
+ ' Falling back to API Blueprint by default.' | ||
); | ||
return { mediaType: adapters[0].mediaTypes[0], fallback: false }; | ||
} | ||
return { mediaType: 'text/vnd.apiblueprint', fallback: true }; | ||
} | ||
|
||
const args = { source, mediaType, generateSourceMap: true }; | ||
|
||
return fury.parse(args, (err, apiElements) => { | ||
let modifiedApiElements = apiElements; | ||
let nativeError = null; | ||
function parse(apiDescription, callback) { | ||
const { mediaType, fallback } = detectMediaType(apiDescription); | ||
|
||
if (!(err || apiElements)) { | ||
nativeError = new Error('Unexpected parser error occurred'); | ||
} else if (err) { | ||
// Turning Fury error object into standard JavaScript error | ||
nativeError = new Error(err.message); | ||
} else if (apiElements && !apiElements.errors.isEmpty) { | ||
nativeError = new Error('Parser finished with errors'); | ||
} | ||
fury.parse({ | ||
source: apiDescription, | ||
mediaType, | ||
generateSourceMap: true, | ||
}, (err, parseResult) => { | ||
const apiElements = parseResult || new ParseResult([]); | ||
|
||
if (modifiedApiElements) { | ||
if (warningElement) { modifiedApiElements.unshift(warningElement); } | ||
} else { | ||
modifiedApiElements = null; | ||
if (fallback) { | ||
apiElements.unshift(createAnnotation('warning', ( | ||
'Could not recognize API description format, assuming API Blueprint' | ||
))); | ||
} | ||
if (err && !parseResult) { | ||
// The condition should be only 'if (err)' | ||
// https://github.com/apiaryio/api-elements.js/issues/167 | ||
apiElements.unshift(createAnnotation('error', ( | ||
`Could not parse API description: ${err.message}` | ||
))); | ||
} | ||
|
||
return callback(nativeError, { mediaType, apiElements: modifiedApiElements }); | ||
callback(null, { mediaType, apiElements }); | ||
}); | ||
} | ||
|
||
|
||
module.exports = parse; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters