Merge pull request #1700 from strongloop/3x/type-sub-property

feat: Support "type" key in sub-properties in 3.x
This commit is contained in:
Hage Yaapa 2019-03-19 19:04:39 +05:30 committed by GitHub
commit 16ffd42c94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 18 deletions

View File

@ -849,47 +849,46 @@ ModelBuilder.prototype.getSchemaName = function(name) {
/** /**
* Resolve the type string to be a function, for example, 'String' to String. * Resolve the type string to be a function, for example, 'String' to String.
* Returns {Function} if the type is resolved * Returns {Function} if the type is resolved
* @param {String} type The type string, such as 'number', 'Number', 'boolean', * @param {String | Object | Array} prop The object whose type is to be resolved
* or 'String'. This parameter is case insensitive.
*/ */
ModelBuilder.prototype.resolveType = function(type) { ModelBuilder.prototype.resolveType = function(prop, isSubProperty) {
if (!type) { if (!prop) {
return type; return prop;
} }
if (Array.isArray(type) && type.length > 0) { if (Array.isArray(prop) && prop.length > 0) {
// For array types, the first item should be the type string // For array types, the first item should be the type string
const itemType = this.resolveType(type[0]); const itemType = this.resolveType(prop[0]);
if (typeof itemType === 'function') { if (typeof itemType === 'function') {
return [itemType]; return [itemType];
} else { } else {
return itemType; // Not resolved, return the type string return itemType; // Not resolved, return the type string
} }
} }
if (typeof type === 'string') { if (typeof prop === 'string') {
const schemaType = ModelBuilder.schemaTypes[type.toLowerCase()] || this.models[type]; const schemaType = ModelBuilder.schemaTypes[prop.toLowerCase()] || this.models[prop];
if (schemaType) { if (schemaType) {
return schemaType; return schemaType;
} else { } else {
// The type cannot be resolved, let's create a place holder // The type cannot be resolved, let's create a place holder
type = this.define(type, {}, {unresolved: true}); prop = this.define(prop, {}, {unresolved: true});
return type; return prop;
} }
} else if (type.constructor.name === 'Object') { } else if (prop.constructor.name === 'Object') {
// We also support the syntax {type: 'string', ...} // We also support the syntax {type: 'string', ...}
if (type.type) { if (!isSubProperty && prop.type) {
return this.resolveType(type.type); return this.resolveType(prop.type, true);
} else { } else {
return this.define(this.getSchemaName(null), return this.define(this.getSchemaName(null),
type, { prop, {
anonymous: true, anonymous: true,
idInjection: false, idInjection: false,
strict: this.settings.strictEmbeddedModels || false, strict: this.settings.strictEmbeddedModels || false,
}); });
} }
} else if ('function' === typeof type) { } else if ('function' === typeof prop) {
return type; return prop;
} }
return type; return prop;
}; };
/** /**

View File

@ -28,6 +28,24 @@ describe('datatypes', function() {
db.automigrate(['Model'], done); db.automigrate(['Model'], done);
}); });
it('should resolve top-level "type" property correctly', function() {
const Account = db.define('Account', {
type: String,
id: String,
});
Account.definition.properties.type.type.should.equal(String);
});
it('should resolve "type" sub-property correctly', function() {
const Account = db.define('Account', {
item: {type: {
itemname: {type: String},
type: {type: String},
}},
});
Account.definition.properties.item.type.should.not.equal(String);
});
it('should return 400 when property of type array is set to string value', it('should return 400 when property of type array is set to string value',
function(done) { function(done) {
const myModel = db.define('myModel', { const myModel = db.define('myModel', {