commit
04a2de9f35
154
docs/api.md
154
docs/api.md
|
@ -21,24 +21,158 @@ app.listen(3000);
|
||||||
> - see [express docs](http://expressjs.com/api.html) for details
|
> - see [express docs](http://expressjs.com/api.html) for details
|
||||||
> - supports [express / connect middleware](http://expressjs.com/api.html#middleware)
|
> - supports [express / connect middleware](http://expressjs.com/api.html#middleware)
|
||||||
|
|
||||||
#### app.model(Model)
|
#### app.boot([options])
|
||||||
|
|
||||||
Expose a `Model` to remote clients.
|
Initialize an application from an options object or a set of JSON and JavaScript files.
|
||||||
|
|
||||||
|
**What happens during an app _boot_?**
|
||||||
|
|
||||||
|
1. **DataSources** are created from an `options.dataSources` object or `datasources.json` in the current directory
|
||||||
|
2. **Models** are created from an `options.models` object or `models.json` in the current directory
|
||||||
|
3. Any JavaScript files in the `./models` directory are loaded with `require()`.
|
||||||
|
|
||||||
|
**Options**
|
||||||
|
|
||||||
|
- `cwd` - _optional_ - the directory to use when loading JSON and JavaScript files
|
||||||
|
- `models` - _optional_ - an object containing `Model` definitions
|
||||||
|
- `dataSources` - _optional_ - an object containing `DataSource` definitions
|
||||||
|
|
||||||
|
> **NOTE:** mixing `app.boot()` and `app.model(name, config)` in multiple files may result
|
||||||
|
> in models being **undefined** due to race conditions. To avoid this when using `app.boot()`
|
||||||
|
> make sure all models are passed as part of the `models` definition.
|
||||||
|
|
||||||
|
<a name="model-definition"></a>
|
||||||
|
**Model Definitions**
|
||||||
|
|
||||||
|
The following is an example of an object containing two `Model` definitions: "location" and "inventory".
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// create a testing data source
|
{
|
||||||
var memory = loopback.memory();
|
"dealership": {
|
||||||
var Color = memory.createModel('color', {name: String});
|
// a reference, by name, to a dataSource definition
|
||||||
|
"dataSource": "my-db",
|
||||||
|
// the options passed to Model.extend(name, properties, options)
|
||||||
|
"options": {
|
||||||
|
"relationships": {
|
||||||
|
"cars": {
|
||||||
|
"type": "hasMany",
|
||||||
|
"model": "Car",
|
||||||
|
"foreignKey": "dealerId"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"remoteMethods": {
|
||||||
|
"nearby": {
|
||||||
|
"description": "Find nearby locations around the geo point",
|
||||||
|
"accepts": [
|
||||||
|
{"arg": "here", "type": "GeoPoint", "required": true, "description": "geo location (lat & lng)"}
|
||||||
|
],
|
||||||
|
"returns": {"arg": "locations", "root": true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// the properties passed to Model.extend(name, properties, options)
|
||||||
|
"properties": {
|
||||||
|
"id": {"id": true},
|
||||||
|
"name": "String",
|
||||||
|
"zip": "Number",
|
||||||
|
"address": "String"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"car": {
|
||||||
|
"dataSource": "my-db"
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true,
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"make": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"model": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
app.model(Color);
|
**Model Definition Properties**
|
||||||
app.use(loopback.rest());
|
|
||||||
|
- `dataSource` - **required** - a string containing the name of the data source definition to attach the `Model` to
|
||||||
|
- `options` - _optional_ - an object containing `Model` options
|
||||||
|
- `properties` _optional_ - an object defining the `Model` properties in [LoopBack Definition Language](http://docs.strongloop.com/loopback-datasource-juggler/#loopback-definition-language)
|
||||||
|
|
||||||
|
**DataSource Definition Properties**
|
||||||
|
|
||||||
|
- `connector` - **required** - the name of the [connector](#working-with-data-sources-and-connectors)
|
||||||
|
|
||||||
|
#### app.model(name, definition)
|
||||||
|
|
||||||
|
Define a `Model` and export it for use by remote clients.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// declare a DataSource
|
||||||
|
app.boot({
|
||||||
|
dataSources: {
|
||||||
|
db: {
|
||||||
|
connector: 'mongodb',
|
||||||
|
url: 'mongodb://localhost:27015/my-database-name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// describe a model
|
||||||
|
var modelDefinition = {dataSource: 'db'};
|
||||||
|
|
||||||
|
// create the model
|
||||||
|
var Product = app.model('product', modelDefinition);
|
||||||
|
|
||||||
|
// use the model api
|
||||||
|
Product.create({name: 'pencil', price: 0.99}, console.log);
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note** - this will expose all [shared methods](#shared-methods) on the model.
|
> **Note** - this will expose all [shared methods](#shared-methods) on the model.
|
||||||
|
|
||||||
|
You may also export an existing `Model` by calling `app.model(Model)` like the example below.
|
||||||
|
|
||||||
|
#### app.models.MyModel
|
||||||
|
|
||||||
|
All models are avaialbe from the `loopback.models` object. In the following
|
||||||
|
example the `Product` and `CustomerReceipt` models are accessed using
|
||||||
|
the `models` object.
|
||||||
|
|
||||||
|
> **NOTE:** you must call `app.boot()` in order to build the app.models object.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var loopback = require('loopback');
|
||||||
|
var app = loopback();
|
||||||
|
app.boot({
|
||||||
|
dataSources: {
|
||||||
|
db: {connector: 'memory'}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app.model('product', {dataSource: 'db'});
|
||||||
|
app.model('customer-receipt', {dataSource: 'db'});
|
||||||
|
|
||||||
|
// available based on the given name
|
||||||
|
var Product = app.models.Product;
|
||||||
|
|
||||||
|
// also available as camelCase
|
||||||
|
var product = app.models.product;
|
||||||
|
|
||||||
|
// multi-word models are avaiable as pascal cased
|
||||||
|
var CustomerReceipt = app.models.CustomerReceipt;
|
||||||
|
|
||||||
|
// also available as camelCase
|
||||||
|
var customerReceipt = app.models.customerReceipt;
|
||||||
|
```
|
||||||
|
|
||||||
#### app.models()
|
#### app.models()
|
||||||
|
|
||||||
Get the app's exposed models.
|
Get the app's exported models. Only models defined using `app.model()` will show up in this list.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var models = app.models();
|
var models = app.models();
|
||||||
|
@ -47,7 +181,7 @@ models.forEach(function (Model) {
|
||||||
console.log(Model.modelName); // color
|
console.log(Model.modelName); // color
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### app.docs(options)
|
#### app.docs(options)
|
||||||
|
|
||||||
Enable swagger REST API documentation.
|
Enable swagger REST API documentation.
|
||||||
|
|
|
@ -5,8 +5,11 @@
|
||||||
var DataSource = require('loopback-datasource-juggler').DataSource
|
var DataSource = require('loopback-datasource-juggler').DataSource
|
||||||
, ModelBuilder = require('loopback-datasource-juggler').ModelBuilder
|
, ModelBuilder = require('loopback-datasource-juggler').ModelBuilder
|
||||||
, assert = require('assert')
|
, assert = require('assert')
|
||||||
|
, fs = require('fs')
|
||||||
, RemoteObjects = require('strong-remoting')
|
, RemoteObjects = require('strong-remoting')
|
||||||
, swagger = require('strong-remoting/ext/swagger');
|
, swagger = require('strong-remoting/ext/swagger')
|
||||||
|
, stringUtils = require('underscore.string')
|
||||||
|
, path = require('path');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export the app prototype.
|
* Export the app prototype.
|
||||||
|
@ -52,12 +55,28 @@ app._models = [];
|
||||||
* @param Model {Model}
|
* @param Model {Model}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.model = function (Model) {
|
app.model = function (Model, config) {
|
||||||
this.remotes().exports[Model.pluralModelName] = Model;
|
if(arguments.length === 1) {
|
||||||
this._models.push(Model);
|
assert(typeof Model === 'function', 'app.model(Model) => Model must be a function / constructor');
|
||||||
Model.shared = true;
|
assert(Model.pluralModelName, 'Model must have a "pluralModelName" property');
|
||||||
Model.app = this;
|
this.remotes().exports[Model.pluralModelName] = Model;
|
||||||
Model.emit('attached', this);
|
this._models.push(Model);
|
||||||
|
Model.shared = true;
|
||||||
|
Model.app = this;
|
||||||
|
Model.emit('attached', this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var modelName = Model;
|
||||||
|
assert(typeof modelName === 'string', 'app.model(name, config) => "name" name must be a string');
|
||||||
|
|
||||||
|
Model =
|
||||||
|
this.models[modelName] =
|
||||||
|
this.models[classify(modelName)] =
|
||||||
|
this.models[camelize(modelName)] = modelFromConfig(modelName, config, this);
|
||||||
|
|
||||||
|
this.model(Model);
|
||||||
|
|
||||||
|
return Model;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,6 +87,16 @@ app.models = function () {
|
||||||
return this._models;
|
return this._models;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a DataSource.
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.dataSource = function (name, config) {
|
||||||
|
this.dataSources[name] =
|
||||||
|
this.dataSources[classify(name)] =
|
||||||
|
this.dataSources[camelize(name)] = dataSourcesFromConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all remote objects.
|
* Get all remote objects.
|
||||||
*/
|
*/
|
||||||
|
@ -120,3 +149,204 @@ app.handler = function (type) {
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object to store dataSource instances.
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.dataSources = app.datasources = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the app using JSON and JavaScript files.
|
||||||
|
*
|
||||||
|
* @throws {Error} If config is not valid
|
||||||
|
* @throws {Error} If boot fails
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.boot = function(options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
if(typeof options === 'string') {
|
||||||
|
options = {appRootDir: options};
|
||||||
|
}
|
||||||
|
var app = this;
|
||||||
|
var appRootDir = options.appRootDir = options.appRootDir || process.cwd();
|
||||||
|
var ctx = {};
|
||||||
|
var appConfig = options.app;
|
||||||
|
var modelConfig = options.models;
|
||||||
|
var dataSourceConfig = options.dataSources;
|
||||||
|
|
||||||
|
if(!appConfig) {
|
||||||
|
appConfig = tryReadConfig(appRootDir, 'app') || {};
|
||||||
|
}
|
||||||
|
if(!modelConfig) {
|
||||||
|
modelConfig = tryReadConfig(appRootDir, 'models') || {};
|
||||||
|
}
|
||||||
|
if(!dataSourceConfig) {
|
||||||
|
dataSourceConfig = tryReadConfig(appRootDir, 'datasources') || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
assertIsValidConfig('app', appConfig);
|
||||||
|
assertIsValidConfig('model', modelConfig);
|
||||||
|
assertIsValidConfig('data source', dataSourceConfig);
|
||||||
|
|
||||||
|
if(appConfig.host !== undefined) {
|
||||||
|
assert(typeof appConfig.host === 'string', 'app.host must be a string');
|
||||||
|
app.set('host', appConfig.host);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(appConfig.port !== undefined) {
|
||||||
|
var portType = typeof appConfig.port;
|
||||||
|
assert(portType === 'string' || portType === 'number', 'app.port must be a string or number');
|
||||||
|
app.set('port', appConfig.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// instantiate data sources
|
||||||
|
forEachKeyedObject(dataSourceConfig, function(key, obj) {
|
||||||
|
app.dataSource(key, obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
// instantiate models
|
||||||
|
forEachKeyedObject(modelConfig, function(key, obj) {
|
||||||
|
app.model(key, obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
// require directories
|
||||||
|
var requiredModels = requireDir(path.join(appRootDir, 'models'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertIsValidConfig(name, config) {
|
||||||
|
if(config) {
|
||||||
|
assert(typeof config === 'object', name + ' config must be a valid JSON object');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function forEachKeyedObject(obj, fn) {
|
||||||
|
if(typeof obj !== 'object') return;
|
||||||
|
|
||||||
|
Object.keys(obj).forEach(function(key) {
|
||||||
|
fn(key, obj[key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function classify(str) {
|
||||||
|
return stringUtils.classify(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function camelize(str) {
|
||||||
|
return stringUtils.camelize(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dataSourcesFromConfig(config) {
|
||||||
|
var connectorPath;
|
||||||
|
|
||||||
|
assert(typeof config === 'object',
|
||||||
|
'cannont create data source without config object');
|
||||||
|
|
||||||
|
if(typeof config.connector === 'string') {
|
||||||
|
connectorPath = path.join(__dirname, 'connectors', config.connector+'.js');
|
||||||
|
|
||||||
|
if(fs.existsSync(connectorPath)) {
|
||||||
|
config.connector = require(connectorPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return require('./loopback').createDataSource(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
function modelFromConfig(name, config, app) {
|
||||||
|
var ModelCtor = require('./loopback').createModel(name, config.properties, config.options);
|
||||||
|
var dataSource = app.dataSources[config.dataSource];
|
||||||
|
|
||||||
|
assert(isDataSource(dataSource), name + ' is referencing a dataSource that does not exist: "'+ config.dataSource +'"');
|
||||||
|
|
||||||
|
ModelCtor.attachTo(dataSource);
|
||||||
|
return ModelCtor;
|
||||||
|
}
|
||||||
|
|
||||||
|
function requireDir(dir, basenames) {
|
||||||
|
assert(dir, 'cannot require directory contents without directory name');
|
||||||
|
|
||||||
|
var requires = {};
|
||||||
|
|
||||||
|
if (arguments.length === 2) {
|
||||||
|
// if basenames argument is passed, explicitly include those files
|
||||||
|
basenames.forEach(function (basename) {
|
||||||
|
var filepath = Path.resolve(Path.join(dir, basename));
|
||||||
|
requires[basename] = tryRequire(filepath);
|
||||||
|
});
|
||||||
|
} else if (arguments.length === 1) {
|
||||||
|
// if basenames arguments isn't passed, require all javascript
|
||||||
|
// files (except for those prefixed with _) and all directories
|
||||||
|
|
||||||
|
var files = tryReadDir(dir);
|
||||||
|
|
||||||
|
// sort files in lowercase alpha for linux
|
||||||
|
files.sort(function (a,b) {
|
||||||
|
a = a.toLowerCase();
|
||||||
|
b = b.toLowerCase();
|
||||||
|
|
||||||
|
if (a < b) {
|
||||||
|
return -1;
|
||||||
|
} else if (b < a) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
files.forEach(function (filename) {
|
||||||
|
// ignore index.js and files prefixed with underscore
|
||||||
|
if ((filename === 'index.js') || (filename[0] === '_')) { return; }
|
||||||
|
|
||||||
|
var filepath = path.resolve(path.join(dir, filename));
|
||||||
|
var ext = path.extname(filename);
|
||||||
|
var stats = fs.statSync(filepath);
|
||||||
|
|
||||||
|
// only require files supported by require.extensions (.txt .md etc.)
|
||||||
|
if (stats.isFile() && !(ext in require.extensions)) { return; }
|
||||||
|
|
||||||
|
var basename = path.basename(filename, ext);
|
||||||
|
|
||||||
|
requires[basename] = tryRequire(filepath);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return requires;
|
||||||
|
};
|
||||||
|
|
||||||
|
function tryRequire(modulePath) {
|
||||||
|
try {
|
||||||
|
return require.apply(this, arguments);
|
||||||
|
} catch(e) {
|
||||||
|
console.error('failed to require "%s"', modulePath);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryReadDir() {
|
||||||
|
try {
|
||||||
|
return fs.readdirSync.apply(fs, arguments);
|
||||||
|
} catch(e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isModelCtor(obj) {
|
||||||
|
return typeof obj === 'function' && obj.modelName && obj.name === 'ModelCtor';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDataSource(obj) {
|
||||||
|
return obj instanceof DataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryReadConfig(cwd, fileName) {
|
||||||
|
try {
|
||||||
|
return require(path.join(cwd, fileName + '.json'));
|
||||||
|
} catch(e) {
|
||||||
|
if(e.code !== "MODULE_NOT_FOUND") {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
12
package.json
12
package.json
|
@ -1,7 +1,14 @@
|
||||||
{
|
{
|
||||||
"name": "loopback",
|
"name": "loopback",
|
||||||
"description": "LoopBack: Open Mobile Platform for Node.js",
|
"description": "LoopBack: Open Mobile Platform for Node.js",
|
||||||
"keywords": [ "StrongLoop", "LoopBack", "Mobile", "Backend", "Platform", "mBaaS" ],
|
"keywords": [
|
||||||
|
"StrongLoop",
|
||||||
|
"LoopBack",
|
||||||
|
"Mobile",
|
||||||
|
"Backend",
|
||||||
|
"Platform",
|
||||||
|
"mBaaS"
|
||||||
|
],
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha -R spec",
|
"test": "mocha -R spec",
|
||||||
|
@ -20,7 +27,8 @@
|
||||||
"passport-local": "~0.1.6",
|
"passport-local": "~0.1.6",
|
||||||
"nodemailer": "~0.4.4",
|
"nodemailer": "~0.4.4",
|
||||||
"ejs": "~0.8.4",
|
"ejs": "~0.8.4",
|
||||||
"bcryptjs": "~0.7.10"
|
"bcryptjs": "~0.7.10",
|
||||||
|
"underscore.string": "~2.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"blanket": "~1.1.5",
|
"blanket": "~1.1.5",
|
||||||
|
|
107
test/app.test.js
107
test/app.test.js
|
@ -2,6 +2,7 @@ describe('app', function() {
|
||||||
|
|
||||||
describe('app.model(Model)', function() {
|
describe('app.model(Model)', function() {
|
||||||
it("Expose a `Model` to remote clients", function() {
|
it("Expose a `Model` to remote clients", function() {
|
||||||
|
var app = loopback();
|
||||||
var memory = loopback.createDataSource({connector: loopback.Memory});
|
var memory = loopback.createDataSource({connector: loopback.Memory});
|
||||||
var Color = memory.createModel('color', {name: String});
|
var Color = memory.createModel('color', {name: String});
|
||||||
app.model(Color);
|
app.model(Color);
|
||||||
|
@ -9,13 +10,105 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('app.models()', function() {
|
describe('app.model(name, properties, options)', function () {
|
||||||
it("Get the app's exposed models", function() {
|
it('Sugar for defining a fully built model', function () {
|
||||||
var Color = loopback.createModel('color', {name: String});
|
var app = loopback();
|
||||||
var models = app.models();
|
app.boot({
|
||||||
|
app: {port: 3000, host: '127.0.0.1'},
|
||||||
|
dataSources: {
|
||||||
|
db: {
|
||||||
|
connector: 'memory'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.model('foo', {
|
||||||
|
dataSource: 'db'
|
||||||
|
});
|
||||||
|
|
||||||
|
var Foo = app.models.foo;
|
||||||
|
var f = new Foo;
|
||||||
|
|
||||||
|
assert(f instanceof loopback.Model);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
// describe('app.models()', function() {
|
||||||
|
// it("Get the app's exposed models", function() {
|
||||||
|
// var app = loopback();
|
||||||
|
// var models = app.models();
|
||||||
|
|
||||||
|
// models.forEach(function(m) {
|
||||||
|
// console.log(m.modelName);
|
||||||
|
// })
|
||||||
|
|
||||||
assert.equal(models.length, 1);
|
// assert.equal(models.length, 1);
|
||||||
assert.equal(models[0].modelName, 'color');
|
// assert.equal(models[0].modelName, 'color');
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
describe('app.boot([options])', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
var app = this.app = loopback();
|
||||||
|
|
||||||
|
app.boot({
|
||||||
|
app: {
|
||||||
|
port: 3000,
|
||||||
|
host: '127.0.0.1'
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
'foo-bar-bat-baz': {
|
||||||
|
options: {
|
||||||
|
plural: 'foo-bar-bat-bazzies'
|
||||||
|
},
|
||||||
|
dataSource: 'the-db'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataSources: {
|
||||||
|
'the-db': {
|
||||||
|
connector: 'memory'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Load configuration', function () {
|
||||||
|
assert.equal(this.app.get('port'), 3000);
|
||||||
|
assert.equal(this.app.get('host'), '127.0.0.1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Instantiate models', function () {
|
||||||
|
assert(app.models);
|
||||||
|
assert(app.models.FooBarBatBaz);
|
||||||
|
assert(app.models.fooBarBatBaz);
|
||||||
|
assertValidDataSource(app.models.FooBarBatBaz.dataSource);
|
||||||
|
assert.isFunc(app.models.FooBarBatBaz, 'find');
|
||||||
|
assert.isFunc(app.models.FooBarBatBaz, 'create');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Attach models to data sources', function () {
|
||||||
|
assert.equal(app.models.FooBarBatBaz.dataSource, app.dataSources.theDb);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Instantiate data sources', function () {
|
||||||
|
assert(app.dataSources);
|
||||||
|
assert(app.dataSources.theDb);
|
||||||
|
assertValidDataSource(app.dataSources.theDb);
|
||||||
|
assert(app.dataSources.TheDb);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
describe('app.boot(appRootDir)', function () {
|
||||||
|
it('Load config files', function () {
|
||||||
|
var app = loopback();
|
||||||
|
|
||||||
|
app.boot(require('path').join(__dirname, 'fixtures', 'simple-app'));
|
||||||
|
|
||||||
|
assert(app.models.foo);
|
||||||
|
assert(app.models.Foo);
|
||||||
|
assert(app.models.Foo.dataSource);
|
||||||
|
assert.isFunc(app.models.Foo, 'find');
|
||||||
|
assert.isFunc(app.models.Foo, 'create');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"port": 3000,
|
||||||
|
"host": "127.0.0.1"
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"db": {
|
||||||
|
"connector": "memory"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"foo": {
|
||||||
|
"dataSource": "db"
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,4 +28,4 @@ assertValidDataSource = function (dataSource) {
|
||||||
assert.isFunc = function (obj, name) {
|
assert.isFunc = function (obj, name) {
|
||||||
assert(obj, 'cannot assert function ' + name + ' on object that doesnt exist');
|
assert(obj, 'cannot assert function ' + name + ' on object that doesnt exist');
|
||||||
assert(typeof obj[name] === 'function', name + ' is not a function');
|
assert(typeof obj[name] === 'function', name + ' is not a function');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue