Merge pull request #3 from shelbys/PLATAPI-1912
add $ref and remove type for models
This commit is contained in:
commit
2158af9c82
|
@ -41,9 +41,10 @@ var classHelper = module.exports = {
|
||||||
* @return {Object} API declaration reference.
|
* @return {Object} API declaration reference.
|
||||||
*/
|
*/
|
||||||
generateResourceDocAPIEntry: function(aClass) {
|
generateResourceDocAPIEntry: function(aClass) {
|
||||||
|
var description = aClass.ctor.settings.description || aClass.ctor.sharedCtor && aClass.ctor.sharedCtor.description;
|
||||||
return {
|
return {
|
||||||
path: aClass.http.path,
|
path: aClass.http.path,
|
||||||
description: aClass.ctor.settings.description || aClass.ctor.sharedCtor && aClass.ctor.sharedCtor.description
|
description: Array.isArray(description) ? description.join('') : description
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
var _cloneDeep = require('lodash.clonedeep');
|
var _cloneDeep = require('lodash.clonedeep');
|
||||||
var translateDataTypeKeys = require('./translate-data-type-keys');
|
var translateDataTypeKeys = require('./translate-data-type-keys');
|
||||||
|
var TYPES_PRIMITIVE = ['array', 'boolean', 'integer', 'number', 'null', 'object', 'string', 'any'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export the modelHelper singleton.
|
* Export the modelHelper singleton.
|
||||||
|
@ -28,7 +29,14 @@ var modelHelper = module.exports = {
|
||||||
referencedModels.push(model);
|
referencedModels.push(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
var convertTypeTo$Ref = function convertTypeTo$Ref(prop){
|
||||||
|
if (prop.type && TYPES_PRIMITIVE.indexOf(prop.type) === -1 ){
|
||||||
|
prop.$ref = prop.type;
|
||||||
|
delete prop.type;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var def = modelClass.definition;
|
var def = modelClass.definition;
|
||||||
var name = def.name;
|
var name = def.name;
|
||||||
|
@ -73,6 +81,7 @@ var modelHelper = module.exports = {
|
||||||
processType(modelClass.app, prop.type, referencedModels);
|
processType(modelClass.app, prop.type, referencedModels);
|
||||||
if (prop.items) {
|
if (prop.items) {
|
||||||
processType(modelClass.app, prop.items.type, referencedModels);
|
processType(modelClass.app, prop.items.type, referencedModels);
|
||||||
|
convertTypeTo$Ref(prop.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required props sit in a per-model array.
|
// Required props sit in a per-model array.
|
||||||
|
@ -83,6 +92,15 @@ var modelHelper = module.exports = {
|
||||||
// Change mismatched keys.
|
// Change mismatched keys.
|
||||||
prop = translateDataTypeKeys(prop);
|
prop = translateDataTypeKeys(prop);
|
||||||
|
|
||||||
|
convertTypeTo$Ref(prop);
|
||||||
|
|
||||||
|
delete prop.required;
|
||||||
|
delete prop.id;
|
||||||
|
|
||||||
|
if (prop.description){
|
||||||
|
prop.description = Array.isArray(prop.description) ? prop.description.join('') : prop.description;
|
||||||
|
}
|
||||||
|
|
||||||
// Assign this back to the properties object.
|
// Assign this back to the properties object.
|
||||||
properties[key] = prop;
|
properties[key] = prop;
|
||||||
|
|
||||||
|
@ -102,13 +120,25 @@ var modelHelper = module.exports = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var additionalProperties = undefined;
|
||||||
|
if (def.settings){
|
||||||
|
var strict = def.settings.strict;
|
||||||
|
additionalProperties = def.settings.additionalProperties;
|
||||||
|
var notAllowAdditionalProperties = strict || (additionalProperties !== true);
|
||||||
|
if (notAllowAdditionalProperties){
|
||||||
|
additionalProperties = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out[name] = {
|
out[name] = {
|
||||||
id: name,
|
id: name,
|
||||||
|
additionalProperties: additionalProperties,
|
||||||
properties: properties,
|
properties: properties,
|
||||||
required: required
|
required: required
|
||||||
};
|
};
|
||||||
if (def.settings && typeof def.settings.additionalProperties != 'undefined') {
|
|
||||||
out[name].additionalProperties = def.settings.additionalProperties;
|
if (def.description){
|
||||||
|
out[name].description = Array.isArray(def.description) ? def.description.join('') : def.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate model definitions for related models
|
// Generate model definitions for related models
|
||||||
|
@ -215,7 +245,4 @@ var modelHelper = module.exports = {
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -191,8 +191,8 @@ var routeHelper = module.exports = {
|
||||||
nickname: route.method.replace(/\./g, '_'),
|
nickname: route.method.replace(/\./g, '_'),
|
||||||
deprecated: route.deprecated,
|
deprecated: route.deprecated,
|
||||||
type: returns.model || returns.type || 'void',
|
type: returns.model || returns.type || 'void',
|
||||||
summary: route.description, // TODO(schoon) - Excerpt?
|
summary: Array.isArray(route.description) ? route.description.join('') : route.description, // TODO(schoon) - Excerpt?
|
||||||
notes: route.notes, // TODO(schoon) - `description` metadata?
|
notes: Array.isArray(route.notes) ? route.notes.join('') : route.notes, // TODO(schoon) - `description` metadata?
|
||||||
consumes: ['application/json', 'application/xml', 'text/xml'],
|
consumes: ['application/json', 'application/xml', 'text/xml'],
|
||||||
produces: ['application/json', 'application/javascript', 'application/xml', 'text/javascript', 'text/xml'],
|
produces: ['application/json', 'application/javascript', 'application/xml', 'text/javascript', 'text/xml'],
|
||||||
parameters: accepts,
|
parameters: accepts,
|
||||||
|
@ -264,7 +264,7 @@ var routeHelper = module.exports = {
|
||||||
minimum: accepts.minimum,
|
minimum: accepts.minimum,
|
||||||
maximum: accepts.maximum,
|
maximum: accepts.maximum,
|
||||||
allowMultiple: accepts.allowMultiple,
|
allowMultiple: accepts.allowMultiple,
|
||||||
description: accepts.description
|
description: Array.isArray(accepts.description) ? accepts.description.join('') : accepts.description
|
||||||
};
|
};
|
||||||
|
|
||||||
out = routeHelper.extendWithType(out);
|
out = routeHelper.extendWithType(out);
|
||||||
|
|
|
@ -12,6 +12,7 @@ var urlJoin = require('./url-join');
|
||||||
var _defaults = require('lodash.defaults');
|
var _defaults = require('lodash.defaults');
|
||||||
var classHelper = require('./class-helper');
|
var classHelper = require('./class-helper');
|
||||||
var routeHelper = require('./route-helper');
|
var routeHelper = require('./route-helper');
|
||||||
|
var _cloneDeep = require('lodash.clonedeep');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a remotable Swagger module for plugging into `RemoteObjects`.
|
* Create a remotable Swagger module for plugging into `RemoteObjects`.
|
||||||
|
@ -129,11 +130,17 @@ function addRoute(app, uri, doc, opts) {
|
||||||
* @return {Object} Resource doc.
|
* @return {Object} Resource doc.
|
||||||
*/
|
*/
|
||||||
function generateResourceDoc(opts) {
|
function generateResourceDoc(opts) {
|
||||||
|
var apiInfo = _cloneDeep(opts.apiInfo);
|
||||||
|
for (var propertyName in apiInfo) {
|
||||||
|
var property = apiInfo[propertyName];
|
||||||
|
apiInfo[propertyName] = Array.isArray(property) ? property.join('') : property;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
swaggerVersion: opts.swaggerVersion,
|
swaggerVersion: opts.swaggerVersion,
|
||||||
apiVersion: opts.version,
|
apiVersion: opts.version,
|
||||||
// See https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#513-info-object
|
// See https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#513-info-object
|
||||||
info: opts.apiInfo,
|
info: apiInfo,
|
||||||
// TODO Authorizations
|
// TODO Authorizations
|
||||||
// https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#514-authorizations-object
|
// https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#514-authorizations-object
|
||||||
consumes: ['application/json', 'application/xml', 'text/xml'],
|
consumes: ['application/json', 'application/xml', 'text/xml'],
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "loopback-explorer",
|
"name": "loopback-explorer",
|
||||||
"version": "1.2.12",
|
"version": "1.2.13",
|
||||||
"description": "Browse and test your LoopBack app's APIs",
|
"description": "Browse and test your LoopBack app's APIs",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* Created by ytang on 4/7/15.
|
||||||
|
*/
|
||||||
|
var classHelper = require('../lib/class-helper');
|
||||||
|
var loopback = require('loopback');
|
||||||
|
var expect = require('chai').expect;
|
||||||
|
|
||||||
|
describe('class-helper', function() {
|
||||||
|
describe('#generateResourceDocAPIEntry', function() {
|
||||||
|
describe('when ctor.settings.description is an array of string', function() {
|
||||||
|
it('should return description as a string', function() {
|
||||||
|
var aClass = {
|
||||||
|
ctor: {
|
||||||
|
settings: {
|
||||||
|
description: ['1','2','3']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
http:{
|
||||||
|
path: 'path'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = classHelper.generateResourceDocAPIEntry(aClass);
|
||||||
|
expect(result.description).to.eql('123');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when ctor.sharedCtor.description is an array of string', function() {
|
||||||
|
it('should return description as a string', function() {
|
||||||
|
var aClass = {
|
||||||
|
ctor: {
|
||||||
|
settings: {},
|
||||||
|
sharedCtor: {
|
||||||
|
description: ['1','2','3']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
http:{
|
||||||
|
path: 'path'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = classHelper.generateResourceDocAPIEntry(aClass);
|
||||||
|
expect(result.description).to.eql('123');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -111,14 +111,14 @@ describe('model-helper', function() {
|
||||||
expect(prop).to.eql({ type: 'array', items: { type: 'any' } });
|
expect(prop).to.eql({ type: 'array', items: { type: 'any' } });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts Model type', function() {
|
it('converts Model type to $ref', function() {
|
||||||
var Address = loopback.createModel('Address', {street: String});
|
var Address = loopback.createModel('Address', {street: String});
|
||||||
var def = buildSwaggerModels({
|
var def = buildSwaggerModels({
|
||||||
str: String,
|
str: String,
|
||||||
address: Address
|
address: Address
|
||||||
});
|
});
|
||||||
var prop = def.properties.address;
|
var prop = def.properties.address;
|
||||||
expect(prop).to.eql({ type: 'Address' });
|
expect(prop).to.eql({ $ref: 'Address' });
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -192,6 +192,36 @@ describe('model-helper', function() {
|
||||||
expect(def.properties).to.have.property('visibleProperty');
|
expect(def.properties).to.have.property('visibleProperty');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#generateModelDefinition', function(){
|
||||||
|
it('should convert top level array description to string', function(){
|
||||||
|
var model = {};
|
||||||
|
model.definition = {
|
||||||
|
name: 'test',
|
||||||
|
description: ['1','2','3'],
|
||||||
|
properties: {}
|
||||||
|
};
|
||||||
|
var models = {};
|
||||||
|
modelHelper.generateModelDefinition(model, models);
|
||||||
|
expect(models.test.description).to.equal('123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert property level array description to string', function(){
|
||||||
|
var model = {};
|
||||||
|
model.definition = {
|
||||||
|
name: 'test',
|
||||||
|
properties: {
|
||||||
|
prop1: {
|
||||||
|
type: 'string',
|
||||||
|
description: ['1','2','3']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var models = {};
|
||||||
|
modelHelper.generateModelDefinition(model, models);
|
||||||
|
expect(models.test.properties.prop1.description).to.equal('123');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Simulates the format of a remoting class.
|
// Simulates the format of a remoting class.
|
||||||
|
|
|
@ -73,6 +73,35 @@ describe('route-helper', function() {
|
||||||
expect(opDoc.responseMessages[0].responseModel).to.equal('string');
|
expect(opDoc.responseMessages[0].responseModel).to.equal('string');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#acceptToParameter', function(){
|
||||||
|
it('should return function that converts accepts.description from array of string to string', function(){
|
||||||
|
var f = routeHelper.acceptToParameter({verb: 'get', path: 'path'});
|
||||||
|
var result = f({description: ['1','2','3']});
|
||||||
|
expect(result.description).to.eql('123');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#routeToAPIDoc', function(){
|
||||||
|
it('should convert route.description from array fo string to string', function(){
|
||||||
|
var result = routeHelper.routeToAPIDoc({
|
||||||
|
method: 'someMethod',
|
||||||
|
verb: 'get',
|
||||||
|
path: 'path',
|
||||||
|
description:['1','2','3']
|
||||||
|
});
|
||||||
|
expect(result.operations[0].summary).to.eql('123');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert route.notes from array fo string to string', function(){
|
||||||
|
var result = routeHelper.routeToAPIDoc({
|
||||||
|
method: 'someMethod',
|
||||||
|
verb: 'get',
|
||||||
|
path: 'path',
|
||||||
|
notes:['1','2','3']
|
||||||
|
});
|
||||||
|
expect(result.operations[0].notes).to.eql('123');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Easy wrapper around createRoute
|
// Easy wrapper around createRoute
|
||||||
|
|
Loading…
Reference in New Issue