Merge pull request #3 from shelbys/PLATAPI-1912

add $ref and remove type for models
This commit is contained in:
y-tang 2015-04-13 09:42:31 -07:00
commit 2158af9c82
8 changed files with 156 additions and 15 deletions

View File

@ -41,9 +41,10 @@ var classHelper = module.exports = {
* @return {Object} API declaration reference.
*/
generateResourceDocAPIEntry: function(aClass) {
var description = aClass.ctor.settings.description || aClass.ctor.sharedCtor && aClass.ctor.sharedCtor.description;
return {
path: aClass.http.path,
description: aClass.ctor.settings.description || aClass.ctor.sharedCtor && aClass.ctor.sharedCtor.description
description: Array.isArray(description) ? description.join('') : description
};
}
};

View File

@ -5,6 +5,7 @@
*/
var _cloneDeep = require('lodash.clonedeep');
var translateDataTypeKeys = require('./translate-data-type-keys');
var TYPES_PRIMITIVE = ['array', 'boolean', 'integer', 'number', 'null', 'object', 'string', 'any'];
/**
* Export the modelHelper singleton.
@ -28,7 +29,14 @@ var modelHelper = module.exports = {
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 name = def.name;
@ -73,6 +81,7 @@ var modelHelper = module.exports = {
processType(modelClass.app, prop.type, referencedModels);
if (prop.items) {
processType(modelClass.app, prop.items.type, referencedModels);
convertTypeTo$Ref(prop.items);
}
// Required props sit in a per-model array.
@ -83,6 +92,15 @@ var modelHelper = module.exports = {
// Change mismatched keys.
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.
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] = {
id: name,
additionalProperties: additionalProperties,
properties: properties,
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
@ -216,6 +246,3 @@ var modelHelper = module.exports = {
return out;
}
};

View File

@ -191,8 +191,8 @@ var routeHelper = module.exports = {
nickname: route.method.replace(/\./g, '_'),
deprecated: route.deprecated,
type: returns.model || returns.type || 'void',
summary: route.description, // TODO(schoon) - Excerpt?
notes: route.notes, // TODO(schoon) - `description` metadata?
summary: Array.isArray(route.description) ? route.description.join('') : route.description, // TODO(schoon) - Excerpt?
notes: Array.isArray(route.notes) ? route.notes.join('') : route.notes, // TODO(schoon) - `description` metadata?
consumes: ['application/json', 'application/xml', 'text/xml'],
produces: ['application/json', 'application/javascript', 'application/xml', 'text/javascript', 'text/xml'],
parameters: accepts,
@ -264,7 +264,7 @@ var routeHelper = module.exports = {
minimum: accepts.minimum,
maximum: accepts.maximum,
allowMultiple: accepts.allowMultiple,
description: accepts.description
description: Array.isArray(accepts.description) ? accepts.description.join('') : accepts.description
};
out = routeHelper.extendWithType(out);

View File

@ -12,6 +12,7 @@ var urlJoin = require('./url-join');
var _defaults = require('lodash.defaults');
var classHelper = require('./class-helper');
var routeHelper = require('./route-helper');
var _cloneDeep = require('lodash.clonedeep');
/**
* Create a remotable Swagger module for plugging into `RemoteObjects`.
@ -129,11 +130,17 @@ function addRoute(app, uri, doc, opts) {
* @return {Object} Resource doc.
*/
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 {
swaggerVersion: opts.swaggerVersion,
apiVersion: opts.version,
// See https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#513-info-object
info: opts.apiInfo,
info: apiInfo,
// TODO Authorizations
// https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#514-authorizations-object
consumes: ['application/json', 'application/xml', 'text/xml'],

View File

@ -1,6 +1,6 @@
{
"name": "loopback-explorer",
"version": "1.2.12",
"version": "1.2.13",
"description": "Browse and test your LoopBack app's APIs",
"main": "index.js",
"scripts": {

47
test/class-helper.test.js Normal file
View File

@ -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');
});
});
});
});

View File

@ -111,14 +111,14 @@ describe('model-helper', function() {
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 def = buildSwaggerModels({
str: String,
address: 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');
});
});
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.

View File

@ -73,6 +73,35 @@ describe('route-helper', function() {
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