Merge 0.9 into master
This commit is contained in:
commit
a2308cbc1c
|
@ -13,7 +13,7 @@ v0.9.0
|
||||||
- [DataSource](#data-source)
|
- [DataSource](#data-source)
|
||||||
- [Connectors](#connectors)
|
- [Connectors](#connectors)
|
||||||
- [Loopback Types](#loopback-types)
|
- [Loopback Types](#loopback-types)
|
||||||
- [GeoPoint](#geo-point)
|
- [GeoPoint](#geo-point)
|
||||||
- [REST Router](#rest-router)
|
- [REST Router](#rest-router)
|
||||||
- [Bundled Models](#bundled-models)
|
- [Bundled Models](#bundled-models)
|
||||||
- [User](#user-model)
|
- [User](#user-model)
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
var models = require('../../lib/models');
|
||||||
|
|
||||||
|
var loopback = require('../../');
|
||||||
|
var app = loopback();
|
||||||
|
|
||||||
|
app.use(loopback.rest());
|
||||||
|
|
||||||
|
var dataSource = loopback.createDataSource('db', {connector: loopback.Memory});
|
||||||
|
|
||||||
|
var Application = models.Application(dataSource);
|
||||||
|
|
||||||
|
app.model(Application);
|
||||||
|
|
||||||
|
|
||||||
|
var data = {pushSettings: [
|
||||||
|
{ "platform": "apns",
|
||||||
|
"apns": {
|
||||||
|
"pushOptions": {
|
||||||
|
"gateway": "gateway.sandbox.push.apple.com",
|
||||||
|
"cert": "credentials/apns_cert_dev.pem",
|
||||||
|
"key": "credentials/apns_key_dev.pem"
|
||||||
|
},
|
||||||
|
|
||||||
|
"feedbackOptions": {
|
||||||
|
"gateway": "feedback.sandbox.push.apple.com",
|
||||||
|
"cert": "credentials/apns_cert_dev.pem",
|
||||||
|
"key": "credentials/apns_key_dev.pem",
|
||||||
|
"batchFeedback": true,
|
||||||
|
"interval": 300
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
]}
|
||||||
|
|
||||||
|
Application.create(data, function(err, data) {
|
||||||
|
console.log('Created: ', data.toObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Application.register('MyApp', 'My first mobile application', 'rfeng', function (err, result) {
|
||||||
|
console.log(result.toObject());
|
||||||
|
|
||||||
|
result.resetKeys(function (err, result) {
|
||||||
|
console.log(result.toObject());
|
||||||
|
});
|
||||||
|
});
|
|
@ -25,6 +25,21 @@ app.remotes = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose an object or Class remotely.
|
||||||
|
*
|
||||||
|
* @param {String} name The remote namespace (eg. url base)
|
||||||
|
* @param {Object|Function} obj The object to remote
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.remote = function (name, obj) {
|
||||||
|
// add the object to the remote exports
|
||||||
|
this.remotes().exports[name] = obj;
|
||||||
|
|
||||||
|
// clear the handlers cache
|
||||||
|
this._handlers = {};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a route by reference.
|
* Remove a route by reference.
|
||||||
*/
|
*/
|
||||||
|
@ -44,6 +59,7 @@ app.disuse = function (route) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app._models = [];
|
app._models = [];
|
||||||
|
app._services = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose a model.
|
* Expose a model.
|
||||||
|
@ -52,6 +68,8 @@ app._models = [];
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.model = function (Model) {
|
app.model = function (Model) {
|
||||||
|
var remotes = this.remotes();
|
||||||
|
|
||||||
this._models.push(Model);
|
this._models.push(Model);
|
||||||
Model.shared = true;
|
Model.shared = true;
|
||||||
Model.app = this;
|
Model.app = this;
|
||||||
|
@ -67,22 +85,28 @@ app.models = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all remote objects.
|
* Expose a service.
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
* @param {Service} service
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.remoteObjects = function () {
|
app.service = function (name, service) {
|
||||||
var result = {};
|
this._services.push(service);
|
||||||
var models = this.models();
|
service.shared = true;
|
||||||
|
|
||||||
// add in models
|
service.app = this;
|
||||||
models.forEach(function (ModelCtor) {
|
|
||||||
// only add shared models
|
// add to the remote exports
|
||||||
if(ModelCtor.shared && typeof ModelCtor.sharedCtor === 'function') {
|
this.remote(name, service);
|
||||||
result[ModelCtor.pluralModelName] = ModelCtor;
|
}
|
||||||
}
|
|
||||||
});
|
/**
|
||||||
|
* Get all exposed services.
|
||||||
return result;
|
*/
|
||||||
|
|
||||||
|
app.services = function () {
|
||||||
|
return this._services;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,4 +115,29 @@ app.remoteObjects = function () {
|
||||||
|
|
||||||
app.remotes = function () {
|
app.remotes = function () {
|
||||||
return this._remotes || (this._remotes = RemoteObjects.create());
|
return this._remotes || (this._remotes = RemoteObjects.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a remotes handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.handler = function (type) {
|
||||||
|
var handler = this._handlers[type];
|
||||||
|
|
||||||
|
if(!handler) {
|
||||||
|
// get the sl remoting object
|
||||||
|
var remotes = this.remotes();
|
||||||
|
|
||||||
|
// create and save the handler
|
||||||
|
handler = this._handlers[type] = remotes.handler(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
app._handlers = {};
|
||||||
|
|
||||||
|
|
|
@ -17,21 +17,12 @@ module.exports = rest;
|
||||||
|
|
||||||
function rest() {
|
function rest() {
|
||||||
return function (req, res, next) {
|
return function (req, res, next) {
|
||||||
var app = req.app;
|
var handler = req.app.handler('rest');
|
||||||
var remotes = app.remotes();
|
|
||||||
|
|
||||||
// get all remote objects
|
|
||||||
var objs = app.remoteObjects();
|
|
||||||
|
|
||||||
// export remote objects
|
|
||||||
remotes.exports = objs;
|
|
||||||
|
|
||||||
var handler = remotes.handler('rest');
|
|
||||||
|
|
||||||
if(req.url === '/routes') {
|
if(req.url === '/routes') {
|
||||||
res.send(handler.adapter.allRoutes());
|
res.send(handler.adapter.allRoutes());
|
||||||
} else if(req.url === '/models') {
|
} else if(req.url === '/models') {
|
||||||
return res.send(remotes.toJSON());
|
return res.send(req.app.remotes().toJSON());
|
||||||
} else {
|
} else {
|
||||||
handler(req, res, next);
|
handler(req, res, next);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,25 @@
|
||||||
// Schema ACL options
|
/**
|
||||||
|
Schema ACL options
|
||||||
|
|
||||||
|
Object level permissions, for example, an album owned by a user
|
||||||
|
|
||||||
// Object level permissions
|
Factors to be authorized against:
|
||||||
|
|
||||||
// open: no protection
|
* model name: Album
|
||||||
// none: always rejected
|
* model instance properties: userId of the album, friends, shared
|
||||||
// owner: only the owner
|
* methods
|
||||||
// loggedIn: any logged in user
|
* app and/or user ids/roles
|
||||||
// roles: logged in users with the roles
|
** loggedIn
|
||||||
// related: owner of the related objects
|
** roles
|
||||||
|
** userId
|
||||||
// Class level permissions
|
** appId
|
||||||
|
** none
|
||||||
|
** everyone
|
||||||
|
** relations: owner/friend/granted
|
||||||
|
|
||||||
|
Class level permissions, for example, Album
|
||||||
|
* model name: Album
|
||||||
|
* methods
|
||||||
// blog posts
|
// blog posts
|
||||||
allow: ['owner', 'admin'] to: '*' // allow owner's of posts and admins to do anything
|
allow: ['owner', 'admin'] to: '*' // allow owner's of posts and admins to do anything
|
||||||
allow: '*' to: ['find', 'read'] // allow everyone to read and find
|
allow: '*' to: ['find', 'read'] // allow everyone to read and find
|
||||||
|
@ -27,5 +35,4 @@ allow: 'owner' to: ['*.destroy', '*.save']
|
||||||
// scopes
|
// scopes
|
||||||
|
|
||||||
// URL level permissions
|
// URL level permissions
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,54 @@
|
||||||
// Application model
|
// Authentication schemes
|
||||||
|
var AuthenticationSchemeSchema = {
|
||||||
|
scheme: String, // local, facebook, google, twitter, linkedin, github
|
||||||
|
credential: Object // Scheme-specific credentials
|
||||||
|
}
|
||||||
|
|
||||||
|
var APNSSettingSchema = {
|
||||||
|
pushOptions: {type: {
|
||||||
|
gateway: String,
|
||||||
|
cert: String,
|
||||||
|
key: String
|
||||||
|
}},
|
||||||
|
|
||||||
|
feedbackOptions: {type: {
|
||||||
|
gateway: String,
|
||||||
|
cert: String,
|
||||||
|
key: String,
|
||||||
|
batchFeedback: Boolean,
|
||||||
|
interval: Number
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Push notification settings
|
||||||
|
var PushNotificationSettingSchema = {
|
||||||
|
platform: {type: String, required: true}, // apns, gcm, mpns
|
||||||
|
// configuration: {type: Object} // platform-specific configurations
|
||||||
|
apns: APNSSettingSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data model for Application
|
||||||
|
*/
|
||||||
var ApplicationSchema = {
|
var ApplicationSchema = {
|
||||||
|
|
||||||
// Basic information
|
// Basic information
|
||||||
id: {type: String, required: true},
|
id: {type: String, required: true}, // The id
|
||||||
name: {type: String, required: true},
|
name: {type: String, required: true}, // The name
|
||||||
description: String, // description
|
description: String, // The description
|
||||||
icon: String, // The icon url
|
icon: String, // The icon image url
|
||||||
public: Boolean,
|
|
||||||
permissions: [String],
|
|
||||||
|
|
||||||
userId: String,
|
owner: String, // The user id of the developer who registers the application
|
||||||
|
collaborators: [String], // A list of users ids who have permissions to work on this app
|
||||||
|
|
||||||
status: String,
|
// EMail
|
||||||
|
email: String, // e-mail address
|
||||||
|
emailVerified: Boolean, // Is the e-mail verified
|
||||||
|
|
||||||
|
// oAuth 2.0 settings
|
||||||
|
url: String, // The application url
|
||||||
|
callbackUrls: [String], // oAuth 2.0 code/token callback url
|
||||||
|
permissions: [String], // A list of permissions required by the application
|
||||||
|
|
||||||
// Keys
|
// Keys
|
||||||
clientKey: String,
|
clientKey: String,
|
||||||
|
@ -21,21 +58,80 @@ var ApplicationSchema = {
|
||||||
masterKey: String,
|
masterKey: String,
|
||||||
|
|
||||||
// Push notification
|
// Push notification
|
||||||
pushPlatforms: [String],
|
pushSettings: [PushNotificationSettingSchema],
|
||||||
pushCredentials: [],
|
|
||||||
|
|
||||||
// Authentication
|
// User Authentication
|
||||||
authenticationEnabled: Boolean,
|
authenticationEnabled: {type: Boolean, default: true},
|
||||||
anonymousAllowed: Boolean,
|
anonymousAllowed: {type: Boolean, default: true},
|
||||||
schemes: [String], // Basic, facebook, github, google
|
authenticationSchemes: [AuthenticationSchemeSchema],
|
||||||
attachedCredentials: [],
|
|
||||||
|
|
||||||
// email
|
status: {type: String, default: 'sandbox'}, // Status of the application, production/sandbox/disabled
|
||||||
email: String, // e-mail address
|
|
||||||
emailVerified: Boolean, // Is the e-mail verified
|
|
||||||
|
|
||||||
collaborators: [String], // A list of users ids who have permissions to work on this app
|
// Timestamps
|
||||||
|
created: {type: Date, default: Date},
|
||||||
created: Date,
|
modified: {type: Date, default: Date}
|
||||||
lastUpdated: Date
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application management functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
var crypto = require('crypto');
|
||||||
|
|
||||||
|
function generateKey(hmacKey, algorithm) {
|
||||||
|
hmacKey = hmacKey || 'loopback';
|
||||||
|
algorithm = algorithm || 'sha256';
|
||||||
|
var hmac = crypto.createHmac(algorithm, hmacKey);
|
||||||
|
var buf = crypto.randomBytes(64);
|
||||||
|
hmac.update(buf);
|
||||||
|
return hmac.digest('base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function (dataSource) {
|
||||||
|
dataSource = dataSource || new require('loopback-data').ModelBuilder();
|
||||||
|
|
||||||
|
// var AuthenticationScheme = dataSource.define('AuthenticationScheme', AuthenticationSchemeSchema);
|
||||||
|
// ApplicationSchema.authenticationSchemes = [AuthenticationScheme];
|
||||||
|
|
||||||
|
// var PushNotificationSetting = dataSource.define('PushNotificationSetting', PushNotificationSettingSchema);
|
||||||
|
// ApplicationSchema.pushSettings = [PushNotificationSetting];
|
||||||
|
|
||||||
|
var Application = dataSource.define('Application', ApplicationSchema);
|
||||||
|
|
||||||
|
// Application.hasMany(AuthenticationScheme, {as: 'authenticationSchemes', foreignKey: 'appId'});
|
||||||
|
// Application.hasMany(PushNotificationSetting, {as: 'pushNotificationSettings', foreignKey: 'appId'});
|
||||||
|
|
||||||
|
Application.afterInitialize = function () {
|
||||||
|
var app = this;
|
||||||
|
// use data argument to update object
|
||||||
|
app.created = app.modified = new Date();
|
||||||
|
app.id = generateKey('id', 'sha1');
|
||||||
|
app.clientKey = generateKey('client');
|
||||||
|
app.javaScriptKey = generateKey('javaScript');
|
||||||
|
app.restApiKey = generateKey('restApi');
|
||||||
|
app.windowsKey = generateKey('windows');
|
||||||
|
app.masterKey = generateKey('master');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register a new application
|
||||||
|
Application.register = function (name, description, owner, cb) {
|
||||||
|
Application.create({name: name, description: description, owner: owner}, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
Application.prototype.resetKeys = function(cb) {
|
||||||
|
this.clientKey = generateKey('client');
|
||||||
|
this.javaScriptKey = generateKey('javaScript');
|
||||||
|
this.restApiKey = generateKey('restApi');
|
||||||
|
this.windowsKey = generateKey('windows');
|
||||||
|
this.masterKey = generateKey('master');
|
||||||
|
this.save(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Application;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
exports.Application = require('./application');
|
||||||
|
exports.ACL = require('./acl');
|
||||||
|
exports.Role = require('./role');
|
||||||
|
exports.Installation = require('./installation');
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,26 @@
|
||||||
// Device registration
|
// See Device registration
|
||||||
var InstallationSchema = {
|
var InstallationSchema = {
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
id: 1
|
||||||
|
},
|
||||||
|
appId: String, // Application id
|
||||||
|
appVersion: String, // Application version
|
||||||
|
userId: String, // User id
|
||||||
|
deviceToken: String,
|
||||||
|
deviceType: String,
|
||||||
|
subscriptions: [String],
|
||||||
|
|
||||||
|
status: {type: String, default: 'active'}, // Status of the application, production/sandbox/disabled
|
||||||
|
|
||||||
|
// Timestamps
|
||||||
|
created: {type: Date, default: Date},
|
||||||
|
modified: {type: Date, default: Date}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = function(dataSource) {
|
||||||
|
dataSource = dataSource || new require('loopback-data').ModelBuilder();
|
||||||
|
var Installation = dataSource.define('Installation', InstallationSchema);
|
||||||
|
return Installation;
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
// Role model
|
// Role model
|
||||||
var RoleSchema = {
|
var RoleSchema = {
|
||||||
id: {type: String, required: true},
|
id: {type: String, required: true}, // Id
|
||||||
name: {type: String, required: true},
|
name: {type: String, required: true}, // The name of a role
|
||||||
roles: [String],
|
description: String, // Description
|
||||||
users: [String],
|
roles: [String], // A role can be an aggregate of other roles
|
||||||
acl: [],
|
users: [String], // A role contains a list of user ids
|
||||||
|
|
||||||
created: Date,
|
// Timestamps
|
||||||
lastUpdated: Date
|
created: {type: Date, default: Date},
|
||||||
|
modified: {type: Date, default: Date}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function(dataSource) {
|
||||||
|
dataSource = dataSource || new require('loopback-data').ModelBuilder();
|
||||||
|
var Role = dataSource.define('Role', RoleSchema);
|
||||||
|
return Role;
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@ var properties = {
|
||||||
email: String,
|
email: String,
|
||||||
emailVerified: Boolean,
|
emailVerified: Boolean,
|
||||||
verificationToken: String,
|
verificationToken: String,
|
||||||
|
|
||||||
credentials: [
|
credentials: [
|
||||||
'UserCredential' // User credentials, private or public, such as private/public keys, Kerberos tickets, oAuth tokens, facebook, google, github ids
|
'UserCredential' // User credentials, private or public, such as private/public keys, Kerberos tickets, oAuth tokens, facebook, google, github ids
|
||||||
],
|
],
|
||||||
|
@ -328,4 +329,4 @@ User.prototype.logout = function (fn) {
|
||||||
* Setup the base user.
|
* Setup the base user.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
User.setup();
|
User.setup();
|
||||||
|
|
|
@ -2,6 +2,12 @@
|
||||||
- [app](#app)
|
- [app](#app)
|
||||||
- [app.model(Model)](#app-appmodelmodel)
|
- [app.model(Model)](#app-appmodelmodel)
|
||||||
- [app.models()](#app-appmodels)
|
- [app.models()](#app-appmodels)
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
- [loopback](#loopback)
|
||||||
|
- [loopback.createDataSource(options)](#loopback-loopbackcreatedatasourceoptions)
|
||||||
|
- [loopback.remoteMethod(Model, fn, [options]);](#loopback-loopbackremotemethodmodel-fn-options)
|
||||||
|
>>>>>>> master
|
||||||
- [DataSource](#datasource)
|
- [DataSource](#datasource)
|
||||||
- [dataSource.createModel(name, properties, settings)](#datasource-datasourcecreatemodelname-properties-settings)
|
- [dataSource.createModel(name, properties, settings)](#datasource-datasourcecreatemodelname-properties-settings)
|
||||||
- [dataSource.operations()](#datasource-datasourceoperations)
|
- [dataSource.operations()](#datasource-datasourceoperations)
|
||||||
|
@ -76,6 +82,48 @@ assert.equal(models.length, 1);
|
||||||
assert.equal(models[0].modelName, 'color');
|
assert.equal(models[0].modelName, 'color');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
<a name="loopback"></a>
|
||||||
|
# loopback
|
||||||
|
<a name="loopback-loopbackcreatedatasourceoptions"></a>
|
||||||
|
## loopback.createDataSource(options)
|
||||||
|
Create a data source with a connector..
|
||||||
|
|
||||||
|
```js
|
||||||
|
var dataSource = loopback.createDataSource({
|
||||||
|
connector: loopback.Memory
|
||||||
|
});
|
||||||
|
assert(dataSource.connector());
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="loopback-loopbackremotemethodmodel-fn-options"></a>
|
||||||
|
## loopback.remoteMethod(Model, fn, [options]);
|
||||||
|
Setup a remote method..
|
||||||
|
|
||||||
|
```js
|
||||||
|
var Product = loopback.createModel('product', {price: Number});
|
||||||
|
|
||||||
|
Product.stats = function(fn) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
loopback.remoteMethod(
|
||||||
|
Product.stats,
|
||||||
|
{
|
||||||
|
returns: {arg: 'stats', type: 'array'},
|
||||||
|
http: {path: '/info', verb: 'get'}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(Product.stats.returns.arg, 'stats');
|
||||||
|
assert.equal(Product.stats.returns.type, 'array');
|
||||||
|
assert.equal(Product.stats.http.path, '/info');
|
||||||
|
assert.equal(Product.stats.http.verb, 'get');
|
||||||
|
assert.equal(Product.stats.shared, true);
|
||||||
|
```
|
||||||
|
|
||||||
|
>>>>>>> master
|
||||||
<a name="datasource"></a>
|
<a name="datasource"></a>
|
||||||
# DataSource
|
# DataSource
|
||||||
<a name="datasource-datasourcecreatemodelname-properties-settings"></a>
|
<a name="datasource-datasourcecreatemodelname-properties-settings"></a>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
describe('loopback', function() {
|
describe('loopback', function() {
|
||||||
describe('loopback.createDataSource(options)', function(){
|
describe('loopback.createDataSource(options)', function(){
|
||||||
it('Create a data source with a connector', function() {
|
it('Create a data source with a connector.', function() {
|
||||||
var dataSource = loopback.createDataSource({
|
var dataSource = loopback.createDataSource({
|
||||||
connector: loopback.Memory
|
connector: loopback.Memory
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ describe('loopback', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('loopback.remoteMethod(Model, fn, [options]);', function() {
|
describe('loopback.remoteMethod(Model, fn, [options]);', function() {
|
||||||
it("Setup a remote method", function() {
|
it("Setup a remote method.", function() {
|
||||||
var Product = loopback.createModel('product', {price: Number});
|
var Product = loopback.createModel('product', {price: Number});
|
||||||
|
|
||||||
Product.stats = function(fn) {
|
Product.stats = function(fn) {
|
||||||
|
@ -31,18 +31,4 @@ describe('loopback', function() {
|
||||||
assert.equal(Product.stats.shared, true);
|
assert.equal(Product.stats.shared, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('loopback.memory([name])', function(){
|
|
||||||
it('Get an in-memory data source. Use one if it already exists', function() {
|
|
||||||
var memory = loopback.memory();
|
|
||||||
assertValidDataSource(memory);
|
|
||||||
var m1 = loopback.memory();
|
|
||||||
var m2 = loopback.memory('m2');
|
|
||||||
var alsoM2 = loopback.memory('m2');
|
|
||||||
|
|
||||||
assert(m1 === memory);
|
|
||||||
assert(m1 !== m2);
|
|
||||||
assert(alsoM2 === m2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
Loading…
Reference in New Issue