UNPKG

loopback-swagger

Version:

Integration between LoopBack and Swagger API specs

179 lines (167 loc) 4.98 kB
// Copyright IBM Corp. 2015,2019. All Rights Reserved. // Node module: loopback-swagger // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT 'use strict'; function getRef(obj) { return (obj != null && typeof obj === 'object') && (obj.$ref || obj.$REF); } function resolveTypeRef(schema, ref) { if (typeof ref === 'string') { if (ref.indexOf('#/definitions/') === 0) { ref = ref.substring('#/definitions/'.length); } if (ref.indexOf('#/models/') === 0) { ref = ref.substring('#/models/'.length); } var model = schema[ref]; if (model) { if (model.type === 'object' || !model.type) { return ref; } if (model.type === 'array') { var itemType = model.items.type; if (getRef(model.items)) { itemType = resolveTypeRef(schema, getRef(model.items)); } return [itemType]; } else { return model.type; } } } return ref; } /** * Build a LoopBack property definition from the JSON model * @param {Object} schema JSON Schema * @param {Object} jsonModel The json model definition * @param {String} propertyName The property name * @returns {Object} */ function buildProperty(schema, jsonModel, propertyName) { var jsonProperty = jsonModel.properties[propertyName]; var property = {}; var type = jsonProperty.type; if (getRef(jsonProperty)) { type = resolveTypeRef(schema, getRef(jsonProperty)); } if (type === 'array' && jsonProperty.items) { var itemType = jsonProperty.items.type; if (getRef(jsonProperty.items)) { itemType = resolveTypeRef(schema, getRef(jsonProperty.items)); } type = [itemType]; } if (type === 'integer') { type = 'number'; } property.type = type; if (Array.isArray(jsonModel.required) && jsonModel.required.indexOf(propertyName) !== -1) { property.required = true; } for (var a in jsonProperty) { if (a === '$ref' || a === '$REF' || a === 'items' || (a in property)) { continue; } property[a] = jsonProperty[a]; } return property; } function buildModel(models, schema, jsonModel, modelName, anonymous) { if (models[modelName]) { return models[modelName]; } if (jsonModel.type && jsonModel.type !== 'object') { // The model is either an array or primitive type return; } var model = {name: modelName, properties: {}}; var base, prop; // Handle allOf if (Array.isArray(jsonModel.allOf)) { var refs = []; var required = []; /* eslint-disable one-var */ for (var i = 0, n = jsonModel.allOf.length; i < n; i++) { var item = jsonModel.allOf[i]; if (Array.isArray(item.required)) { required = required.concat(item.required); } var itemModel; if (getRef(item)) { // Extract model name from reference object base = models[getRef(item).substring('#/definitions/'.length)] || base; refs.push(base); } else { // Build the embedded model itemModel = buildModel(models, schema, item, modelName + '_' + i, true); } if (itemModel) { // Add more item model properties to the model for (prop in itemModel.properties) { model.properties[prop] = itemModel.properties[prop]; } } } /* eslint-enable one-var */ if (refs.length === 1) { // Set the referenced model as the base model.base = (base && base.name) || base; } else { // Mix in all properties from the referenced models for (i = 0, n = refs.length; i < n; i++) { // Add more item model properties to the model for (prop in refs[i].properties) { model.properties[prop] = refs[i].properties[prop]; } } } for (prop in model.properties) { if (required.indexOf(prop) !== -1) { model.properties[prop].required = true; } } } if (jsonModel['x-base-type']) { model.base = jsonModel['x-base-type']; } /* eslint-disable one-var */ for (var p in jsonModel.properties) { var property = buildProperty(schema, jsonModel, p); model.properties[p] = property; } if (typeof jsonModel['x-relations'] === 'object') { model.relations = {}; for (var r in jsonModel['x-relations']) { var rel = jsonModel['x-relations'][r]; if (rel.partner && getRef(rel.partner)) { rel.model = resolveTypeRef(schema, getRef(rel.partner)); delete rel.partner; } model.relations[r] = rel; } } /* eslint-enable one-var */ if (!anonymous) { models[modelName] = model; } return model; } /** * Convert the JSON-schema to LoopBack model definitions * @param {Object} schema */ module.exports = function(schema) { var models = {}; if (!schema) { return models; } for (var m in schema) { var jsonModel = schema[m]; buildModel(models, schema, jsonModel, m); } return models; };