diff --git a/README.md b/README.md index f5d1f8cb..e059c83f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,263 @@ -# Loopback Data +# LoopBack DataSource Juggler -Loopback Data is an ORM that provides a common set of interfaces for interacting with databases, REST apis, and other data sources. +LoopBack DataSource Juggler is an ORM that provides a common set of interfaces for interacting with databases, REST APIs, and other data sources. +It was initially forked from [JugglingDB](https://github.com/1602/jugglingdb). + +## Overview + +LoopBack DataSource Juggler consists of the following components: + +* LoopBack Definition Language +* DataSource +* Connector + +![loopback-datasource-juggler-overview](overview.png "LoopBack Diagram") + +### LoopBack Definition Language + +To define model dataSource have single method `dataSource.define`. It accepts three +arguments: + +* **model name**: + String name in camel-case with first upper-case letter. This name will be used + later to access model. +* **properties**: + Object with property type definitions. Key is property name, value is type + definition. Type definition can be function representing type of property + (String, Number, Date, Boolean), or object with {type: String|Number|..., + index: true|false} format. +* **settings**: + Object with model-wide settings such as `tableName` or so. + +Examples of model definition: + + var User = dataSource.define('User', { + email: String, + password: String, + birthDate: Date, + activated: Boolean + }); + + var User = dataSource.define('User', { + email: { type: String, limit: 150, index: true }, + password: { type: String, limit: 50 }, + birthDate: Date, + registrationDate: { + type: Date, + default: function () { return new Date } + }, + activated: { type: Boolean, default: false } + }, { + tableName: 'users' + }); + +### DataSource + +DataSource is a factory for model classes. DataSource connected with specific database or other +backend system using connector. + +All model classes within single datasource shares same connector type and one database +connection. But it's possible to use more than one datasource to connect with +different databases. + +#### Creating dataSource + +`DataSource` constructor available on `loopback-datasource-juggler` module: + + var DataSource = require('loopback-datasource-juggler').DataSource; + +DataSource constructor accepts two arguments. First argument is connector. It could be +connector name or connector package: + + var dataSourceByConnectorName = new DataSource('memory'); + var dataSourceByConnectorModule = new DataSource(require('redis')); + +#### Settings + +Second argument is optional settings. Settings object format and defaults +depends on specific connector, but common fields are: + +* `host`: Database host +* `port`: Database port +* `username`: Username to connect to database +* `password`: Password to connect to database +* `database`: Database name +* `debug`: Turn on verbose mode to debug db queries and lifecycle + +For connector-specific settings refer to connector's readme file. + +#### Connecting to database + +DataSource connecting to database automatically. Once connection established dataSource +object emit 'connected' event, and set `connected` flag to true, but it is not +necessary to wait for 'connected' event because all queries cached and executed +when dataSource emit 'connected' event. + +To disconnect from database server call `dataSource.disconnect` method. This call +forwarded to connector if connector have ability to connect/disconnect. + + +#### DB structure syncronization + +DataSource instance have two methods for updating db structure: automigrate and +autoupdate. + +The `automigrate` method drop table (if exists) and create it again, +`autoupdate` method generates ALTER TABLE query. Both method accepts callback +called when migration/update done. + +To check if any db changes required use `isActual` method. It accepts single +`callback` argument, which receive boolean value depending on db state: false if +db structure outdated, true when dataSource and db is in sync: + + dataSource.isActual(function(err, actual) { + if (!actual) { + dataSource.autoupdate(); + } + }); + +## LoopBack Connectors + +| Type | Package Name | +| --------- |:--------------------------------------------------------------------------------------:| +| MongoDB | [loopback-connector-mongodb](https://github.com/strongloop/loopback-connector-mongodb) | +| Oracle | [loopback-connector-oracle](https://github.com/strongloop/loopback-connector-oracle) | +| MySQL | [loopback-connector-mysql](https://github.com/strongloop/loopback-connector-mysql) | + +## Build your own connector + +LoopBack connectors provide access to backend systems including databases, REST APIs +and other services. Connectors are not used directly by application code. We create +a DataSource to interact with the connector. + +For example, + + var DataSource = require('loopback-datasource-juggler').DataSource; + var oracleConnector = require('loopback-connector-oracle'); + + var ds = new DataSource(oracleConnector, { + host : '166.78.158.45', + database : 'XE', + username : 'strongloop', + password : 'str0ng100pjs', + debug : true + }); + +The connector argument passed the DataSource constructor can be one of the following: + +* The connector module from `require(connectorName)` +* The full name of the connector module, such as 'loopback-connector-oracle' +* The short name of the connector module, such as 'oracle', which will be converted to 'loopback-connector-' +* A local module under ./connectors/ folder + +## Generic connector implmentations + +A connector module can implement the following methods to interact with the datasource. + + exports.initialize = function (dataSource, postInit) { + + var settings = dataSource.settings || {}; // The settings is passed in from the dataSource + + var connector = new MyConnector(settings); // Construct the connector instance + dataSource.connector = connector; // Attach connector to dataSource + connector.dataSource = dataSource; // Hold a reference to dataSource + + /** + * Connector instance can have an optional property named as DataAccessObject that provides + * static and prototype methods to be mixed into the model constructor. The property can be defined + * on the prototype. + */ + connector.DataAccessObject = function {}; + + /** + * Connector instance can have an optional function to be called to handle data model definitions. + * The function can be defined on the prototype too. + * @param model The name of the model + * @param properties An object for property definitions keyed by propery names + * @param settings An object for the model settings + */ + connector.define = function(model, properties, settings) { + ... + }; + + connector.connect(..., postInit); // Run some async code for initialization + // process.nextTick(postInit); + } + +Another way is to directly export the connection function which takes a settings object. + + module.exports = function(settings) { + ... + } + +## CRUD connector implmentations + +To support CRUD operations for a model class that is attached to the dataSource/connector, the connector needs to provide +the following functions: + + /** + * Create a new model instance + */ + CRUDConnector.prototype.create = function (model, data, callback) { + }; + + /** + * Save a model instance + */ + CRUDConnector.prototype.save = function (model, data, callback) { + }; + + /** + * Check if a model instance exists by id + */ + CRUDConnector.prototype.exists = function (model, id, callback) { + }; + + /** + * Find a model instance by id + */ + CRUDConnector.prototype.find = function find(model, id, callback) { + }; + + /** + * Update a model instance or create a new model instance if it doesn't exist + */ + CRUDConnector.prototype.updateOrCreate = function updateOrCreate(model, data, callback) { + }; + + /** + * Delete a model instance by id + */ + CRUDConnector.prototype.destroy = function destroy(model, id, callback) { + }; + + /** + * Query model instances by the filter + */ + CRUDConnector.prototype.all = function all(model, filter, callback) { + }; + + /** + * Delete all model instances + */ + CRUDConnector.prototype.destroyAll = function destroyAll(model, callback) { + }; + + /** + * Count the model instances by the where criteria + */ + CRUDConnector.prototype.count = function count(model, callback, where) { + }; + + /** + * Update the attributes for a model instance by id + */ + CRUDConnector.prototype.updateAttributes = function updateAttrs(model, id, data, callback) { + }; ## Installation - slnode install loopback-datasource-juggler + npm install loopback-datasource-juggler Also install the appropriated connector, for example for mongodb: @@ -12,35 +265,5 @@ Also install the appropriated connector, for example for mongodb: check following list of available connectors -## Loopback Data Connectors - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TypePackage name
MongoDB MongoDBloopback-connector-mongodb
Oracle Oracleloopback-connector-oracle
MySQL MySQLloopback-connector-mysql
diff --git a/docs.json b/docs.json index f73a8684..67c66d6b 100644 --- a/docs.json +++ b/docs.json @@ -1,9 +1,6 @@ { "content": [ "README.md", - "docs/loopback-datasource-juggler.md", - "docs/connector.md", - "docs/data-source.md", { "title": "LoopBack DataSource API", "depth": 2 diff --git a/docs/connector.md b/docs/connector.md deleted file mode 100644 index a977e5be..00000000 --- a/docs/connector.md +++ /dev/null @@ -1,134 +0,0 @@ -# loopback-datasource-juggler-connector - -Loopback connectors provide access to backend systems including databases, REST APIs -and other services. Connectors are not used directly by application code. We create -a DataSource to interact with the connector. - -For example, - - var DataSource = require('loopback-datasource-juggler').DataSource; - var oracleConnector = require('loopback-connector-oracle'); - - var ds = new DataSource(oracleConnector, { - host : '166.78.158.45', - database : 'XE', - username : 'strongloop', - password : 'str0ng100pjs', - debug : true - }); - -The connector argument passed the DataSource constructor can be one of the following: - -* The connector module from `require(connectorName)` -* The full name of the connector module, such as 'loopback-connector-oracle' -* The short name of the connector module, such as 'oracle', which will be converted to 'loopback-connector-' -* A local module under ./connectors/ folder - -## Generic connector implmentations - -A connector module can implement the following methods to interact with the datasource. - - exports.initialize = function (dataSource, postInit) { - - var settings = dataSource.settings || {}; // The settings is passed in from the dataSource - - var connector = new MyConnector(settings); // Construct the connector instance - dataSource.connector = connector; // Attach connector to dataSource - connector.dataSource = dataSource; // Hold a reference to dataSource - - /** - * Connector instance can have an optional property named as DataAccessObject that provides - * static and prototype methods to be mixed into the model constructor. The property can be defined - * on the prototype. - */ - connector.DataAccessObject = function {}; - - /** - * Connector instance can have an optional function to be called to handle data model definitions. - * The function can be defined on the prototype too. - * @param model The name of the model - * @param properties An object for property definitions keyed by propery names - * @param settings An object for the model settings - */ - connector.define = function(model, properties, settings) { - ... - }; - - connector.connect(..., postInit); // Run some async code for initialization - // process.nextTick(postInit); - } - -Another way is to directly export the connection function which takes a settings object. - - module.exports = function(settings) { - ... - } - -## CRUD connector implmentations - -To support CRUD operations for a model class that is attached to the dataSource/connector, the connector needs to provide -the following functions: - - /** - * Create a new model instance - */ - CRUDConnector.prototype.create = function (model, data, callback) { - }; - - /** - * Save a model instance - */ - CRUDConnector.prototype.save = function (model, data, callback) { - }; - - /** - * Check if a model instance exists by id - */ - CRUDConnector.prototype.exists = function (model, id, callback) { - }; - - /** - * Find a model instance by id - */ - CRUDConnector.prototype.find = function find(model, id, callback) { - }; - - /** - * Update a model instance or create a new model instance if it doesn't exist - */ - CRUDConnector.prototype.updateOrCreate = function updateOrCreate(model, data, callback) { - }; - - /** - * Delete a model instance by id - */ - CRUDConnector.prototype.destroy = function destroy(model, id, callback) { - }; - - /** - * Query model instances by the filter - */ - CRUDConnector.prototype.all = function all(model, filter, callback) { - }; - - /** - * Delete all model instances - */ - CRUDConnector.prototype.destroyAll = function destroyAll(model, callback) { - }; - - /** - * Count the model instances by the where criteria - */ - CRUDConnector.prototype.count = function count(model, callback, where) { - }; - - /** - * Update the attributes for a model instance by id - */ - CRUDConnector.prototype.updateAttributes = function updateAttrs(model, id, data, callback) { - }; - - - - diff --git a/docs/data-source.md b/docs/data-source.md deleted file mode 100644 index 13eff8b0..00000000 --- a/docs/data-source.md +++ /dev/null @@ -1,127 +0,0 @@ -# loopback-datasource-juggler-datasource - -Everything about datasource, data types and model definition. - -## DESCRIPTION - -DataSource is a factory for model classes. DataSource connected with specific database or other -backend system using connector. - -All model classes within single datasource shares same connector type and one database -connection. But it's possible to use more than one datasource to connect with -different databases. - -## EVENTS - -Instances of DataSource are event emitters, events supported by default: - -* `.on('connected', function() {})`: - Fired when db connection established. Params: none. -* `.on('log', function(msg, duration) {})`: - Fired when connector logged line. Params: String message, Number duration - -## USAGE - -### Creating dataSource - -`DataSource` constructor available on `loopback-datasource-juggler` module: - - var DataSource = require('loopback-datasource-juggler').DataSource; - -DataSource constructor accepts two arguments. First argument is connector. It could be -connector name or connector package: - - var dataSourceByConnectorName = new DataSource('memory'); - var dataSourceByConnectorModule = new DataSource(require('redis')); - -### Settings - -Second argument is optional settings. Settings object format and defaults -depends on specific connector, but common fields are: - -* `host`: -Database host -* `port`: -Database port -* `username`: -Username to connect to database -* `password`: -Password to connect to database -* `database`: -Database name -* `debug`: -Turn on verbose mode to debug db queries and lifecycle - -For connector-specific settings refer to connector's readme file. - -### Connecting to database - -DataSource connecting to database automatically. Once connection established dataSource -object emit 'connected' event, and set `connected` flag to true, but it is not -necessary to wait for 'connected' event because all queries cached and executed -when dataSource emit 'connected' event. - -To disconnect from database server call `dataSource.disconnect` method. This call -forwarded to connector if connector have ability to connect/disconnect. - -### Model definition - -To define model dataSource have single method `dataSource.define`. It accepts three -argumets: - -* **model name**: - String name in camel-case with first upper-case letter. This name will be used - later to access model. -* **properties**: - Object with property type definitions. Key is property name, value is type - definition. Type definition can be function representing type of property - (String, Number, Date, Boolean), or object with {type: String|Number|..., - index: true|false} format. -* **settings**: - Object with model-wide settings such as `tableName` or so. - -Examples of model definition: - - var User = dataSource.define('User', { - email: String, - password: String, - birthDate: Date, - activated: Boolean - }); - - var User = dataSource.define('User', { - email: { type: String, limit: 150, index: true }, - password: { type: String, limit: 50 }, - birthDate: Date, - registrationDate: { - type: Date, - default: function () { return new Date } - }, - activated: { type: Boolean, default: false } - }, { - tableName: 'users' - }); - -### DB structure syncronization - -DataSource instance have two methods for updating db structure: automigrate and -autoupdate. - -The `automigrate` method drop table (if exists) and create it again, -`autoupdate` method generates ALTER TABLE query. Both method accepts callback -called when migration/update done. - -To check if any db changes required use `isActual` method. It accepts single -`callback` argument, which receive boolean value depending on db state: false if -db structure outdated, true when dataSource and db is in sync: - - dataSource.isActual(function(err, actual) { - if (!actual) { - dataSource.autoupdate(); - } - }); - -## SEE ALSO - -loopback-datasource-juggler-model -loopback-datasource-juggler-connector diff --git a/docs/loopback-datasource-juggler.md b/docs/loopback-datasource-juggler.md deleted file mode 100644 index 2822c056..00000000 --- a/docs/loopback-datasource-juggler.md +++ /dev/null @@ -1,11 +0,0 @@ -# loopback-datasource-juggler - -Loopback-data provides ORM and data connectivity for Node.js. It was initially forked from [JugglingDB](https://github.com/1602/jugglingdb). - -## Overview - -![loopback-datasource-juggler](loopback-datasource-juggler.png "Loopback Data Diagram") - -## SEE ALSO - -loopback-datasource-juggler-connector diff --git a/docs/loopback-datasource-juggler.png b/docs/loopback-datasource-juggler.png deleted file mode 100644 index 9a13aad6..00000000 Binary files a/docs/loopback-datasource-juggler.png and /dev/null differ diff --git a/overview.png b/overview.png new file mode 100644 index 00000000..426deb22 Binary files /dev/null and b/overview.png differ