Merge branch 'release/2.0.1' into production

This commit is contained in:
Raymond Feng 2014-07-26 14:30:54 -07:00
commit 0e3187c736
9 changed files with 118 additions and 61 deletions

View File

@ -1,69 +1,72 @@
LoopBack is a highly extensible, open source Node.js framework that enables you to:
LoopBack is a highly-extensible, open-source Node.js framework that enables you to:
* Create dynamic end-to-end REST APIs with little or no coding
* Easily access data from Oracle, MySQL, PostgreSQL, MS SQL Server, MongoDB, SOAP and other REST APIs
* Incorporate model relationships and access controls for complex APIs
* Run your application on-premises or in the cloud
* Use built-in push, geolocation, and file services for mobile use cases
* Easily create client apps using Android, iOS, and JavaScript SDKs
* Create dynamic end-to-end REST APIs with little or no coding.
* Access data from Oracle, MySQL, PostgreSQL, MS SQL Server, MongoDB, SOAP and other REST APIs.
* Incorporate model relationships and access controls for complex APIs.
* Use built-in push, geolocation, and file services for mobile apps.
* Easily create client apps using Android, iOS, and JavaScript SDKs.
* Run your application on-premises or in the cloud.
LoopBack consists of:
* A library of Node.js modules.
* A command line tool, `slc`, for creating and working with LoopBack applications.
* Client SDKs for native and web-based mobile clients.
* [Yeoman](http://yeoman.io/) generators for scaffolding applications.
* Client SDKs for iOS, Android, and web clients.
For more details, see http://loopback.io/.
## LoopBack modules
In addition to the [main LoopBack module](https://github.com/strongloop/loopback), LoopBack consists of numerous other modules that implement specific functionality,
as illustrated below:
The LoopBack framework includes of a set of Node.js modules that you can use independently or together.
![LoopBack modules](https://github.com/strongloop/loopback/raw/master/docs/assets/lb-modules.png "LoopBack modules")
* Frameworks
* [loopback](https://github.com/strongloop/loopback)
* [loopback-datasource-juggler](https://github.com/strongloop/loopback-datasource-juggler)
* [strong-remoting](https://github.com/strongloop/strong-remoting)
### Core
* [loopback](https://github.com/strongloop/loopback)
* [loopback-datasource-juggler](https://github.com/strongloop/loopback-datasource-juggler)
* [strong-remoting](https://github.com/strongloop/strong-remoting)
* Enterprise Connectors
* [loopback-connector-mongodb](https://github.com/strongloop/loopback-connector-mongodb)
* [loopback-connector-mysql](https://github.com/strongloop/loopback-connector-mysql)
* [loopback-connector-oracle](https://github.com/strongloop/loopback-connector-oracle)
* [loopback-connector-mssql](https://github.com/strongloop/loopback-connector-mssql)
* [loopback-connector-postgresql](https://github.com/strongloop/loopback-connector-postgresql)
* [loopback-connector-rest](https://github.com/strongloop/loopback-connector-rest)
* [loopback-connector-soap](https://github.com/strongloop/loopback-connector-soap)
### Connectors
* [loopback-connector-mongodb](https://github.com/strongloop/loopback-connector-mongodb)
* [loopback-connector-mysql](https://github.com/strongloop/loopback-connector-mysql)
* [loopback-connector-postgresql](https://github.com/strongloop/loopback-connector-postgresql)
* [loopback-connector-rest](https://github.com/strongloop/loopback-connector-rest)
* Mobile Components
* [loopback-component-push](https://github.com/strongloop/loopback-component-push)
* [loopback-component-storage](https://github.com/strongloop/loopback-component-storage)
### Enterprise Connectors
* [loopback-connector-oracle](https://github.com/strongloop/loopback-connector-oracle)
* [loopback-connector-mssql](https://github.com/strongloop/loopback-connector-mssql)
* [loopback-connector-soap](https://github.com/strongloop/loopback-connector-soap)
* [loopback-connector-atg](https://github.com/strongloop/loopback-connector-atg)
* Security Components
* [loopback-component-passport](https://github.com/strongloop/loopback-component-passport)
### Components
* [loopback-component-push](https://github.com/strongloop/loopback-component-push)
* [loopback-component-storage](https://github.com/strongloop/loopback-component-storage)
* [loopback-component-passport](https://github.com/strongloop/loopback-component-passport)
* Clients
* [loopback-sdk-ios](https://github.com/strongloop/loopback-sdk-ios)
* [loopback-sdk-android](https://github.com/strongloop/loopback-sdk-android)
* [loopback-sdk-angular](https://github.com/strongloop/loopback-sdk-angular)
### Client SDKs
* [loopback-sdk-ios](https://github.com/strongloop/loopback-sdk-ios)
* [loopback-sdk-android](https://github.com/strongloop/loopback-sdk-android)
* [loopback-sdk-angular](https://github.com/strongloop/loopback-sdk-angular)
* [loopback-sdk-angular-cli](https://github.com/strongloop/loopback-sdk-angular-cli)
* [grunt-loopback-sdk-angular](https://github.com/strongloop/grunt-loopback-sdk-angular)
* Tools
* [loopback-explorer](https://github.com/strongloop/loopback-explorer)
* [loopback-workspace](https://github.com/strongloop/loopback-workspace)
* [strong-cli](https://github.com/strongloop/strong-cli)
### Tools
* [loopback-explorer](https://github.com/strongloop/loopback-explorer)
* [loopback-workspace](https://github.com/strongloop/loopback-workspace)
* [generator-loopback](https://github.com/strongloop/generator-loopback)
* Examples
* [loopback-example-database](https://github.com/strongloop/loopback-example-database)
* [loopback-example-datagraph](https://github.com/strongloop/loopback-example-datagraph)
* [loopback-example-full-stack](https://github.com/strongloop/loopback-example-full-stack)
* [loopback-example-office-supplies](https://github.com/strongloop/loopback-example-office-supplies)
* [loopback-example-todo](https://github.com/strongloop/loopback-example-todo)
* [loopback-example-access-control](https://github.com/strongloop/loopback-example-access-control)
* [loopback-example-proxy](https://github.com/strongloop/loopback-example-proxy)
* [strongloop-community/loopback-examples-ios](https://github.com/strongloop-community/loopback-examples-ios)
* [loopback-example-ssl](https://github.com/strongloop/loopback-example-ssl)
### Examples
* [loopback-example-app](https://github.com/strongloop/loopback-example-app)
* [loopback-example-database](https://github.com/strongloop/loopback-example-database)
* [loopback-example-datagraph](https://github.com/strongloop/loopback-example-datagraph)
* [loopback-example-full-stack](https://github.com/strongloop/loopback-example-full-stack)
* [loopback-example-office-supplies](https://github.com/strongloop/loopback-example-office-supplies)
* [loopback-example-todo](https://github.com/strongloop/loopback-example-todo)
* [loopback-example-access-control](https://github.com/strongloop/loopback-example-access-control)
* [loopback-example-proxy](https://github.com/strongloop/loopback-example-proxy)
* [strongloop-community/loopback-examples-ios](https://github.com/strongloop-community/loopback-examples-ios)
* [loopback-example-ssl](https://github.com/strongloop/loopback-example-ssl)
## Resources
@ -71,7 +74,6 @@ as illustrated below:
* [API documentation](http://apidocs.strongloop.com/loopback).
* [LoopBack Google Group](https://groups.google.com/forum/#!forum/loopbackjs).
* [GitHub issues](https://github.com/strongloop/loopback/issues).
* Read more about the [LoopBack's features](https://github.com/strongloop/loopback/wiki/Features).
## Contributing

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -152,9 +152,11 @@ app.model = function (Model, config) {
if (isPublic && Model.sharedClass) {
this.remotes().addClass(Model.sharedClass);
if (Model.settings.trackChanges && Model.Change)
if (Model.settings.trackChanges && Model.Change) {
this.remotes().addClass(Model.Change.sharedClass);
}
clearHandlerCache(this);
this.emit('modelRemoted', Model.sharedClass);
}
Model.shared = isPublic;

View File

@ -1,3 +1,6 @@
var EventEmitter = require('events').EventEmitter;
var util = require('util');
module.exports = browserExpress;
function browserExpress() {
@ -10,6 +13,8 @@ function BrowserExpress() {
this.settings = {};
}
util.inherits(BrowserExpress, EventEmitter);
BrowserExpress.prototype.set = function(key, value) {
if (arguments.length == 1) {
return this.get(key);

View File

@ -59,10 +59,17 @@ MailConnector.prototype.setupTransport = function(setting) {
connector.transports = connector.transports || [];
connector.transportsIndex = connector.transportsIndex || {};
var transportModuleName = 'nodemailer-' + (setting.type || 'STUB').toLowerCase() + '-transport';
var transportModule = require(transportModuleName);
var transport = mailer.createTransport(transportModule(setting));
var transport;
var transportType = (setting.type || 'STUB').toLowerCase();
if (transportType === 'direct') {
transport = mailer.createTransport();
} else if (transportType === 'smtp') {
transport = mailer.createTransport(setting);
} else {
var transportModuleName = 'nodemailer-' + transportType + '-transport';
var transportModule = require(transportModuleName);
transport = mailer.createTransport(transportModule(setting));
}
connector.transportsIndex[setting.type] = transport;
connector.transports.push(transport);

View File

@ -136,7 +136,8 @@ Model.setup = function () {
var idDesc = ModelCtor.modelName + ' id';
ModelCtor.sharedCtor.accepts = [
{arg: 'id', type: 'any', http: {source: 'path'}, description: idDesc}
{arg: 'id', type: 'any', required: true, http: {source: 'path'},
description: idDesc}
// {arg: 'instance', type: 'object', http: {source: 'body'}}
];
@ -347,6 +348,7 @@ Model.belongsToRemoting = function(relationName, relation, define) {
}
Model.hasManyRemoting = function (relationName, relation, define) {
var toModelName = relation.modelTo.modelName;
var findByIdFunc = this.prototype['__findById__' + relationName];
define('__findById__' + relationName, {
isStatic: false,
@ -355,7 +357,7 @@ Model.hasManyRemoting = function (relationName, relation, define) {
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}},
description: 'Find a related item by id for ' + relationName,
returns: {arg: 'result', type: relation.modelTo.modelName, root: true}
returns: {arg: 'result', type: toModelName, root: true}
}, findByIdFunc);
var destroyByIdFunc = this.prototype['__destroyById__' + relationName];
@ -373,11 +375,14 @@ Model.hasManyRemoting = function (relationName, relation, define) {
define('__updateById__' + relationName, {
isStatic: false,
http: {verb: 'put', path: '/' + relationName + '/:fk'},
accepts: {arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}},
accepts: [
{arg: 'fk', type: 'any',
description: 'Foreign key for ' + relationName, required: true,
http: {source: 'path'}},
{arg: 'data', type: toModelName, http: {source: 'body'}}
],
description: 'Update a related item by id for ' + relationName,
returns: {arg: 'result', type: relation.modelTo.modelName, root: true}
returns: {arg: 'result', type: toModelName, root: true}
}, updateByIdFunc);
if (relation.modelThrough) {
@ -432,7 +437,7 @@ Model.scopeRemoting = function(relationName, relation, define) {
define('__create__' + relationName, {
isStatic: false,
http: {verb: 'post', path: '/' + relationName},
accepts: {arg: 'data', type: 'object', http: {source: 'body'}},
accepts: {arg: 'data', type: toModelName, http: {source: 'body'}},
description: 'Creates a new instance in ' + relationName + ' of this model.',
returns: {arg: 'data', type: toModelName, root: true}
});

View File

@ -1,6 +1,6 @@
{
"name": "loopback",
"description": "LoopBack: Open API Framework for Node.js",
"description": "LoopBack: Open Source Framework for Node.js",
"homepage": "http://loopback.io",
"keywords": [
"restful",
@ -26,7 +26,7 @@
"mobile",
"mBaaS"
],
"version": "2.0.0",
"version": "2.0.1",
"scripts": {
"test": "grunt mocha-and-karma"
},

View File

@ -47,6 +47,18 @@ describe('app', function() {
expect(app.models.Color).to.equal(Color);
});
it("emits a `modelRemoted` event", function() {
var Color = PersistedModel.extend('color', {name: String});
Color.shared = true;
var remotedClass;
app.on('modelRemoted', function(sharedClass) {
remotedClass = sharedClass;
});
app.model(Color);
expect(remotedClass).to.exist;
expect(remotedClass).to.eql(Color.sharedClass);
});
it.onServer('updates REST API when a new model is added', function(done) {
app.use(loopback.rest());
request(app).get('/colors').expect(404, function(err, res) {

View File

@ -1,6 +1,30 @@
var loopback = require('../');
var MyEmail;
var assert = require('assert');
var MailConnector = require('../lib/connectors/mail');
describe('Email connector', function () {
it('should set up SMTP', function () {
var connector = new MailConnector({transports: [
{type: 'smtp', service: 'gmail'}
]});
assert(connector.transportForName('smtp'));
});
it('should set up DIRECT', function () {
var connector = new MailConnector({transports: [
{type: 'direct', name: 'localhost'}
]});
assert(connector.transportForName('direct'));
});
it('should set up STUB', function () {
var connector = new MailConnector({transports: [
{type: 'stub', service: 'gmail'}
]});
assert(connector.transportForName('stub'));
});
});
describe('Email and SMTP', function () {
beforeEach(function() {