126 lines
4.2 KiB
JavaScript
126 lines
4.2 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
/**
|
||
|
* functions to walk an OpenAPI schema object and traverse all subschemas
|
||
|
* calling a callback function on each one
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* obtains the default starting state for the `state` object used
|
||
|
* by walkSchema
|
||
|
* @return the state object suitable for use in walkSchema
|
||
|
*/
|
||
|
function getDefaultState() {
|
||
|
return { depth: 0, seen: new WeakMap(), top: true, combine: false, allowRefSiblings: false };
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* begins the walk of a schema object
|
||
|
* @param schema the schema object to walk
|
||
|
* @param parent the parent schema, if any. Use empty object if none
|
||
|
* @param state the initial starting state of the walker, usually obtained from `getDefaultState`. Use empty object to auto-initialise
|
||
|
* @param callback a function taking a schema, parent and state to be called on this and all subschemas
|
||
|
* @return the schema object
|
||
|
*/
|
||
|
function walkSchema(schema, parent, state, callback) {
|
||
|
|
||
|
if (typeof state.depth === 'undefined') state = getDefaultState();
|
||
|
if ((schema === null) || (typeof schema === 'undefined')) return schema;
|
||
|
if (typeof schema.$ref !== 'undefined') {
|
||
|
let temp = {$ref:schema.$ref};
|
||
|
if (state.allowRefSiblings && schema.description) {
|
||
|
temp.description = schema.description;
|
||
|
}
|
||
|
callback(temp,parent,state);
|
||
|
return temp; // all other properties SHALL be ignored
|
||
|
}
|
||
|
|
||
|
if (state.combine) {
|
||
|
if (schema.allOf && Array.isArray(schema.allOf) && schema.allOf.length === 1) {
|
||
|
schema = Object.assign({},schema.allOf[0],schema);
|
||
|
delete schema.allOf;
|
||
|
}
|
||
|
if (schema.anyOf && Array.isArray(schema.anyOf) && schema.anyOf.length === 1) {
|
||
|
schema = Object.assign({},schema.anyOf[0],schema);
|
||
|
delete schema.anyOf;
|
||
|
}
|
||
|
if (schema.oneOf && Array.isArray(schema.oneOf) && schema.oneOf.length === 1) {
|
||
|
schema = Object.assign({},schema.oneOf[0],schema);
|
||
|
delete schema.oneOf;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
callback(schema,parent,state);
|
||
|
if (state.seen.has(schema)) {
|
||
|
return schema;
|
||
|
}
|
||
|
//else
|
||
|
if ((typeof schema === 'object') && (schema !== null)) state.seen.set(schema,true);
|
||
|
state.top = false;
|
||
|
state.depth++;
|
||
|
|
||
|
if (typeof schema.items !== 'undefined') {
|
||
|
state.property = 'items';
|
||
|
walkSchema(schema.items,schema,state,callback);
|
||
|
}
|
||
|
if (schema.additionalItems) {
|
||
|
if (typeof schema.additionalItems === 'object') {
|
||
|
state.property = 'additionalItems';
|
||
|
walkSchema(schema.additionalItems,schema,state,callback);
|
||
|
}
|
||
|
}
|
||
|
if (schema.additionalProperties) {
|
||
|
if (typeof schema.additionalProperties === 'object') {
|
||
|
state.property = 'additionalProperties';
|
||
|
walkSchema(schema.additionalProperties,schema,state,callback);
|
||
|
}
|
||
|
}
|
||
|
if (schema.properties) {
|
||
|
for (let prop in schema.properties) {
|
||
|
let subSchema = schema.properties[prop];
|
||
|
state.property = 'properties/'+prop;
|
||
|
walkSchema(subSchema,schema,state,callback);
|
||
|
}
|
||
|
}
|
||
|
if (schema.patternProperties) {
|
||
|
for (let prop in schema.patternProperties) {
|
||
|
let subSchema = schema.patternProperties[prop];
|
||
|
state.property = 'patternProperties/'+prop;
|
||
|
walkSchema(subSchema,schema,state,callback);
|
||
|
}
|
||
|
}
|
||
|
if (schema.allOf) {
|
||
|
for (let index in schema.allOf) {
|
||
|
let subSchema = schema.allOf[index];
|
||
|
state.property = 'allOf/'+index;
|
||
|
walkSchema(subSchema,schema,state,callback);
|
||
|
}
|
||
|
}
|
||
|
if (schema.anyOf) {
|
||
|
for (let index in schema.anyOf) {
|
||
|
let subSchema = schema.anyOf[index];
|
||
|
state.property = 'anyOf/'+index;
|
||
|
walkSchema(subSchema,schema,state,callback);
|
||
|
}
|
||
|
}
|
||
|
if (schema.oneOf) {
|
||
|
for (let index in schema.oneOf) {
|
||
|
let subSchema = schema.oneOf[index];
|
||
|
state.property = 'oneOf/'+index;
|
||
|
walkSchema(subSchema,schema,state,callback);
|
||
|
}
|
||
|
}
|
||
|
if (schema.not) {
|
||
|
state.property = 'not';
|
||
|
walkSchema(schema.not,schema,state,callback);
|
||
|
}
|
||
|
state.depth--;
|
||
|
return schema;
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
getDefaultState: getDefaultState,
|
||
|
walkSchema: walkSchema
|
||
|
};
|
||
|
|