Merge branch 'release/2.0.1' into production
This commit is contained in:
commit
0e3187c736
96
README.md
96
README.md
|
@ -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
|
* 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
|
* Access data from Oracle, MySQL, PostgreSQL, MS SQL Server, MongoDB, SOAP and other REST APIs.
|
||||||
* Incorporate model relationships and access controls for complex 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 apps.
|
||||||
* Use built-in push, geolocation, and file services for mobile use cases
|
* Easily create client apps using Android, iOS, and JavaScript SDKs.
|
||||||
* Easily create client apps using Android, iOS, and JavaScript SDKs
|
* Run your application on-premises or in the cloud.
|
||||||
|
|
||||||
LoopBack consists of:
|
LoopBack consists of:
|
||||||
|
|
||||||
* A library of Node.js modules.
|
* A library of Node.js modules.
|
||||||
* A command line tool, `slc`, for creating and working with LoopBack applications.
|
* [Yeoman](http://yeoman.io/) generators for scaffolding applications.
|
||||||
* Client SDKs for native and web-based mobile clients.
|
* Client SDKs for iOS, Android, and web clients.
|
||||||
|
|
||||||
For more details, see http://loopback.io/.
|
For more details, see http://loopback.io/.
|
||||||
|
|
||||||
## LoopBack modules
|
## LoopBack modules
|
||||||
|
|
||||||
In addition to the [main LoopBack module](https://github.com/strongloop/loopback), LoopBack consists of numerous other modules that implement specific functionality,
|
The LoopBack framework includes of a set of Node.js modules that you can use independently or together.
|
||||||
as illustrated below:
|
|
||||||
|
|
||||||
![LoopBack modules](https://github.com/strongloop/loopback/raw/master/docs/assets/lb-modules.png "LoopBack modules")
|
![LoopBack modules](https://github.com/strongloop/loopback/raw/master/docs/assets/lb-modules.png "LoopBack modules")
|
||||||
|
|
||||||
* Frameworks
|
### Core
|
||||||
* [loopback](https://github.com/strongloop/loopback)
|
* [loopback](https://github.com/strongloop/loopback)
|
||||||
* [loopback-datasource-juggler](https://github.com/strongloop/loopback-datasource-juggler)
|
* [loopback-datasource-juggler](https://github.com/strongloop/loopback-datasource-juggler)
|
||||||
* [strong-remoting](https://github.com/strongloop/strong-remoting)
|
* [strong-remoting](https://github.com/strongloop/strong-remoting)
|
||||||
|
|
||||||
* Enterprise Connectors
|
### Connectors
|
||||||
* [loopback-connector-mongodb](https://github.com/strongloop/loopback-connector-mongodb)
|
* [loopback-connector-mongodb](https://github.com/strongloop/loopback-connector-mongodb)
|
||||||
* [loopback-connector-mysql](https://github.com/strongloop/loopback-connector-mysql)
|
* [loopback-connector-mysql](https://github.com/strongloop/loopback-connector-mysql)
|
||||||
* [loopback-connector-oracle](https://github.com/strongloop/loopback-connector-oracle)
|
* [loopback-connector-postgresql](https://github.com/strongloop/loopback-connector-postgresql)
|
||||||
* [loopback-connector-mssql](https://github.com/strongloop/loopback-connector-mssql)
|
* [loopback-connector-rest](https://github.com/strongloop/loopback-connector-rest)
|
||||||
* [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)
|
|
||||||
|
|
||||||
* Mobile Components
|
### Enterprise Connectors
|
||||||
* [loopback-component-push](https://github.com/strongloop/loopback-component-push)
|
* [loopback-connector-oracle](https://github.com/strongloop/loopback-connector-oracle)
|
||||||
* [loopback-component-storage](https://github.com/strongloop/loopback-component-storage)
|
* [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
|
### Components
|
||||||
* [loopback-component-passport](https://github.com/strongloop/loopback-component-passport)
|
* [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
|
### Client SDKs
|
||||||
* [loopback-sdk-ios](https://github.com/strongloop/loopback-sdk-ios)
|
* [loopback-sdk-ios](https://github.com/strongloop/loopback-sdk-ios)
|
||||||
* [loopback-sdk-android](https://github.com/strongloop/loopback-sdk-android)
|
* [loopback-sdk-android](https://github.com/strongloop/loopback-sdk-android)
|
||||||
* [loopback-sdk-angular](https://github.com/strongloop/loopback-sdk-angular)
|
* [loopback-sdk-angular](https://github.com/strongloop/loopback-sdk-angular)
|
||||||
* [loopback-sdk-angular-cli](https://github.com/strongloop/loopback-sdk-angular-cli)
|
* [loopback-sdk-angular-cli](https://github.com/strongloop/loopback-sdk-angular-cli)
|
||||||
* [grunt-loopback-sdk-angular](https://github.com/strongloop/grunt-loopback-sdk-angular)
|
* [grunt-loopback-sdk-angular](https://github.com/strongloop/grunt-loopback-sdk-angular)
|
||||||
|
|
||||||
* Tools
|
### Tools
|
||||||
* [loopback-explorer](https://github.com/strongloop/loopback-explorer)
|
* [loopback-explorer](https://github.com/strongloop/loopback-explorer)
|
||||||
* [loopback-workspace](https://github.com/strongloop/loopback-workspace)
|
* [loopback-workspace](https://github.com/strongloop/loopback-workspace)
|
||||||
* [strong-cli](https://github.com/strongloop/strong-cli)
|
* [generator-loopback](https://github.com/strongloop/generator-loopback)
|
||||||
|
|
||||||
* Examples
|
### Examples
|
||||||
* [loopback-example-database](https://github.com/strongloop/loopback-example-database)
|
|
||||||
* [loopback-example-datagraph](https://github.com/strongloop/loopback-example-datagraph)
|
* [loopback-example-app](https://github.com/strongloop/loopback-example-app)
|
||||||
* [loopback-example-full-stack](https://github.com/strongloop/loopback-example-full-stack)
|
* [loopback-example-database](https://github.com/strongloop/loopback-example-database)
|
||||||
* [loopback-example-office-supplies](https://github.com/strongloop/loopback-example-office-supplies)
|
* [loopback-example-datagraph](https://github.com/strongloop/loopback-example-datagraph)
|
||||||
* [loopback-example-todo](https://github.com/strongloop/loopback-example-todo)
|
* [loopback-example-full-stack](https://github.com/strongloop/loopback-example-full-stack)
|
||||||
* [loopback-example-access-control](https://github.com/strongloop/loopback-example-access-control)
|
* [loopback-example-office-supplies](https://github.com/strongloop/loopback-example-office-supplies)
|
||||||
* [loopback-example-proxy](https://github.com/strongloop/loopback-example-proxy)
|
* [loopback-example-todo](https://github.com/strongloop/loopback-example-todo)
|
||||||
* [strongloop-community/loopback-examples-ios](https://github.com/strongloop-community/loopback-examples-ios)
|
* [loopback-example-access-control](https://github.com/strongloop/loopback-example-access-control)
|
||||||
* [loopback-example-ssl](https://github.com/strongloop/loopback-example-ssl)
|
* [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
|
## Resources
|
||||||
|
|
||||||
|
@ -71,7 +74,6 @@ as illustrated below:
|
||||||
* [API documentation](http://apidocs.strongloop.com/loopback).
|
* [API documentation](http://apidocs.strongloop.com/loopback).
|
||||||
* [LoopBack Google Group](https://groups.google.com/forum/#!forum/loopbackjs).
|
* [LoopBack Google Group](https://groups.google.com/forum/#!forum/loopbackjs).
|
||||||
* [GitHub issues](https://github.com/strongloop/loopback/issues).
|
* [GitHub issues](https://github.com/strongloop/loopback/issues).
|
||||||
* Read more about the [LoopBack's features](https://github.com/strongloop/loopback/wiki/Features).
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 309 KiB After Width: | Height: | Size: 104 KiB |
|
@ -152,9 +152,11 @@ app.model = function (Model, config) {
|
||||||
|
|
||||||
if (isPublic && Model.sharedClass) {
|
if (isPublic && Model.sharedClass) {
|
||||||
this.remotes().addClass(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);
|
this.remotes().addClass(Model.Change.sharedClass);
|
||||||
|
}
|
||||||
clearHandlerCache(this);
|
clearHandlerCache(this);
|
||||||
|
this.emit('modelRemoted', Model.sharedClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
Model.shared = isPublic;
|
Model.shared = isPublic;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
var EventEmitter = require('events').EventEmitter;
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
module.exports = browserExpress;
|
module.exports = browserExpress;
|
||||||
|
|
||||||
function browserExpress() {
|
function browserExpress() {
|
||||||
|
@ -10,6 +13,8 @@ function BrowserExpress() {
|
||||||
this.settings = {};
|
this.settings = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util.inherits(BrowserExpress, EventEmitter);
|
||||||
|
|
||||||
BrowserExpress.prototype.set = function(key, value) {
|
BrowserExpress.prototype.set = function(key, value) {
|
||||||
if (arguments.length == 1) {
|
if (arguments.length == 1) {
|
||||||
return this.get(key);
|
return this.get(key);
|
||||||
|
|
|
@ -59,10 +59,17 @@ MailConnector.prototype.setupTransport = function(setting) {
|
||||||
connector.transports = connector.transports || [];
|
connector.transports = connector.transports || [];
|
||||||
connector.transportsIndex = connector.transportsIndex || {};
|
connector.transportsIndex = connector.transportsIndex || {};
|
||||||
|
|
||||||
var transportModuleName = 'nodemailer-' + (setting.type || 'STUB').toLowerCase() + '-transport';
|
var transport;
|
||||||
var transportModule = require(transportModuleName);
|
var transportType = (setting.type || 'STUB').toLowerCase();
|
||||||
|
if (transportType === 'direct') {
|
||||||
var transport = mailer.createTransport(transportModule(setting));
|
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.transportsIndex[setting.type] = transport;
|
||||||
connector.transports.push(transport);
|
connector.transports.push(transport);
|
||||||
|
|
|
@ -136,7 +136,8 @@ Model.setup = function () {
|
||||||
|
|
||||||
var idDesc = ModelCtor.modelName + ' id';
|
var idDesc = ModelCtor.modelName + ' id';
|
||||||
ModelCtor.sharedCtor.accepts = [
|
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'}}
|
// {arg: 'instance', type: 'object', http: {source: 'body'}}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -347,6 +348,7 @@ Model.belongsToRemoting = function(relationName, relation, define) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Model.hasManyRemoting = function (relationName, relation, define) {
|
Model.hasManyRemoting = function (relationName, relation, define) {
|
||||||
|
var toModelName = relation.modelTo.modelName;
|
||||||
var findByIdFunc = this.prototype['__findById__' + relationName];
|
var findByIdFunc = this.prototype['__findById__' + relationName];
|
||||||
define('__findById__' + relationName, {
|
define('__findById__' + relationName, {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
|
@ -355,7 +357,7 @@ Model.hasManyRemoting = function (relationName, relation, define) {
|
||||||
description: 'Foreign key for ' + relationName, required: true,
|
description: 'Foreign key for ' + relationName, required: true,
|
||||||
http: {source: 'path'}},
|
http: {source: 'path'}},
|
||||||
description: 'Find a related item by id for ' + relationName,
|
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);
|
}, findByIdFunc);
|
||||||
|
|
||||||
var destroyByIdFunc = this.prototype['__destroyById__' + relationName];
|
var destroyByIdFunc = this.prototype['__destroyById__' + relationName];
|
||||||
|
@ -373,11 +375,14 @@ Model.hasManyRemoting = function (relationName, relation, define) {
|
||||||
define('__updateById__' + relationName, {
|
define('__updateById__' + relationName, {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: {verb: 'put', path: '/' + relationName + '/:fk'},
|
http: {verb: 'put', path: '/' + relationName + '/:fk'},
|
||||||
accepts: {arg: 'fk', type: 'any',
|
accepts: [
|
||||||
description: 'Foreign key for ' + relationName, required: true,
|
{arg: 'fk', type: 'any',
|
||||||
http: {source: 'path'}},
|
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,
|
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);
|
}, updateByIdFunc);
|
||||||
|
|
||||||
if (relation.modelThrough) {
|
if (relation.modelThrough) {
|
||||||
|
@ -432,7 +437,7 @@ Model.scopeRemoting = function(relationName, relation, define) {
|
||||||
define('__create__' + relationName, {
|
define('__create__' + relationName, {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: {verb: 'post', path: '/' + relationName},
|
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.',
|
description: 'Creates a new instance in ' + relationName + ' of this model.',
|
||||||
returns: {arg: 'data', type: toModelName, root: true}
|
returns: {arg: 'data', type: toModelName, root: true}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "loopback",
|
"name": "loopback",
|
||||||
"description": "LoopBack: Open API Framework for Node.js",
|
"description": "LoopBack: Open Source Framework for Node.js",
|
||||||
"homepage": "http://loopback.io",
|
"homepage": "http://loopback.io",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"restful",
|
"restful",
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
"mobile",
|
"mobile",
|
||||||
"mBaaS"
|
"mBaaS"
|
||||||
],
|
],
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "grunt mocha-and-karma"
|
"test": "grunt mocha-and-karma"
|
||||||
},
|
},
|
||||||
|
|
|
@ -47,6 +47,18 @@ describe('app', function() {
|
||||||
expect(app.models.Color).to.equal(Color);
|
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) {
|
it.onServer('updates REST API when a new model is added', function(done) {
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
request(app).get('/colors').expect(404, function(err, res) {
|
request(app).get('/colors').expect(404, function(err, res) {
|
||||||
|
|
|
@ -1,6 +1,30 @@
|
||||||
var loopback = require('../');
|
var loopback = require('../');
|
||||||
var MyEmail;
|
var MyEmail;
|
||||||
var assert = require('assert');
|
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 () {
|
describe('Email and SMTP', function () {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
|
|
Loading…
Reference in New Issue