diff --git a/lib/model-builder.js b/lib/model-builder.js index cd831f43..55983370 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -849,47 +849,46 @@ ModelBuilder.prototype.getSchemaName = function(name) { /** * Resolve the type string to be a function, for example, 'String' to String. * Returns {Function} if the type is resolved - * @param {String} type The type string, such as 'number', 'Number', 'boolean', - * or 'String'. This parameter is case insensitive. + * @param {String | Object | Array} prop The object whose type is to be resolved */ -ModelBuilder.prototype.resolveType = function(type) { - if (!type) { - return type; +ModelBuilder.prototype.resolveType = function(prop, isSubProperty) { + if (!prop) { + 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 - const itemType = this.resolveType(type[0]); + const itemType = this.resolveType(prop[0]); if (typeof itemType === 'function') { return [itemType]; } else { return itemType; // Not resolved, return the type string } } - if (typeof type === 'string') { - const schemaType = ModelBuilder.schemaTypes[type.toLowerCase()] || this.models[type]; + if (typeof prop === 'string') { + const schemaType = ModelBuilder.schemaTypes[prop.toLowerCase()] || this.models[prop]; if (schemaType) { return schemaType; } else { // The type cannot be resolved, let's create a place holder - type = this.define(type, {}, {unresolved: true}); - return type; + prop = this.define(prop, {}, {unresolved: true}); + return prop; } - } else if (type.constructor.name === 'Object') { + } else if (prop.constructor.name === 'Object') { // We also support the syntax {type: 'string', ...} - if (type.type) { - return this.resolveType(type.type); + if (!isSubProperty && prop.type) { + return this.resolveType(prop.type, true); } else { return this.define(this.getSchemaName(null), - type, { + prop, { anonymous: true, idInjection: false, strict: this.settings.strictEmbeddedModels || false, }); } - } else if ('function' === typeof type) { - return type; + } else if ('function' === typeof prop) { + return prop; } - return type; + return prop; }; /** diff --git a/test/datatype.test.js b/test/datatype.test.js index ee069191..aab8166c 100644 --- a/test/datatype.test.js +++ b/test/datatype.test.js @@ -28,6 +28,24 @@ describe('datatypes', function() { 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', function(done) { const myModel = db.define('myModel', {