app: implement `connector()` and `connectors`
Allow browserified applications to explicitly register connectors to use in data-sources via `app.connector(name, exportsFromRequire)`. Include built-in connectors like `Memory` and `Remote` in the registry. Modify `dataSourcesFromConfig()` to resolve the connector via `app.connectors` first and only then fall back to auto-require the connector module.
This commit is contained in:
parent
7508337d56
commit
94ec5c294a
|
@ -196,9 +196,30 @@ app.models = function () {
|
||||||
app.dataSource = function (name, config) {
|
app.dataSource = function (name, config) {
|
||||||
this.dataSources[name] =
|
this.dataSources[name] =
|
||||||
this.dataSources[classify(name)] =
|
this.dataSources[classify(name)] =
|
||||||
this.dataSources[camelize(name)] = dataSourcesFromConfig(config);
|
this.dataSources[camelize(name)] =
|
||||||
|
dataSourcesFromConfig(config, this.connectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a connector.
|
||||||
|
*
|
||||||
|
* When a new data-source is being added via `app.dataSource`, the connector
|
||||||
|
* name is looked up in the registered connectors first.
|
||||||
|
*
|
||||||
|
* Connectors are required to be explicitly registered only for applications
|
||||||
|
* using browserify, because browserify does not support dynamic require,
|
||||||
|
* which is used by LoopBack to automatically load the connector module.
|
||||||
|
*
|
||||||
|
* @param {String} name Name of the connector, e.g. 'mysql'.
|
||||||
|
* @param {Object} connector Connector object as returned
|
||||||
|
* by `require('loopback-connector-{name}')`.
|
||||||
|
*/
|
||||||
|
app.connector = function(name, connector) {
|
||||||
|
this.connectors[name] =
|
||||||
|
this.connectors[classify(name)] =
|
||||||
|
this.connectors[camelize(name)] = connector;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all remote objects.
|
* Get all remote objects.
|
||||||
* @returns {Object} [Remote objects](http://apidocs.strongloop.com/strong-remoting/#remoteobjectsoptions).
|
* @returns {Object} [Remote objects](http://apidocs.strongloop.com/strong-remoting/#remoteobjectsoptions).
|
||||||
|
@ -523,17 +544,22 @@ function camelize(str) {
|
||||||
return stringUtils.camelize(str);
|
return stringUtils.camelize(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dataSourcesFromConfig(config) {
|
function dataSourcesFromConfig(config, connectorRegistry) {
|
||||||
var connectorPath;
|
var connectorPath;
|
||||||
|
|
||||||
assert(typeof config === 'object',
|
assert(typeof config === 'object',
|
||||||
'cannont create data source without config object');
|
'cannont create data source without config object');
|
||||||
|
|
||||||
if(typeof config.connector === 'string') {
|
if(typeof config.connector === 'string') {
|
||||||
connectorPath = path.join(__dirname, 'connectors', config.connector+'.js');
|
var name = config.connector;
|
||||||
|
if (connectorRegistry[name]) {
|
||||||
|
config.connector = connectorRegistry[name];
|
||||||
|
} else {
|
||||||
|
connectorPath = path.join(__dirname, 'connectors', name + '.js');
|
||||||
|
|
||||||
if(fs.existsSync(connectorPath)) {
|
if (fs.existsSync(connectorPath)) {
|
||||||
config.connector = require(connectorPath);
|
config.connector = require(connectorPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,15 @@ function createApplication() {
|
||||||
// Create a new instance of datasources registry per each app instance
|
// Create a new instance of datasources registry per each app instance
|
||||||
app.datasources = app.dataSources = {};
|
app.datasources = app.dataSources = {};
|
||||||
|
|
||||||
|
// Create a new instance of connector registry per each app instance
|
||||||
|
app.connectors = {};
|
||||||
|
|
||||||
|
// Register built-in connectors. It's important to keep this code
|
||||||
|
// hand-written, so that all require() calls are static
|
||||||
|
// and thus browserify can process them (include connectors in the bundle)
|
||||||
|
app.connector('memory', loopback.Memory);
|
||||||
|
app.connector('remote', loopback.Remote);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,14 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('app.dataSource', function() {
|
||||||
|
it('looks up the connector in `app.connectors`', function() {
|
||||||
|
app.connector('custom', loopback.Memory);
|
||||||
|
app.dataSource('custom', { connector: 'custom' });
|
||||||
|
expect(app.dataSources.custom.name).to.equal(loopback.Memory.name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('app.boot([options])', function () {
|
describe('app.boot([options])', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
app.boot({
|
app.boot({
|
||||||
|
@ -502,4 +510,39 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('app.connectors', function() {
|
||||||
|
it('is unique per app instance', function() {
|
||||||
|
app.connectors.foo = 'bar';
|
||||||
|
var anotherApp = loopback();
|
||||||
|
expect(anotherApp.connectors.foo).to.equal(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes Remote connector', function() {
|
||||||
|
expect(app.connectors.remote).to.equal(loopback.Remote);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes Memory connector', function() {
|
||||||
|
expect(app.connectors.memory).to.equal(loopback.Memory);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('app.connector', function() {
|
||||||
|
// any connector will do
|
||||||
|
it('adds the connector to the registry', function() {
|
||||||
|
app.connector('foo-bar', loopback.Memory);
|
||||||
|
expect(app.connectors['foo-bar']).to.equal(loopback.Memory);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds a classified alias', function() {
|
||||||
|
app.connector('foo-bar', loopback.Memory);
|
||||||
|
expect(app.connectors.FooBar).to.equal(loopback.Memory);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds a camelized alias', function() {
|
||||||
|
app.connector('FOO-BAR', loopback.Memory);
|
||||||
|
console.log(app.connectors);
|
||||||
|
expect(app.connectors.FOOBAR).to.equal(loopback.Memory);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue