Merge pull request #9 from strongloop/configure-models
Configure models
This commit is contained in:
commit
fccc6e147a
|
@ -25,3 +25,12 @@ app.listen();
|
||||||
|
|
||||||
See [API docs](http://apidocs.strongloop.com/loopback-boot/) for
|
See [API docs](http://apidocs.strongloop.com/loopback-boot/) for
|
||||||
complete API reference.
|
complete API reference.
|
||||||
|
|
||||||
|
## Versions
|
||||||
|
|
||||||
|
The version range `1.x` is backwards compatible with `app.boot` provided
|
||||||
|
by LoopBack 1.x versions and the project layout scaffolded by `slc lb project`
|
||||||
|
up to slc version 2.5.
|
||||||
|
|
||||||
|
The version range `2.x` supports the new project layout as scaffolded by
|
||||||
|
`yo loopback`.
|
||||||
|
|
|
@ -46,6 +46,7 @@ contained in the browser bundle:
|
||||||
/*-- app.js --*/
|
/*-- app.js --*/
|
||||||
var loopback = require('loopback');
|
var loopback = require('loopback');
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
|
require('./models');
|
||||||
|
|
||||||
var app = module.exports = loopback();
|
var app = module.exports = loopback();
|
||||||
boot(app);
|
boot(app);
|
||||||
|
|
|
@ -48,3 +48,124 @@ The following is example JSON for two `Model` definitions:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Migrating from 1.x to 2.x
|
||||||
|
|
||||||
|
**Starting point: a sample 1.x project**
|
||||||
|
|
||||||
|
*models.json*
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"car": {
|
||||||
|
"properties": {
|
||||||
|
"color": "string",
|
||||||
|
},
|
||||||
|
"dataSource": "db"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*models/car.js*
|
||||||
|
|
||||||
|
```js
|
||||||
|
var app = require('../app');
|
||||||
|
var Car = app.models.Car;
|
||||||
|
|
||||||
|
Car.prototype.honk = function() {
|
||||||
|
// make some noise
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
*app.js*
|
||||||
|
```js
|
||||||
|
var loopback = require('loopback');
|
||||||
|
var boot = require('loopback-boot');
|
||||||
|
var app = loopback();
|
||||||
|
boot(app, __dirname);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Model definitions & configurations
|
||||||
|
|
||||||
|
**The 2.x version of loopback-boot no longer creates Models, it's up to the
|
||||||
|
developer to create them before booting the app.**
|
||||||
|
|
||||||
|
The folder `models/` has a different semantincs in 2.x than in 1.x. Instead
|
||||||
|
of extending Models already defined by `app.boot` and `models.json`,
|
||||||
|
it is an encapsulated component that defines all Models independently of
|
||||||
|
any application that may use them.
|
||||||
|
|
||||||
|
Perform the following steps to update a 1.x project for loopback-boot 2.x.
|
||||||
|
All code samples are referring to the sample project described above.
|
||||||
|
|
||||||
|
1. Move all Model-definition metadata from `models.json`
|
||||||
|
to new per-model json files in `models/` directory.
|
||||||
|
|
||||||
|
*models/car.json*
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "car",
|
||||||
|
"properties": {
|
||||||
|
"color": "string",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*models.json*
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"car": {
|
||||||
|
"dataSource": "db"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Change per-model javascript files to build and export the Model class:
|
||||||
|
|
||||||
|
*models/car.js*
|
||||||
|
|
||||||
|
```js
|
||||||
|
var loopback = require('loopback');
|
||||||
|
var Car = module.exports = loopback.createModel(require('./car.json'));
|
||||||
|
|
||||||
|
Car.prototype.honk = function() {
|
||||||
|
// make some noise
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Add a new file `models/index.js` to build all models:
|
||||||
|
|
||||||
|
*models/index.js*
|
||||||
|
|
||||||
|
```js
|
||||||
|
exports.Car = require('./car');
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Modify the main application file to load model definitions before booting
|
||||||
|
the application.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var loopback = require('loopback');
|
||||||
|
var boot = require('loopback-boot');
|
||||||
|
require('./models');
|
||||||
|
|
||||||
|
var app = loopback();
|
||||||
|
boot(app, __dirname);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Attaching built-in models
|
||||||
|
|
||||||
|
Models provided by LoopBack, such as `User` or `Role`, are no longer
|
||||||
|
automatically attached to default data-sources. The data-source configuration
|
||||||
|
entry `defaultForType` is silently ignored.
|
||||||
|
|
||||||
|
You have to explicitly configure all built-in models used by your application
|
||||||
|
in the `models.json` file.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"Role": { "dataSource": "db" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
35
index.js
35
index.js
|
@ -16,10 +16,10 @@ var addInstructionsToBrowserify = require('./lib/bundler');
|
||||||
* 1. Creates DataSources from the `datasources.json` file in the application
|
* 1. Creates DataSources from the `datasources.json` file in the application
|
||||||
* root directory.
|
* root directory.
|
||||||
*
|
*
|
||||||
* 2. Creates Models from the `models.json` file in the application
|
* 2. Configures Models from the `models.json` file in the application
|
||||||
* root directory.
|
* root directory.
|
||||||
*
|
*
|
||||||
* If the argument is an object, then it looks for `model`, `dataSources`,
|
* If the argument is an object, then it looks for `models`, `dataSources`,
|
||||||
* and `appRootDir` properties of the object.
|
* and `appRootDir` properties of the object.
|
||||||
* If the object has no `appRootDir` property then it sets the current working
|
* If the object has no `appRootDir` property then it sets the current working
|
||||||
* directory as the application root directory.
|
* directory as the application root directory.
|
||||||
|
@ -27,32 +27,37 @@ var addInstructionsToBrowserify = require('./lib/bundler');
|
||||||
*
|
*
|
||||||
* 1. Creates DataSources from the `options.dataSources` object.
|
* 1. Creates DataSources from the `options.dataSources` object.
|
||||||
*
|
*
|
||||||
* 2. Creates Models from the `options.models` object.
|
* 2. Configures Models from the `options.models` object.
|
||||||
*
|
*
|
||||||
* In both cases, the function loads JavaScript files in the `/models` and
|
* In both cases, the function loads JavaScript files in the
|
||||||
* `/boot` subdirectories of the application root directory with `require()`.
|
* `/boot` subdirectory of the application root directory with `require()`.
|
||||||
|
*
|
||||||
|
* **NOTE:** The version 2.0 of loopback-boot changed the way how models
|
||||||
|
* are created. loopback-boot no longer creates the models for you,
|
||||||
|
* the `models.json` file contains only configuration options like
|
||||||
|
* dataSource and extra relations.
|
||||||
*
|
*
|
||||||
* **NOTE:** mixing `app.boot()` and `app.model(name, config)` in multiple
|
* **NOTE:** mixing `app.boot()` and `app.model(name, config)` in multiple
|
||||||
* files may result in models being **undefined** due to race conditions.
|
* files may result in models being **undefined** due to race conditions.
|
||||||
* To avoid this when using `app.boot()` make sure all models are passed
|
* To avoid this when using `app.boot()` make sure all models are passed
|
||||||
* as part of the `models` definition.
|
* as part of the `models` configuration.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* Throws an error if the config object is not valid or if boot fails.
|
* Throws an error if the config object is not valid or if boot fails.
|
||||||
*
|
*
|
||||||
* @param app LoopBack application created by `loopback()`.
|
* @param app LoopBack application created by `loopback()`.
|
||||||
* @options {String|Object} options Boot options; If String, this is
|
* @options {String|Object} options Boot options; If String, this is
|
||||||
* the application root directory; if object, has below properties.
|
* the application root directory; if object, has below properties.
|
||||||
* @property {String} appRootDir Directory to use when loading JSON and
|
* @property {String} [appRootDir] Directory to use when loading JSON and
|
||||||
* JavaScript files (optional).
|
* JavaScript files.
|
||||||
* Defaults to the current directory (`process.cwd()`).
|
* Defaults to the current directory (`process.cwd()`).
|
||||||
* @property {Object} models Object containing `Model` definitions (optional).
|
* @property {Object} [models] Object containing `Model` configurations.
|
||||||
* @property {Object} dataSources Object containing `DataSource`
|
* @property {Object} [dataSources] Object containing `DataSource` definitions.
|
||||||
* definitions (optional).
|
* @property {String} [modelsRootDir] Directory to use when loading
|
||||||
* @property {String} modelsRootDir Directory to use when loading `models.json`
|
* `models.json`. Defaults to `appRootDir`.
|
||||||
* and `models/*.js`. Defaults to `appRootDir`.
|
* @property {String} [dsRootDir] Directory to use when loading
|
||||||
* @property {String} datasourcesRootDir Directory to use when loading
|
|
||||||
* `datasources.json`. Defaults to `appRootDir`.
|
* `datasources.json`. Defaults to `appRootDir`.
|
||||||
* @property {String} env Environment type, defaults to `process.env.NODE_ENV`
|
* @property {String} [env] Environment type, defaults to `process.env.NODE_ENV`
|
||||||
* or `development`. Common values are `development`, `staging` and
|
* or `development`. Common values are `development`, `staging` and
|
||||||
* `production`; however the applications are free to use any names.
|
* `production`; however the applications are free to use any names.
|
||||||
* @end
|
* @end
|
||||||
|
|
|
@ -32,7 +32,7 @@ module.exports = function compile(options) {
|
||||||
var modelsRootDir = options.modelsRootDir || appRootDir;
|
var modelsRootDir = options.modelsRootDir || appRootDir;
|
||||||
var modelsConfig = options.models ||
|
var modelsConfig = options.models ||
|
||||||
ConfigLoader.loadModels(modelsRootDir, env);
|
ConfigLoader.loadModels(modelsRootDir, env);
|
||||||
assertIsValidConfig('model', modelsConfig);
|
assertIsValidModelConfig(modelsConfig);
|
||||||
|
|
||||||
var dsRootDir = options.dsRootDir || appRootDir;
|
var dsRootDir = options.dsRootDir || appRootDir;
|
||||||
var dataSourcesConfig = options.dataSources ||
|
var dataSourcesConfig = options.dataSources ||
|
||||||
|
@ -40,7 +40,6 @@ module.exports = function compile(options) {
|
||||||
assertIsValidConfig('data source', dataSourcesConfig);
|
assertIsValidConfig('data source', dataSourcesConfig);
|
||||||
|
|
||||||
// require directories
|
// require directories
|
||||||
var modelsScripts = findScripts(path.join(modelsRootDir, 'models'));
|
|
||||||
var bootScripts = findScripts(path.join(appRootDir, 'boot'));
|
var bootScripts = findScripts(path.join(appRootDir, 'boot'));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -48,7 +47,6 @@ module.exports = function compile(options) {
|
||||||
dataSources: dataSourcesConfig,
|
dataSources: dataSourcesConfig,
|
||||||
models: modelsConfig,
|
models: modelsConfig,
|
||||||
files: {
|
files: {
|
||||||
models: modelsScripts,
|
|
||||||
boot: bootScripts
|
boot: bootScripts
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -61,6 +59,22 @@ function assertIsValidConfig(name, config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertIsValidModelConfig(config) {
|
||||||
|
assertIsValidConfig('model', config);
|
||||||
|
for (var name in config) {
|
||||||
|
var entry = config[name];
|
||||||
|
var options = entry.options || {};
|
||||||
|
var unsupported = entry.properties ||
|
||||||
|
entry.base || options.base ||
|
||||||
|
entry.plural || options.plural;
|
||||||
|
|
||||||
|
if (unsupported) {
|
||||||
|
throw new Error(
|
||||||
|
'The data in models.json is in the unsupported 1.x format.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all javascript files (except for those prefixed with _)
|
* Find all javascript files (except for those prefixed with _)
|
||||||
* and all directories.
|
* and all directories.
|
||||||
|
|
|
@ -20,7 +20,6 @@ module.exports = function execute(app, instructions) {
|
||||||
|
|
||||||
setupDataSources(app, instructions);
|
setupDataSources(app, instructions);
|
||||||
setupModels(app, instructions);
|
setupModels(app, instructions);
|
||||||
autoAttach();
|
|
||||||
|
|
||||||
runBootScripts(app, instructions);
|
runBootScripts(app, instructions);
|
||||||
|
|
||||||
|
@ -97,10 +96,12 @@ function setupDataSources(app, instructions) {
|
||||||
|
|
||||||
function setupModels(app, instructions) {
|
function setupModels(app, instructions) {
|
||||||
forEachKeyedObject(instructions.models, function(key, obj) {
|
forEachKeyedObject(instructions.models, function(key, obj) {
|
||||||
app.model(key, obj);
|
var model = loopback.getModel(key);
|
||||||
|
if (!model) {
|
||||||
|
throw new Error('Cannot configure unknown model ' + key);
|
||||||
|
}
|
||||||
|
app.model(model, obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
runScripts(app, instructions.files.models);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function forEachKeyedObject(obj, fn) {
|
function forEachKeyedObject(obj, fn) {
|
||||||
|
@ -115,16 +116,11 @@ function runScripts(app, list) {
|
||||||
if (!list || !list.length) return;
|
if (!list || !list.length) return;
|
||||||
list.forEach(function(filepath) {
|
list.forEach(function(filepath) {
|
||||||
var exports = tryRequire(filepath);
|
var exports = tryRequire(filepath);
|
||||||
if (isFunctionNotModelCtor(exports))
|
if (typeof exports === 'function')
|
||||||
exports(app);
|
exports(app);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function isFunctionNotModelCtor(fn) {
|
|
||||||
return typeof fn === 'function' &&
|
|
||||||
!(fn.prototype instanceof loopback.Model);
|
|
||||||
}
|
|
||||||
|
|
||||||
function tryRequire(modulePath) {
|
function tryRequire(modulePath) {
|
||||||
try {
|
try {
|
||||||
return require.apply(this, arguments);
|
return require.apply(this, arguments);
|
||||||
|
@ -138,19 +134,6 @@ function tryRequire(modulePath) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated, will be removed soon
|
|
||||||
function autoAttach() {
|
|
||||||
try {
|
|
||||||
loopback.autoAttach();
|
|
||||||
} catch(e) {
|
|
||||||
if(e.name === 'AssertionError') {
|
|
||||||
console.warn(e);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function runBootScripts(app, instructions) {
|
function runBootScripts(app, instructions) {
|
||||||
runScripts(app, instructions.files.boot);
|
runScripts(app, instructions.files.boot);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,6 @@ describe('compiler', function() {
|
||||||
},
|
},
|
||||||
models: {
|
models: {
|
||||||
'foo-bar-bat-baz': {
|
'foo-bar-bat-baz': {
|
||||||
options: {
|
|
||||||
plural: 'foo-bar-bat-bazzies'
|
|
||||||
},
|
|
||||||
dataSource: 'the-db'
|
dataSource: 'the-db'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -73,8 +70,8 @@ describe('compiler', function() {
|
||||||
describe('from directory', function() {
|
describe('from directory', function() {
|
||||||
it('loads config files', function() {
|
it('loads config files', function() {
|
||||||
var instructions = boot.compile(SIMPLE_APP);
|
var instructions = boot.compile(SIMPLE_APP);
|
||||||
assert(instructions.models.foo);
|
assert(instructions.models.User);
|
||||||
assert(instructions.models.foo.dataSource);
|
assert(instructions.models.User.dataSource);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('merges datasource configs from multiple files', function() {
|
it('merges datasource configs from multiple files', function() {
|
||||||
|
@ -189,15 +186,12 @@ describe('compiler', function() {
|
||||||
foo: { dataSource: 'db' }
|
foo: { dataSource: 'db' }
|
||||||
});
|
});
|
||||||
|
|
||||||
var fooJs = appdir.writeFileSync('custom/models/foo.js', '');
|
|
||||||
|
|
||||||
var instructions = boot.compile({
|
var instructions = boot.compile({
|
||||||
appRootDir: appdir.PATH,
|
appRootDir: appdir.PATH,
|
||||||
modelsRootDir: path.resolve(appdir.PATH, 'custom')
|
modelsRootDir: path.resolve(appdir.PATH, 'custom')
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(instructions.models).to.have.property('foo');
|
expect(instructions.models).to.have.property('foo');
|
||||||
expect(instructions.files.models).to.eql([fooJs]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('includes boot/*.js scripts', function() {
|
it('includes boot/*.js scripts', function() {
|
||||||
|
@ -208,13 +202,32 @@ describe('compiler', function() {
|
||||||
expect(instructions.files.boot).to.eql([initJs]);
|
expect(instructions.files.boot).to.eql([initJs]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('supports models/ subdirectires that are not require()able', function() {
|
it('ignores models/ subdirectory', function() {
|
||||||
appdir.createConfigFilesSync();
|
appdir.createConfigFilesSync();
|
||||||
appdir.writeFileSync('models/test/model.test.js',
|
appdir.writeFileSync('models/my-model.js', '');
|
||||||
'throw new Error("should not been called");');
|
|
||||||
var instructions = boot.compile(appdir.PATH);
|
var instructions = boot.compile(appdir.PATH);
|
||||||
|
|
||||||
expect(instructions.files.models).to.eql([]);
|
expect(instructions.files).to.not.have.property('models');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('throws when models.json contains `properties` from 1.x', function() {
|
||||||
|
appdir.createConfigFilesSync({}, {}, {
|
||||||
|
foo: { properties: { name: 'string' } }
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(function() { boot.compile(appdir.PATH); })
|
||||||
|
.to.throw(/unsupported 1\.x format/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws when models.json contains `options.base` from 1.x', function() {
|
||||||
|
appdir.createConfigFilesSync({}, {}, {
|
||||||
|
Customer: { options: { base: 'User' } }
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(function() { boot.compile(appdir.PATH); })
|
||||||
|
.to.throw(/unsupported 1\.x format/);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,6 +8,9 @@ var appdir = require('./helpers/appdir');
|
||||||
|
|
||||||
var SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-app');
|
var SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-app');
|
||||||
|
|
||||||
|
// ensure simple-app's models are known by loopback
|
||||||
|
require(path.join(SIMPLE_APP, '/models'));
|
||||||
|
|
||||||
var app;
|
var app;
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,10 +32,7 @@ describe('executor', function() {
|
||||||
baz: true
|
baz: true
|
||||||
},
|
},
|
||||||
models: {
|
models: {
|
||||||
'foo-bar-bat-baz': {
|
'User': {
|
||||||
options: {
|
|
||||||
plural: 'foo-bar-bat-bazzies'
|
|
||||||
},
|
|
||||||
dataSource: 'the-db'
|
dataSource: 'the-db'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -47,16 +47,17 @@ describe('executor', function() {
|
||||||
it('instantiates models', function() {
|
it('instantiates models', function() {
|
||||||
boot.execute(app, dummyInstructions);
|
boot.execute(app, dummyInstructions);
|
||||||
assert(app.models);
|
assert(app.models);
|
||||||
assert(app.models.FooBarBatBaz);
|
assert(app.models.User);
|
||||||
assert(app.models.fooBarBatBaz);
|
assert.equal(app.models.User, loopback.User,
|
||||||
assertValidDataSource(app.models.FooBarBatBaz.dataSource);
|
'Boot should not have extended loopback.User model');
|
||||||
assert.isFunc(app.models.FooBarBatBaz, 'find');
|
assertValidDataSource(app.models.User.dataSource);
|
||||||
assert.isFunc(app.models.FooBarBatBaz, 'create');
|
assert.isFunc(app.models.User, 'find');
|
||||||
|
assert.isFunc(app.models.User, 'create');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('attaches models to data sources', function() {
|
it('attaches models to data sources', function() {
|
||||||
boot.execute(app, dummyInstructions);
|
boot.execute(app, dummyInstructions);
|
||||||
assert.equal(app.models.FooBarBatBaz.dataSource, app.dataSources.theDb);
|
assert.equal(app.models.User.dataSource, app.dataSources.theDb);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('instantiates data sources', function() {
|
it('instantiates data sources', function() {
|
||||||
|
@ -67,6 +68,17 @@ describe('executor', function() {
|
||||||
assert(app.dataSources.TheDb);
|
assert(app.dataSources.TheDb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not call autoAttach', function() {
|
||||||
|
boot.execute(app, dummyInstructions);
|
||||||
|
|
||||||
|
// loopback-datasource-juggler quirk:
|
||||||
|
// Model.dataSources has modelBuilder as the default value,
|
||||||
|
// therefore it's not enough to assert a false-y value
|
||||||
|
var actual = loopback.Email.dataSource instanceof loopback.DataSource ?
|
||||||
|
'attached' : 'not attached';
|
||||||
|
expect(actual).to.equal('not attached');
|
||||||
|
});
|
||||||
|
|
||||||
describe('with boot and models files', function() {
|
describe('with boot and models files', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
boot.execute(app, simpleAppInstructions());
|
boot.execute(app, simpleAppInstructions());
|
||||||
|
@ -76,11 +88,6 @@ describe('executor', function() {
|
||||||
assert(process.loadedFooJS);
|
assert(process.loadedFooJS);
|
||||||
delete process.loadedFooJS;
|
delete process.loadedFooJS;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should run `models/*` files', function() {
|
|
||||||
assert(process.loadedBarJS);
|
|
||||||
delete process.loadedBarJS;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('with PaaS and npm env variables', function() {
|
describe('with PaaS and npm env variables', function() {
|
||||||
|
@ -165,15 +172,6 @@ describe('executor', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls function exported by models/model.js', function() {
|
|
||||||
var file = appdir.writeFileSync('models/model.js',
|
|
||||||
'module.exports = function(app) { app.fnCalled = true; };');
|
|
||||||
|
|
||||||
delete app.fnCalled;
|
|
||||||
boot.execute(app, someInstructions({ files: { models: [ file ] } }));
|
|
||||||
expect(app.fnCalled, 'exported fn was called').to.be.true();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls function exported by boot/init.js', function() {
|
it('calls function exported by boot/init.js', function() {
|
||||||
var file = appdir.writeFileSync('boot/init.js',
|
var file = appdir.writeFileSync('boot/init.js',
|
||||||
'module.exports = function(app) { app.fnCalled = true; };');
|
'module.exports = function(app) { app.fnCalled = true; };');
|
||||||
|
@ -182,19 +180,6 @@ describe('executor', function() {
|
||||||
boot.execute(app, someInstructions({ files: { boot: [ file ] } }));
|
boot.execute(app, someInstructions({ files: { boot: [ file ] } }));
|
||||||
expect(app.fnCalled, 'exported fn was called').to.be.true();
|
expect(app.fnCalled, 'exported fn was called').to.be.true();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not call Model ctor exported by models/model.json', function() {
|
|
||||||
var file = appdir.writeFileSync('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' +
|
|
||||||
'};');
|
|
||||||
|
|
||||||
delete global.fnCalled;
|
|
||||||
boot.execute(app, someInstructions({ files: { models: [ file ] } }));
|
|
||||||
expect(global.fnCalled, 'exported fn was called').to.be.undefined();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,7 +206,6 @@ function someInstructions(values) {
|
||||||
models: values.models || {},
|
models: values.models || {},
|
||||||
dataSources: values.dataSources || {},
|
dataSources: values.dataSources || {},
|
||||||
files: {
|
files: {
|
||||||
models: [],
|
|
||||||
boot: []
|
boot: []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"foo": {
|
"User": {
|
||||||
"dataSource": "db"
|
"dataSource": "db"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
process.loadedBarJS = true;
|
|
|
@ -1,11 +0,0 @@
|
||||||
var loopback = require('loopback');
|
|
||||||
|
|
||||||
// bootLoopBackApp() calls loopback.autoAttach
|
|
||||||
// which attempts to attach all models to default datasources
|
|
||||||
// one of those models is Email which requires 'email' datasource
|
|
||||||
loopback.setDefaultDataSourceForType('mail', {
|
|
||||||
connector: loopback.Mail,
|
|
||||||
transports: [
|
|
||||||
{type: 'STUB'}
|
|
||||||
]
|
|
||||||
});
|
|
Loading…
Reference in New Issue