diff --git a/docs.json b/docs.json new file mode 100644 index 00000000..f73a8684 --- /dev/null +++ b/docs.json @@ -0,0 +1,46 @@ +{ + "content": [ + "README.md", + "docs/loopback-datasource-juggler.md", + "docs/connector.md", + "docs/data-source.md", + { + "title": "LoopBack DataSource API", + "depth": 2 + }, + { + "title": "Model and types", + "depth": 3 + }, + + + "lib/model-builder.js", + "lib/types.js", + "lib/geo.js", + "lib/model.js", + + { + "title": "DataSource", + "depth": 3 + }, + "lib/datasource.js", + + { + "title": "Data access mixins", + "depth": 3 + }, + "lib/dao.js", + "lib/hooks.js", + "lib/include.js", + "lib/relations.js", + "lib/validations.js", + + { + "title": "Base class for SQL connectors", + "depth": 3 + }, + "lib/sql.js" + ], + "codeSectionDepth": 4 +} + diff --git a/lib/dao.js b/lib/dao.js index 2cc873c0..02be7813 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -193,7 +193,9 @@ function setIdValue(m, data, value) { } /** - * Update or insert + * Update or insert a model instance + * @param {Object} data The model instance data + * @param {Function} [callback] The callback function */ DataAccessObject.upsert = DataAccessObject.updateOrCreate = function upsert(data, callback) { if (stillConnecting(this.dataSource, this, arguments)) return; @@ -277,7 +279,7 @@ DataAccessObject.exists.returns = {arg: 'exists', type: 'any'}; /** * Find object by id * - * @param {id} id - primary key value + * @param {*} id - primary key value * @param {Function} cb - callback called with (err, instance) */ DataAccessObject.findById = function find(id, cb) { @@ -462,7 +464,8 @@ DataAccessObject.destroyAll = function destroyAll(cb) { }; /** - * Destroy all records + * Destroy a record by id + * @param {*} id The id value * @param {Function} cb - callback called with (err) */ DataAccessObject.deleteById = diff --git a/lib/model-builder.js b/lib/model-builder.js index f205648c..a8503607 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -3,7 +3,7 @@ */ var i8n = require('inflection'); -var ModelBaseClass = require('./model.js'); +var DefaultModelBaseClass = require('./model.js'); var List = require('./list.js'); var EventEmitter = require('events').EventEmitter; var util = require('util'); @@ -18,8 +18,6 @@ var introspect = require('./introspection')(ModelBuilder); */ exports.Schema = exports.ModelBuilder = ModelBuilder; -// exports.ModelBaseClass = ModelBaseClass; - /** * Helpers */ @@ -32,7 +30,7 @@ function ModelBuilder() { // create blank models pool this.models = {}; this.definitions = {}; -}; +} util.inherits(ModelBuilder, EventEmitter); @@ -71,11 +69,19 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett var dataSource = this; var args = slice.call(arguments); var pluralName = settings && settings.plural; - var ModelBaseClass = parent || require('./model.js'); + var ModelBaseClass = parent || DefaultModelBaseClass; - if (!className) throw new Error('Class name required'); - if (args.length == 1) properties = {}, args.push(properties); - if (args.length == 2) settings = {}, args.push(settings); + if (!className) { + throw new Error('Class name required'); + } + if (args.length === 1) { + properties = {}; + args.push(properties); + } + if (args.length === 2) { + settings = {}; + args.push(settings); + } properties = properties || {}; settings = settings || {}; @@ -161,7 +167,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett ModelClass.attachTo = function (dataSource) { dataSource.attach(this); - } + }; ModelClass.extend = function (className, p, s) { p = p || {}; @@ -188,7 +194,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett } return c; - } + }; ModelClass.registerProperty = function (attr) { var prop = properties[attr]; @@ -431,7 +437,7 @@ ModelBuilder.prototype.getSchemaType = function(type) { return type; } return type; -} +}; /** * Build a dataSource @@ -467,7 +473,7 @@ ModelBuilder.prototype.buildSchema = function(name, properties, associations) { } } return properties; -} +}; /** @@ -516,13 +522,13 @@ ModelBuilder.prototype.buildModels = function (schemas) { } } return models; -} +}; /** * Introspect the json document to build a corresponding model - * @param name - * @param json - * @param options + * @param {String} name + * @param {Object} json + * @param [Object} options * @returns {} */ ModelBuilder.prototype.buildModelFromInstance = function(name, json, options) { diff --git a/lib/sql.js b/lib/sql.js index fdd932db..a4d32dd1 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -1,19 +1,24 @@ module.exports = BaseSQL; /** - * Base SQL class + * Base class for connectors that are backed by relational databases/SQL + * @constructor */ function BaseSQL() { } +/** + * Set the relational property to indicate the backend is a relational DB + * @type {boolean} + */ BaseSQL.prototype.relational = true; BaseSQL.prototype.query = function () { throw new Error('query method should be declared in connector'); }; -BaseSQL.prototype.command = function (sql, callback) { - return this.query(sql, callback); +BaseSQL.prototype.command = function (sql, params, callback) { + return this.query(sql, params, callback); }; BaseSQL.prototype.queryOne = function (sql, callback) { @@ -25,7 +30,7 @@ BaseSQL.prototype.queryOne = function (sql, callback) { /** * Look up the data source by model name - * @param model The model name + * @param {String} model The model name * @returns {DataSource} The data source */ BaseSQL.prototype.getDataSource = function(model) { @@ -38,7 +43,7 @@ BaseSQL.prototype.getDataSource = function(model) { /** * Get the table name for a given model - * @param model The model name + * @param {String} model The model name * @returns {String} The table name */ BaseSQL.prototype.table = function (model) { @@ -52,8 +57,8 @@ BaseSQL.prototype.table = function (model) { /** * Get the column name for given model property - * @param model The model name - * @param property The property name + * @param {String} model The model name + * @param {String} property The property name * @returns {String} The column name */ BaseSQL.prototype.column = function (model, property) { @@ -67,8 +72,8 @@ BaseSQL.prototype.column = function (model, property) { /** * Get the column name for given model property - * @param model The model name - * @param property The property name + * @param {String} model The model name + * @param {String} property The property name * @returns {Object} The column metadata */ BaseSQL.prototype.columnMetadata = function (model, property) { @@ -77,9 +82,9 @@ BaseSQL.prototype.columnMetadata = function (model, property) { /** * Get the corresponding property name for a given column name - * @param model The model name - * @param column The column name - * @returns {*} + * @param {String} model The model name + * @param {String} column The column name + * @returns {String} The property name for a given column */ BaseSQL.prototype.propertyName = function (model, column) { var props = this._models[model].properties; @@ -93,7 +98,7 @@ BaseSQL.prototype.propertyName = function (model, column) { /** * Get the id property name - * @param model The model name + * @param {String} model The model name * @returns {String} The id property name */ BaseSQL.prototype.idName = function (model) { @@ -102,7 +107,7 @@ BaseSQL.prototype.idName = function (model) { /** * Get the id property names - * @param model The model name + * @param {String} model The model name * @returns {[String]} The id property names */ BaseSQL.prototype.idNames = function (model) { @@ -111,7 +116,7 @@ BaseSQL.prototype.idNames = function (model) { /** * Get the id column name - * @param model The model name + * @param {String} model The model name * @returns {String} The column name */ BaseSQL.prototype.idColumn = function (model) { @@ -125,7 +130,7 @@ BaseSQL.prototype.idColumn = function (model) { /** * Get the escaped id column name - * @param model The model name + * @param {String} model The model name * @returns {String} the escaped id column name */ BaseSQL.prototype.idColumnEscaped = function (model) { @@ -134,8 +139,8 @@ BaseSQL.prototype.idColumnEscaped = function (model) { /** * Get the id index (sequence number, starting from 1) - * @param model The model name - * @param prop The property name + * @param {String} model The model name + * @param {String} prop The property name * @returns {Number} The id index, undefined if the property is not part of the primary key */ BaseSQL.prototype.id = function (model, prop) { @@ -148,7 +153,7 @@ BaseSQL.prototype.id = function (model, prop) { /** * Escape the name for the underlying database - * @param name The name + * @param {String} name The name */ BaseSQL.prototype.escapeName = function (name) { throw new Error('escapeName method should be declared in connector'); @@ -156,7 +161,7 @@ BaseSQL.prototype.escapeName = function (name) { /** * Get the escaped table name - * @param model The model name + * @param {String} model The model name * @returns {String} the escaped table name */ BaseSQL.prototype.tableEscaped = function (model) { @@ -165,23 +170,39 @@ BaseSQL.prototype.tableEscaped = function (model) { /** * Get the escaped column name for a given model property - * @param model The model name - * @param property The property name + * @param {String} model The model name + * @param {String} property The property name * @returns {String} The escaped column name */ BaseSQL.prototype.columnEscaped = function (model, property) { return this.escapeName(this.column(model, property)); }; +/** + * Hook to be called by DataSource for defining a model + * @param {Object} descr The description of a model + */ BaseSQL.prototype.define = function (descr) { if (!descr.settings) descr.settings = {}; this._models[descr.model.modelName] = descr; }; +/** + * Hook to be called by DataSource for defining a model property + * @param {String} model The model name + * @param {String} prop The property name + * @param {Object} params The object for property metadata + */ BaseSQL.prototype.defineProperty = function (model, prop, params) { this._models[model].properties[prop] = params; }; +/** + * Save the model instance into the backend store + * @param {String} model The model name + * @param {Object} data The model instance data + * @param {Function} callback The callback function + */ BaseSQL.prototype.save = function (model, data, callback) { var sql = 'UPDATE ' + this.tableEscaped(model) + ' SET ' + this.toFields(model, data) + ' WHERE ' + this.idColumnEscaped(model) + ' = ' + Number(data.id); @@ -192,6 +213,12 @@ BaseSQL.prototype.save = function (model, data, callback) { }; +/** + * Check if a model instance exists for the given id value + * @param {String} model The model name + * @param {*} id The id value + * @param {Function} callback The callback function + */ BaseSQL.prototype.exists = function (model, id, callback) { var sql = 'SELECT 1 FROM ' + this.tableEscaped(model) + ' WHERE ' + this.idColumnEscaped(model) + ' = ' + Number(id) + ' LIMIT 1'; @@ -202,6 +229,12 @@ BaseSQL.prototype.exists = function (model, id, callback) { }); }; +/** + * Find a model instance by id + * @param {String} model The model name + * @param {*} id The id value + * @param {Function} callback The callback function + */ BaseSQL.prototype.find = function find(model, id, callback) { var sql = 'SELECT * FROM ' + this.tableEscaped(model) + ' WHERE ' + this.idColumnEscaped(model) + ' = ' + id + ' LIMIT 1'; @@ -216,6 +249,12 @@ BaseSQL.prototype.find = function find(model, id, callback) { }.bind(this)); }; +/** + * Delete a model instance by id value + * @param {String} model The model name + * @param {*} id The id value + * @param {Function} callback The callback function + */ BaseSQL.prototype.delete = BaseSQL.prototype.destroy = function destroy(model, id, callback) { var sql = 'DELETE FROM ' + this.tableEscaped(model) + ' WHERE ' + this.idColumnEscaped(model) + ' = ' + id; @@ -225,6 +264,12 @@ BaseSQL.prototype.delete = BaseSQL.prototype.destroy = function destroy(model, i }); }; +/** + * Delete all model instances + * + * @param {String} model The model name + * @param {Function} callback The callback function + */ BaseSQL.prototype.deleteAll = BaseSQL.prototype.destroyAll = function destroyAll(model, callback) { this.command('DELETE FROM ' + this.tableEscaped(model), function (err) { if (err) { @@ -234,6 +279,13 @@ BaseSQL.prototype.deleteAll = BaseSQL.prototype.destroyAll = function destroyAll }.bind(this)); }; +/** + * Count all model instances by the where filter + * + * @param {String} model The model name + * @param {Function} callback The callback function + * @param {Object} where The where clause + */ BaseSQL.prototype.count = function count(model, callback, where) { var self = this; var props = this._models[model].properties; @@ -258,19 +310,29 @@ BaseSQL.prototype.count = function count(model, callback, where) { } }; +/** + * Update attributes for a given model instance + * @param {String} model The model name + * @param {*} id The id value + * @param {Object} data The model data instance containing all properties to be updated + * @param {Function} cb The callback function + */ BaseSQL.prototype.updateAttributes = function updateAttrs(model, id, data, cb) { data.id = id; this.save(model, data, cb); }; +/** + * Disconnect from the connector + */ BaseSQL.prototype.disconnect = function disconnect() { this.client.end(); }; /** * Recreate the tables for the given models - * @param models A model name or an array of model names, if not present, apply to all models defined in the connector - * @param cb Callback function + * @param {[String]|String} [models] A model name or an array of model names, if not present, apply to all models defined in the connector + * @param {Function} [cb] The callback function */ BaseSQL.prototype.automigrate = function (models, cb) { var self = this; @@ -307,10 +369,21 @@ BaseSQL.prototype.automigrate = function (models, cb) { } }; +/** + * Drop the table for the given model + * @param {String} model The model name + * @param {Function} [cb] The callback function + */ BaseSQL.prototype.dropTable = function (model, cb) { this.command('DROP TABLE IF EXISTS ' + this.tableEscaped(model), cb); }; +/** + * Create the table for the given model + * @param {String} model The model name + * @param {Function} [cb] The callback function + */ + BaseSQL.prototype.createTable = function (model, cb) { this.command('CREATE TABLE ' + this.tableEscaped(model) + ' (\n ' + this.propertiesSQL(model) + '\n)', cb);