Pass `app` to fn exported by auto-required script
When a script in `models/` or `boot/` exports a function which is not a loopback.Model constructor, the bootstrapper immediatelly calls this exported function wit the current `app` object. This is providing a dependency injection mechanism for boot scripts, so that they no longer need to know where to find the `app` object. Note: the dependency injection is optional. Existing code getting `app` reference via `require('../app')` will continue to work.
This commit is contained in:
parent
9930934686
commit
3ba43e1197
21
index.js
21
index.js
|
@ -2,6 +2,7 @@ var assert = require('assert');
|
|||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var _ = require('underscore');
|
||||
var loopback = require('loopback');
|
||||
var ConfigLoader = require('./lib/config-loader');
|
||||
|
||||
/**
|
||||
|
@ -195,7 +196,7 @@ exports = module.exports = function bootLoopBackApp(app, options) {
|
|||
|
||||
// try to attach models to dataSources by type
|
||||
try {
|
||||
require('loopback').autoAttach();
|
||||
loopback.autoAttach();
|
||||
} catch(e) {
|
||||
if(e.name === 'AssertionError') {
|
||||
console.warn(e);
|
||||
|
@ -213,8 +214,8 @@ exports = module.exports = function bootLoopBackApp(app, options) {
|
|||
}
|
||||
|
||||
// require directories
|
||||
requireDir(path.join(modelsRootDir, 'models'));
|
||||
requireDir(path.join(appRootDir, 'boot'));
|
||||
requireDir(path.join(modelsRootDir, 'models'), app);
|
||||
requireDir(path.join(appRootDir, 'boot'), app);
|
||||
};
|
||||
|
||||
function assertIsValidConfig(name, config) {
|
||||
|
@ -232,7 +233,7 @@ function forEachKeyedObject(obj, fn) {
|
|||
});
|
||||
}
|
||||
|
||||
function requireDir(dir) {
|
||||
function requireDir(dir, app) {
|
||||
assert(dir, 'cannot require directory contents without directory name');
|
||||
|
||||
var requires = {};
|
||||
|
@ -271,9 +272,12 @@ function requireDir(dir) {
|
|||
return;
|
||||
}
|
||||
|
||||
var basename = path.basename(filename, ext);
|
||||
var exports = tryRequire(filepath);
|
||||
if (isFunctionNotModelCtor(exports))
|
||||
exports(app);
|
||||
|
||||
requires[basename] = tryRequire(filepath);
|
||||
var basename = path.basename(filename, ext);
|
||||
requires[basename] = exports;
|
||||
});
|
||||
|
||||
return requires;
|
||||
|
@ -296,4 +300,9 @@ function tryReadDir() {
|
|||
}
|
||||
}
|
||||
|
||||
function isFunctionNotModelCtor(fn) {
|
||||
return typeof fn === 'function' &&
|
||||
!(fn.prototype instanceof loopback.Model);
|
||||
}
|
||||
|
||||
exports.ConfigLoader = ConfigLoader;
|
||||
|
|
|
@ -342,6 +342,43 @@ describe('bootLoopBackApp', function() {
|
|||
expect(app.models).to.have.property('foo');
|
||||
expect(global.testData).to.have.property('foo', 'loaded');
|
||||
});
|
||||
|
||||
it('calls function exported by models/model.js', function() {
|
||||
givenAppInSandbox();
|
||||
writeAppFile('models/model.js',
|
||||
'module.exports = function(app) { app.fnCalled = true; };');
|
||||
|
||||
var app = loopback();
|
||||
delete app.fnCalled;
|
||||
boot(app, appDir);
|
||||
expect(app.fnCalled, 'exported fn was called').to.be.true();
|
||||
});
|
||||
|
||||
it('calls function exported by boot/init.js', function() {
|
||||
givenAppInSandbox();
|
||||
writeAppFile('boot/init.js',
|
||||
'module.exports = function(app) { app.fnCalled = true; };');
|
||||
|
||||
var app = loopback();
|
||||
delete app.fnCalled;
|
||||
boot(app, appDir);
|
||||
expect(app.fnCalled, 'exported fn was called').to.be.true();
|
||||
});
|
||||
|
||||
it('does not call Model ctor exported by models/model.json', function() {
|
||||
givenAppInSandbox();
|
||||
writeAppFile('models/model.js',
|
||||
'var loopback = require("loopback");\n' +
|
||||
'module.exports = loopback.Model.extend("foo");\n' +
|
||||
'module.exports.prototype._initProperties = function() {\n' +
|
||||
' global.fnCalled = true;\n' +
|
||||
'};');
|
||||
|
||||
var app = loopback();
|
||||
delete global.fnCalled;
|
||||
boot(app, appDir);
|
||||
expect(global.fnCalled, 'exported fn was called').to.be.undefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue