From e028d442718869602b1ed41cc70787858f335eb2 Mon Sep 17 00:00:00 2001 From: Miroslav Bajtos Date: Thu, 21 Nov 2013 19:05:19 +0100 Subject: [PATCH 1/5] Add .jshintignore Ignored paths: node_modules support/nodeunit --- .jshintignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .jshintignore diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 00000000..92b148b1 --- /dev/null +++ b/.jshintignore @@ -0,0 +1,2 @@ +node_modules +support/nodeunit From f7c48c0d72d184afa70ba5611f4924dcccbf46c9 Mon Sep 17 00:00:00 2001 From: Miroslav Bajtos Date: Thu, 21 Nov 2013 16:19:34 +0100 Subject: [PATCH 2/5] REST call of DataAccessObject.findById returns 404 Modify the remoting configuration of `DataAccessObject.findById()` and add a `rest.before` handler that converts `null` to 404 error. The change is covered by a test in loopback project. --- lib/dao.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/dao.js b/lib/dao.js index 6d3175da..224e6cdf 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -331,9 +331,20 @@ setRemoting(DataAccessObject.findById, { description: 'Find a model instance by id from the data source', accepts: {arg: 'id', type: 'any', description: 'Model id', required: true}, returns: {arg: 'data', type: 'any', root: true}, - http: {verb: 'get', path: '/:id'} + http: {verb: 'get', path: '/:id'}, + rest: {after: convertNullToNotFoundError} }); +function convertNullToNotFoundError(ctx, cb) { + if (ctx.result !== null) return cb(); + + var modelName = ctx.method.sharedClass.name; + var id = ctx.getArgByName('id'); + var msg = 'Unkown "' + modelName + '" id "' + id + '".'; + var error = new Error(msg); + error.statusCode = error.status = 404; + cb(error); +} // alias function for backwards compat. DataAccessObject.all = function () { From 4c0c852c201786f6a71a62083dd0ac9b717dd407 Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Mon, 25 Nov 2013 17:03:56 -0800 Subject: [PATCH 3/5] Removed most text that's in docs.strongloop.com --- README.md | 121 +----------------------------------------------------- 1 file changed, 2 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index 094b63c4..0c906219 100644 --- a/README.md +++ b/README.md @@ -4,124 +4,7 @@ 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](docs/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 a 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. - -## 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) | - - -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 : '127.0.0.1', - database : 'XE', - username : 'strongloop', - password : 'password', - 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 - +For full documentation, see [StrongLoop Suite Documentation](http://docs.strongloop.com/display/DOC/Data+Source+Juggler). ## Installation @@ -131,6 +14,6 @@ Also install the appropriated connector, for example for mongodb: npm install loopback-connector-mongodb -check following list of available connectors +See [StrongLoop Suite Documentation](http://docs.strongloop.com/) for up-to-date list of connectors supported. From b5e0035d7378b3a9188ac36669b65f5153ec04a4 Mon Sep 17 00:00:00 2001 From: Miroslav Bajtos Date: Mon, 25 Nov 2013 17:20:05 +0100 Subject: [PATCH 4/5] Improve properties of ValidationError - change `statusCode` from 400 to 422 - nest `context` and `codes` inside `details` - add `details.messages` - reword the main error message Remove the call to Error's constructor from ValidationError constructor, because it's a no-op - Error's constructor creates a new instance when called via `.call()`. --- index.js | 1 + lib/validations.js | 14 +++++++++----- test/manipulation.test.js | 3 ++- test/validations.test.js | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 34949bb5..79171c1b 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ exports.ModelBuilder = exports.LDL = require('./lib/model-builder.js').ModelBuil exports.DataSource = exports.Schema = require('./lib/datasource.js').DataSource; exports.ModelBaseClass = require('./lib/model.js'); exports.Connector = require('./lib/connector.js'); +exports.ValidationError = require('./lib/validations.js').ValidationError; var baseSQL = './lib/sql'; diff --git a/lib/validations.js b/lib/validations.js index 19ecb987..397841ec 100644 --- a/lib/validations.js +++ b/lib/validations.js @@ -599,12 +599,16 @@ function ValidationError(obj) { if (!(this instanceof ValidationError)) return new ValidationError(obj); this.name = 'ValidationError'; - this.message = 'Validation error'; - this.statusCode = 400; - this.codes = obj.errors && obj.errors.codes; - this.context = obj && obj.constructor && obj.constructor.modelName; + this.message = 'The Model instance is not valid. ' + + 'See `details` property of the error object for more info.'; + this.statusCode = 422; + + this.details = { + context: obj && obj.constructor && obj.constructor.modelName, + codes: obj.errors && obj.errors.codes, + messages: obj.errors + }; - Error.call(this); Error.captureStackTrace(this, this.constructor); } diff --git a/test/manipulation.test.js b/test/manipulation.test.js index 0e9563ae..295160f6 100644 --- a/test/manipulation.test.js +++ b/test/manipulation.test.js @@ -2,6 +2,7 @@ var should = require('./init.js'); var db, Person; +var ValidationError = require('..').ValidationError; describe('manipulation', function() { @@ -173,7 +174,7 @@ describe('manipulation', function() { p.save({ 'throws': true }); - }).should.throw('Validation error'); + }).should.throw(ValidationError); }); }); diff --git a/test/validations.test.js b/test/validations.test.js index b87fa5fc..c54b46ec 100644 --- a/test/validations.test.js +++ b/test/validations.test.js @@ -2,7 +2,7 @@ var should = require('./init.js'); var j = require('../'), db, User; -var ValidationError = require('../lib/validations.js').ValidationError; +var ValidationError = j.ValidationError; function getValidAttributes() { return { @@ -98,7 +98,7 @@ describe('validations', function() { User.validatesPresenceOf('name'); User.create(function(e, u) { should.exist(e); - e.codes.name.should.eql(['presence']); + e.details.codes.name.should.eql(['presence']); done(); }); }); From 9a549cfe5d3e4eeb8a8ed6e8df5735ff718f0187 Mon Sep 17 00:00:00 2001 From: Ritchie Martori Date: Wed, 4 Dec 2013 11:40:50 -0800 Subject: [PATCH 5/5] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 31da707d..77ee23d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-datasource-juggler", - "version": "1.2.4", + "version": "1.2.5", "description": "LoopBack DataSoure Juggler", "keywords": [ "StrongLoop",