2015-10-07 12:47:57 +03:00
|
|
|
'use strict';
|
2016-05-25 18:34:31 +03:00
|
|
|
|
2016-06-15 23:33:57 +03:00
|
|
|
import JsonSchemaRefParser from 'json-schema-ref-parser';
|
2015-10-09 10:50:02 +03:00
|
|
|
import JsonPointer from './JsonPointer';
|
2015-10-07 12:47:57 +03:00
|
|
|
|
2016-06-22 21:17:48 +03:00
|
|
|
export class SpecManager {
|
2016-06-12 20:44:34 +03:00
|
|
|
public _schema:any = {};
|
2016-06-13 20:54:24 +03:00
|
|
|
public apiUrl: string;
|
2016-05-25 18:34:31 +03:00
|
|
|
private _instance:any;
|
2016-06-12 20:44:34 +03:00
|
|
|
|
2016-06-13 20:54:24 +03:00
|
|
|
static instance() {
|
2016-06-22 21:17:48 +03:00
|
|
|
return new SpecManager();
|
2016-06-13 20:54:24 +03:00
|
|
|
}
|
|
|
|
|
2015-10-07 12:47:57 +03:00
|
|
|
constructor() {
|
2016-06-22 21:17:48 +03:00
|
|
|
if (SpecManager.prototype._instance) {
|
|
|
|
return SpecManager.prototype._instance;
|
2015-10-07 12:47:57 +03:00
|
|
|
}
|
|
|
|
|
2016-06-22 21:17:48 +03:00
|
|
|
SpecManager.prototype._instance = this;
|
2015-10-07 12:47:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
load(url) {
|
|
|
|
let promise = new Promise((resolve, reject) => {
|
|
|
|
this._schema = {};
|
|
|
|
|
2016-05-20 20:13:39 +03:00
|
|
|
JsonSchemaRefParser.bundle(url, {http: {withCredentials: false}})
|
2016-06-22 21:17:48 +03:00
|
|
|
.then(schema => {
|
|
|
|
this._schema = schema;
|
|
|
|
resolve(this._schema);
|
|
|
|
this.init();
|
|
|
|
}, err => reject(err));
|
2015-10-07 12:47:57 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
|
2015-11-17 01:03:09 +03:00
|
|
|
/* calculate common used values */
|
|
|
|
init() {
|
2016-03-27 18:25:46 +03:00
|
|
|
if (!this._schema || !this._schema.schemes) return;
|
2015-11-17 02:14:55 +03:00
|
|
|
this.apiUrl = this._schema.schemes[0] + '://' + this._schema.host + this._schema.basePath;
|
2015-11-29 18:14:18 +03:00
|
|
|
if (this.apiUrl.endsWith('/')) {
|
|
|
|
this.apiUrl = this.apiUrl.substr(0, this.apiUrl.length - 1);
|
|
|
|
}
|
2015-11-17 01:03:09 +03:00
|
|
|
}
|
|
|
|
|
2015-10-07 12:47:57 +03:00
|
|
|
get schema() {
|
|
|
|
return this._schema;
|
|
|
|
}
|
|
|
|
|
2015-10-08 23:21:51 +03:00
|
|
|
byPointer(pointer) {
|
2015-10-10 16:01:41 +03:00
|
|
|
let res = null;
|
|
|
|
try {
|
2016-01-17 00:25:12 +03:00
|
|
|
res = JsonPointer.get(this._schema, decodeURIComponent(pointer));
|
2015-10-10 16:01:41 +03:00
|
|
|
} catch(e) {/*skip*/ }
|
|
|
|
return res;
|
2015-10-07 12:47:57 +03:00
|
|
|
}
|
2015-10-08 23:21:51 +03:00
|
|
|
|
2015-10-25 14:26:38 +03:00
|
|
|
resolveRefs(obj) {
|
|
|
|
Object.keys(obj).forEach(key => {
|
|
|
|
if (obj[key].$ref) {
|
2015-12-12 18:29:50 +03:00
|
|
|
let resolved = this.byPointer(obj[key].$ref);
|
|
|
|
resolved._pointer = obj[key].$ref;
|
|
|
|
obj[key] = resolved;
|
2015-10-25 14:26:38 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
getMethodParams(methodPtr, resolveRefs) {
|
|
|
|
/* inject JsonPointer into array elements */
|
|
|
|
function injectPointers(array, root) {
|
2015-12-14 16:53:22 +03:00
|
|
|
if (!Array.isArray(array)) {
|
|
|
|
throw new Error(`parameters must be an array. Got ${typeof array} at ${root}`);
|
|
|
|
}
|
2015-10-25 14:26:38 +03:00
|
|
|
return array.map((element, idx) => {
|
|
|
|
element._pointer = JsonPointer.join(root, idx);
|
|
|
|
return element;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-12-12 18:29:50 +03:00
|
|
|
// accept pointer directly to parameters as well
|
|
|
|
if (JsonPointer.baseName(methodPtr) === 'parameters') {
|
|
|
|
methodPtr = JsonPointer.dirName(methodPtr);
|
2015-10-25 14:26:38 +03:00
|
|
|
}
|
|
|
|
|
2015-12-12 18:29:50 +03:00
|
|
|
//get path params
|
|
|
|
let pathParamsPtr = JsonPointer.join(JsonPointer.dirName(methodPtr), ['parameters']);
|
|
|
|
let pathParams = this.byPointer(pathParamsPtr) || [];
|
|
|
|
|
|
|
|
let methodParamsPtr = JsonPointer.join(methodPtr, ['parameters']);
|
|
|
|
let methodParams = this.byPointer(methodParamsPtr) || [];
|
|
|
|
pathParams = injectPointers(pathParams, pathParamsPtr);
|
|
|
|
methodParams = injectPointers(methodParams, methodParamsPtr);
|
|
|
|
|
2015-10-25 14:26:38 +03:00
|
|
|
if (resolveRefs) {
|
|
|
|
methodParams = this.resolveRefs(methodParams);
|
2015-11-04 23:39:46 +03:00
|
|
|
pathParams = this.resolveRefs(pathParams);
|
2015-10-25 14:26:38 +03:00
|
|
|
}
|
|
|
|
return methodParams.concat(pathParams);
|
|
|
|
}
|
|
|
|
|
2015-11-17 02:34:13 +03:00
|
|
|
getTagsMap() {
|
|
|
|
let tags = this._schema.tags || [];
|
|
|
|
var tagsMap = {};
|
|
|
|
for (let tag of tags) {
|
|
|
|
tagsMap[tag.name] = {
|
|
|
|
description: tag.description,
|
2015-12-12 14:49:22 +03:00
|
|
|
'x-traitTag': tag['x-traitTag'] || false
|
2015-11-17 02:34:13 +03:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return tagsMap;
|
|
|
|
}
|
|
|
|
|
2016-01-09 17:52:24 +03:00
|
|
|
findDerivedDefinitions(defPointer) {
|
|
|
|
let definition = this.byPointer(defPointer);
|
2016-01-15 23:42:55 +03:00
|
|
|
if (!definition) throw new Error(`Can't load schema at ${defPointer}`);
|
2016-01-09 17:52:24 +03:00
|
|
|
if (!definition.discriminator) return [];
|
|
|
|
|
|
|
|
let globalDefs = this._schema.definitions || {};
|
|
|
|
let res = [];
|
|
|
|
for (let defName of Object.keys(globalDefs)) {
|
2016-06-22 19:13:57 +03:00
|
|
|
if (!globalDefs[defName].allOf &&
|
|
|
|
!globalDefs[defName]['x-derived-from']) continue;
|
|
|
|
let subTypes = globalDefs[defName]['x-derived-from'] ||
|
2016-07-15 17:43:01 +03:00
|
|
|
globalDefs[defName].allOf.map(subType => subType._pointer || subType.$ref);
|
2016-06-22 19:13:57 +03:00
|
|
|
let idx = subTypes.findIndex(ref => ref === defPointer);
|
2016-01-09 17:52:24 +03:00
|
|
|
if (idx < 0) continue;
|
|
|
|
|
2016-04-13 15:46:41 +03:00
|
|
|
let empty = false;
|
|
|
|
if (subTypes.length === 1) {
|
|
|
|
empty = true;
|
|
|
|
}
|
|
|
|
res.push({name: defName, $ref: `#/definitions/${defName}`, empty});
|
2016-01-09 17:52:24 +03:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-10-07 12:47:57 +03:00
|
|
|
}
|