diff --git a/lib/connector.js b/lib/connector.js index efb3843d..86f0998c 100644 --- a/lib/connector.js +++ b/lib/connector.js @@ -17,6 +17,42 @@ function Connector(name, settings) { */ Connector.prototype.relational = false; +/** + * Get types associated with the connector + * @returns {String[]} The types for the connector + */ +Connector.prototype.getTypes = function() { + return ['db', 'nosql']; +}; + +/** + * Get the default data type for ID + * @returns {Function} The default type for ID + */ +Connector.prototype.getDefaultIdType = function() { + return String; +}; + +/** + * Get the metadata for the connector + * @returns {Object} The metadata object + * @property {String} type The type for the backend + * @property {Function} defaultIdType The default id type + * @property {Boolean} [isRelational] If the connector represents a relational database + * @property {Object} schemaForSettings The schema for settings object + */ +Connector.prototype.getMedadata = function () { + if (!this._metadata) { + this._metadata = { + types: this.getTypes(), + defaultIdType: this.getDefaultIdType(), + isRelational: this.isRelational || (this.getTypes().indexOf('rdbms') !== -1), + schemaForSettings: {} + }; + } + return this._metadata; +}; + /** * Execute a command with given parameters * @param {String} command The command such as SQL diff --git a/lib/connectors/memory.js b/lib/connectors/memory.js index 7c337d43..1184ac44 100644 --- a/lib/connectors/memory.js +++ b/lib/connectors/memory.js @@ -35,6 +35,14 @@ function Memory(m, settings) { util.inherits(Memory, Connector); +Memory.prototype.getDefaultIdType = function() { + return Number; +}; + +Memory.prototype.getTypes = function() { + return ['db', 'nosql', 'memory']; +}; + Memory.prototype.connect = function (callback) { if (this.isTransaction) { this.onTransactionExec = callback; diff --git a/lib/datasource.js b/lib/datasource.js index 8f11368c..9ced62d8 100644 --- a/lib/datasource.js +++ b/lib/datasource.js @@ -424,17 +424,27 @@ DataSource.prototype.defineRelations = function (modelClass, relations) { /*! * Set up the data access functions from the data source - * @param modelClass - * @param settings + * @param {Model} modelClass The model class + * @param {Object} settings The settings object */ DataSource.prototype.setupDataAccess = function (modelClass, settings) { - if (this.connector && this.connector.define) { - // pass control to connector - this.connector.define({ - model: modelClass, - properties: modelClass.definition.properties, - settings: settings - }); + if (this.connector) { + // Check if the id property should be generated + var idName = modelClass.definition.idName(); + var idProp = modelClass.definition.properties[idName]; + if(idProp && idProp.generated && this.connector.getDefaultIdType) { + // Set the default id type from connector's ability + var idType = this.connector.getDefaultIdType() || String; + idProp.type = idType; + } + if (this.connector.define) { + // pass control to connector + this.connector.define({ + model: modelClass, + properties: modelClass.definition.properties, + settings: settings + }); + } } // add data access objects @@ -559,14 +569,55 @@ DataSource.prototype.mixin = function (ModelCtor) { }); }; +/** + * @see ModelBuilder.prototype.getModel + */ DataSource.prototype.getModel = function (name, forceCreate) { return this.modelBuilder.getModel(name, forceCreate); }; +/** + * @see ModelBuilder.prototype.getModelDefinition + */ DataSource.prototype.getModelDefinition = function (name) { return this.modelBuilder.getModelDefinition(name); }; +/** + * Get the data source types + * @returns {String[]} The data source type, such as ['db', 'nosql', 'mongodb'], + * ['rest'], or ['db', 'rdbms', 'mysql'] + */ +DataSource.prototype.getTypes = function () { + var types = this.connector && this.connector.getTypes() || []; + if (typeof types === 'string') { + types = types.split(/[\s,\/]+/); + } + return types; +}; + +/** + * Check the data source supports the given types + * @param String|String[]) types A type name or an array of type names + * @return {Boolean} true if all types are supported by the data source + */ +DataSource.prototype.supportTypes = function (types) { + var supportedTypes = this.getTypes(); + if (Array.isArray(types)) { + // Check each of the types + for (var i = 0; i < types.length; i++) { + if (supportedTypes.indexOf(types[i]) === -1) { + // Not supported + return false; + } + } + return true; + } else { + // The types is a string + return supportedTypes.indexOf(types) !== -1; + } +}; + /** * Attach an existing model to a data source. * diff --git a/lib/model-builder.js b/lib/model-builder.js index ab8aa1b2..03bbcc91 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -71,6 +71,11 @@ ModelBuilder.prototype.getModel = function (name, forceCreate) { return model; }; +/** + * Get the model definition by name + * @param {String} name The model name + * @returns {ModelDefinition} The model definition + */ ModelBuilder.prototype.getModelDefinition = function (name) { return this.definitions[name]; }; diff --git a/lib/sql.js b/lib/sql.js index b3b5c664..3f32882b 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -19,6 +19,22 @@ util.inherits(BaseSQL, Connector); */ BaseSQL.prototype.relational = true; +/** + * Get types associated with the connector + * @returns {String[]} The types for the connector + */ + BaseSQL.prototype.getTypes = function() { + return ['db', 'rdbms', 'sql']; +}; + +/*! + * Get the default data type for ID + * @returns {Function} + */ +BaseSQL.prototype.getDefaultIdType = function() { + return Number; +}; + BaseSQL.prototype.query = function () { throw new Error('query method should be declared in connector'); }; diff --git a/test/loopback-dl.test.js b/test/loopback-dl.test.js index 205ee4e1..0f49514f 100644 --- a/test/loopback-dl.test.js +++ b/test/loopback-dl.test.js @@ -416,6 +416,40 @@ describe('DataSource define model', function () { }); }); + it('injects id by default', function (done) { + var ds = new ModelBuilder(); + + var User = ds.define('User', {}); + assert.deepEqual(User.definition.properties.id, + {type: Number, id: 1, generated: true}); + + done(); + }); + + it('disables idInjection if the value is false', function (done) { + var ds = new ModelBuilder(); + + var User1 = ds.define('User', {}, {idInjection: false}); + assert(!User1.definition.properties.id); + done(); + }); + + it('updates generated id type by the connector', function (done) { + var builder = new ModelBuilder(); + + var User = builder.define('User', {id: {type: String, generated: true, id: true}}); + assert.deepEqual(User.definition.properties.id, + {type: String, id: 1, generated: true}); + + var ds = new DataSource('memory');// define models + User.attachTo(ds); + + assert.deepEqual(User.definition.properties.id, + {type: Number, id: 1, generated: true}); + + done(); + }); + }); describe('Load models with base', function () { @@ -445,6 +479,42 @@ describe('Load models with base', function () { }); }); +describe('DataSource connector types', function() { + it('should return an array of types', function() { + var ds = new DataSource('memory'); + var types = ds.getTypes(); + assert.deepEqual(types, ['db', 'nosql', 'memory']); + }); + + it('should test supported types by string', function() { + var ds = new DataSource('memory'); + var result = ds.supportTypes('db'); + assert(result); + }); + + it('should test supported types by array', function() { + var ds = new DataSource('memory'); + var result = ds.supportTypes(['db', 'memory']); + assert(result); + }); + + it('should test unsupported types by string', function() { + var ds = new DataSource('memory'); + var result = ds.supportTypes('rdbms'); + assert(!result); + }); + + it('should test unsupported types by array', function() { + var ds = new DataSource('memory'); + var result = ds.supportTypes(['rdbms', 'memory']); + assert(!result); + + result = ds.supportTypes(['rdbms']); + assert(!result); + }); + +}); + describe('DataSource constructor', function () { // Mocked require var loader = function (name) {