Merge pull request #2581 from strongloop/backport/globalization
Backport of #2407
This commit is contained in:
commit
16c78a83a1
|
@ -3,6 +3,8 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
module.exports = function(loopback) {
|
||||
loopback.getCurrentContext = function() {
|
||||
return null;
|
||||
|
@ -10,6 +12,6 @@ module.exports = function(loopback) {
|
|||
|
||||
loopback.runInContext =
|
||||
loopback.createContext = function() {
|
||||
throw new Error('Current context is not supported in the browser.');
|
||||
throw new Error(g.f('Current context is not supported in the browser.'));
|
||||
};
|
||||
};
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Module Dependencies.
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var loopback = require('../../lib/loopback');
|
||||
var assert = require('assert');
|
||||
var uid = require('uid2');
|
||||
|
@ -112,7 +114,7 @@ module.exports = function(AccessToken) {
|
|||
} else if (isValid) {
|
||||
cb(null, token);
|
||||
} else {
|
||||
var e = new Error('Invalid Access Token');
|
||||
var e = new Error(g.f('Invalid Access Token'));
|
||||
e.status = e.statusCode = 401;
|
||||
e.code = 'INVALID_TOKEN';
|
||||
cb(e);
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var loopback = require('../../lib/loopback');
|
||||
var async = require('async');
|
||||
var assert = require('assert');
|
||||
|
@ -535,7 +537,7 @@ module.exports = function(ACL) {
|
|||
break;
|
||||
default:
|
||||
process.nextTick(function() {
|
||||
var err = new Error('Invalid principal type: ' + type);
|
||||
var err = new Error(g.f('Invalid principal type: %s', type));
|
||||
err.statusCode = 400;
|
||||
cb(err);
|
||||
});
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Module Dependencies.
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var PersistedModel = require('../../lib/loopback').PersistedModel;
|
||||
var loopback = require('../../lib/loopback');
|
||||
var utils = require('../../lib/utils');
|
||||
|
@ -112,7 +114,7 @@ module.exports = function(Change) {
|
|||
})
|
||||
.join('\n');
|
||||
|
||||
var msg = 'Cannot rectify ' + modelName + ' changes:\n' + desc;
|
||||
var msg = g.f('Cannot rectify %s changes:\n%s', modelName, desc);
|
||||
err = new Error(msg);
|
||||
err.details = { errors: errors };
|
||||
return callback(err);
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
* @inherits {Model}
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
module.exports = function(Email) {
|
||||
|
||||
/**
|
||||
|
@ -44,13 +46,13 @@ module.exports = function(Email) {
|
|||
*/
|
||||
|
||||
Email.send = function() {
|
||||
throw new Error('You must connect the Email Model to a Mail connector');
|
||||
throw new Error(g.f('You must connect the {{Email}} Model to a {{Mail}} connector'));
|
||||
};
|
||||
|
||||
/**
|
||||
* A shortcut for Email.send(this).
|
||||
*/
|
||||
Email.prototype.send = function() {
|
||||
throw new Error('You must connect the Email Model to a Mail connector');
|
||||
throw new Error(g.f('You must connect the {{Email}} Model to a {{Mail}} connector'));
|
||||
};
|
||||
};
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Module Dependencies.
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var loopback = require('../../lib/loopback');
|
||||
var utils = require('../../lib/utils');
|
||||
var path = require('path');
|
||||
|
@ -205,14 +207,14 @@ module.exports = function(User) {
|
|||
realmDelimiter);
|
||||
|
||||
if (realmRequired && !query.realm) {
|
||||
var err1 = new Error('realm is required');
|
||||
var err1 = new Error(g.f('{{realm}} is required'));
|
||||
err1.statusCode = 400;
|
||||
err1.code = 'REALM_REQUIRED';
|
||||
fn(err1);
|
||||
return fn.promise;
|
||||
}
|
||||
if (!query.email && !query.username) {
|
||||
var err2 = new Error('username or email is required');
|
||||
var err2 = new Error(g.f('{{username}} or {{email}} is required'));
|
||||
err2.statusCode = 400;
|
||||
err2.code = 'USERNAME_EMAIL_REQUIRED';
|
||||
fn(err2);
|
||||
|
@ -220,7 +222,7 @@ module.exports = function(User) {
|
|||
}
|
||||
|
||||
self.findOne({where: query}, function(err, user) {
|
||||
var defaultError = new Error('login failed');
|
||||
var defaultError = new Error(g.f('login failed'));
|
||||
defaultError.statusCode = 401;
|
||||
defaultError.code = 'LOGIN_FAILED';
|
||||
|
||||
|
@ -250,7 +252,7 @@ module.exports = function(User) {
|
|||
if (self.settings.emailVerificationRequired && !user.emailVerified) {
|
||||
// Fail to log in if email verification is not done yet
|
||||
debug('User email has not been verified');
|
||||
err = new Error('login failed as the email has not been verified');
|
||||
err = new Error(g.f('login failed as the email has not been verified'));
|
||||
err.statusCode = 401;
|
||||
err.code = 'LOGIN_FAILED_EMAIL_NOT_VERIFIED';
|
||||
fn(err);
|
||||
|
@ -296,7 +298,7 @@ module.exports = function(User) {
|
|||
} else if (accessToken) {
|
||||
accessToken.destroy(fn);
|
||||
} else {
|
||||
fn(new Error('could not find accessToken'));
|
||||
fn(new Error(g.f('could not find {{accessToken}}')));
|
||||
}
|
||||
});
|
||||
return fn.promise;
|
||||
|
@ -438,15 +440,21 @@ module.exports = function(User) {
|
|||
|
||||
options.text = options.text.replace(/\{href\}/g, options.verifyHref);
|
||||
|
||||
options.text = g.f(options.text);
|
||||
|
||||
options.to = options.to || user.email;
|
||||
|
||||
options.subject = options.subject || 'Thanks for Registering';
|
||||
|
||||
options.subject = g.f(options.subject);
|
||||
|
||||
options.headers = options.headers || {};
|
||||
|
||||
var template = loopback.template(options.template);
|
||||
options.html = template(options);
|
||||
|
||||
options.html = g.f(options.html);
|
||||
|
||||
Email.send(options, function(err, email) {
|
||||
if (err) {
|
||||
fn(err);
|
||||
|
@ -501,11 +509,11 @@ module.exports = function(User) {
|
|||
});
|
||||
} else {
|
||||
if (user) {
|
||||
err = new Error('Invalid token: ' + token);
|
||||
err = new Error(g.f('Invalid token: %s', token));
|
||||
err.statusCode = 400;
|
||||
err.code = 'INVALID_TOKEN';
|
||||
} else {
|
||||
err = new Error('User not found: ' + uid);
|
||||
err = new Error(g.f('User not found: %s', uid));
|
||||
err.statusCode = 404;
|
||||
err.code = 'USER_NOT_FOUND';
|
||||
}
|
||||
|
@ -533,7 +541,7 @@ module.exports = function(User) {
|
|||
|
||||
options = options || {};
|
||||
if (typeof options.email !== 'string') {
|
||||
var err = new Error('Email is required');
|
||||
var err = new Error(g.f('Email is required'));
|
||||
err.statusCode = 400;
|
||||
err.code = 'EMAIL_REQUIRED';
|
||||
cb(err);
|
||||
|
@ -545,7 +553,7 @@ module.exports = function(User) {
|
|||
return cb(err);
|
||||
}
|
||||
if (!user) {
|
||||
err = new Error('Email not found');
|
||||
err = new Error(g.f('Email not found'));
|
||||
err.statusCode = 404;
|
||||
err.code = 'EMAIL_NOT_FOUND';
|
||||
return cb(err);
|
||||
|
@ -581,7 +589,7 @@ module.exports = function(User) {
|
|||
if (typeof plain === 'string' && plain) {
|
||||
return true;
|
||||
}
|
||||
var err = new Error('Invalid password: ' + plain);
|
||||
var err = new Error(g.f('Invalid password: %s', plain));
|
||||
err.statusCode = 422;
|
||||
throw err;
|
||||
};
|
||||
|
@ -640,20 +648,21 @@ module.exports = function(User) {
|
|||
UserModel.remoteMethod(
|
||||
'login',
|
||||
{
|
||||
description: 'Login a user with username/email and password.',
|
||||
description: g.f('Login a user with username/email and password.'),
|
||||
accepts: [
|
||||
{arg: 'credentials', type: 'object', required: true, http: {source: 'body'}},
|
||||
{arg: 'include', type: ['string'], http: {source: 'query' },
|
||||
description: 'Related objects to include in the response. ' +
|
||||
'See the description of return value for more details.'}
|
||||
{arg: 'include', type: ['string'], http: {source: 'query'},
|
||||
description: g.f('Related objects to include in the response. ' +
|
||||
'See the description of return value for more details.') },
|
||||
],
|
||||
returns: {
|
||||
arg: 'accessToken', type: 'object', root: true,
|
||||
description:
|
||||
'The response body contains properties of the AccessToken created on login.\n' +
|
||||
g.f('The response body contains properties of the {{AccessToken}} created on login.\n' +
|
||||
'Depending on the value of `include` parameter, the body may contain ' +
|
||||
'additional properties:\n\n' +
|
||||
' - `user` - `{User}` - Data of the currently logged in user. (`include=user`)\n\n'
|
||||
' - `user` - `U+007BUserU+007D` - Data of the currently logged in user. ' +
|
||||
'{{(`include=user`)}}\n\n'),
|
||||
},
|
||||
http: {verb: 'post'}
|
||||
}
|
||||
|
@ -662,17 +671,17 @@ module.exports = function(User) {
|
|||
UserModel.remoteMethod(
|
||||
'logout',
|
||||
{
|
||||
description: 'Logout a user with access token.',
|
||||
description: g.f('Logout a user with access token.'),
|
||||
accepts: [
|
||||
{arg: 'access_token', type: 'string', required: true, http: function(ctx) {
|
||||
var req = ctx && ctx.req;
|
||||
var accessToken = req && req.accessToken;
|
||||
var tokenID = accessToken && accessToken.id;
|
||||
|
||||
return tokenID;
|
||||
}, description: 'Do not supply this argument, it is automatically extracted ' +
|
||||
'from request headers.'
|
||||
}],
|
||||
var req = ctx && ctx.req;
|
||||
var accessToken = req && req.accessToken;
|
||||
var tokenID = accessToken && accessToken.id;
|
||||
return tokenID;
|
||||
}, description: g.f('Do not supply this argument, it is automatically extracted ' +
|
||||
'from request headers.'),
|
||||
},
|
||||
],
|
||||
http: {verb: 'all'}
|
||||
}
|
||||
);
|
||||
|
@ -680,7 +689,7 @@ module.exports = function(User) {
|
|||
UserModel.remoteMethod(
|
||||
'confirm',
|
||||
{
|
||||
description: 'Confirm a user registration with email verification token.',
|
||||
description: g.f('Confirm a user registration with email verification token.'),
|
||||
accepts: [
|
||||
{arg: 'uid', type: 'string', required: true},
|
||||
{arg: 'token', type: 'string', required: true},
|
||||
|
@ -693,7 +702,7 @@ module.exports = function(User) {
|
|||
UserModel.remoteMethod(
|
||||
'resetPassword',
|
||||
{
|
||||
description: 'Reset password for a user with email.',
|
||||
description: g.f('Reset password for a user with email.'),
|
||||
accepts: [
|
||||
{arg: 'options', type: 'object', required: true, http: {source: 'body'}}
|
||||
],
|
||||
|
@ -704,7 +713,7 @@ module.exports = function(User) {
|
|||
UserModel.afterRemote('confirm', function(ctx, inst, next) {
|
||||
if (ctx.args.redirect !== undefined) {
|
||||
if (!ctx.res) {
|
||||
return next(new Error('The transport does not support HTTP redirects.'));
|
||||
return next(new Error(g.f('The transport does not support HTTP redirects.')));
|
||||
}
|
||||
ctx.res.location(ctx.args.redirect);
|
||||
ctx.res.status(302);
|
||||
|
@ -722,7 +731,7 @@ module.exports = function(User) {
|
|||
// email validation regex
|
||||
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
|
||||
UserModel.validatesFormatOf('email', {with: re, message: 'Must provide a valid email'});
|
||||
UserModel.validatesFormatOf('email', {with: re, message: g.f('Must provide a valid email')});
|
||||
|
||||
// FIXME: We need to add support for uniqueness of composite keys in juggler
|
||||
if (!(UserModel.settings.realmRequired || UserModel.settings.realmDelimiter)) {
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var loopback = require('../../');
|
||||
var client = loopback();
|
||||
var CartItem = require('./models').CartItem;
|
||||
|
@ -16,10 +18,10 @@ CartItem.attachTo(remote);
|
|||
|
||||
// call the remote method
|
||||
CartItem.sum(1, function(err, total) {
|
||||
console.log('result:', err || total);
|
||||
g.log('result:%s', err || total);
|
||||
});
|
||||
|
||||
// call a built in remote method
|
||||
CartItem.find(function(err, items) {
|
||||
console.log(items);
|
||||
g.log(items);
|
||||
});
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var loopback = require('../../');
|
||||
var app = loopback();
|
||||
|
||||
|
@ -22,4 +24,4 @@ Color.create({name: 'blue'});
|
|||
|
||||
app.listen(3000);
|
||||
|
||||
console.log('a list of colors is available at http://localhost:3000/colors');
|
||||
g.log('a list of colors is available at {{http://localhost:3000/colors}}');
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var loopback = require('../../');
|
||||
var app = loopback();
|
||||
|
||||
|
@ -22,7 +24,7 @@ var Color = loopback.createModel('color', { 'name': String });
|
|||
Color.beforeRemote('**', function (ctx, unused, next) {
|
||||
// Inside LoopBack code, you can read the property from the context
|
||||
var ns = loopback.getCurrentContext();
|
||||
console.log('Request to host', ns && ns.get('host'));
|
||||
g.log('Request to host %s', ns && ns.get('host'));
|
||||
next();
|
||||
});
|
||||
|
||||
|
@ -30,5 +32,5 @@ app.dataSource('db', { connector: 'memory' });
|
|||
app.model(Color, { dataSource: 'db' });
|
||||
|
||||
app.listen(3000, function() {
|
||||
console.log('A list of colors is available at http://localhost:3000/colors');
|
||||
g.log('A list of colors is available at {{http://localhost:3000/colors}}');
|
||||
});
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var models = require('../../lib/models');
|
||||
|
||||
var loopback = require('../../');
|
||||
|
@ -37,14 +39,15 @@ var data = {pushSettings: [
|
|||
]}
|
||||
|
||||
Application.create(data, function(err, data) {
|
||||
console.log('Created: ', data.toObject());
|
||||
g.log('Created: %s', data.toObject());
|
||||
});
|
||||
|
||||
|
||||
Application.register('rfeng', 'MyApp', {description: 'My first mobile application'}, function (err, result) {
|
||||
Application.register('rfeng', 'MyApp', { description: g.f('My first mobile application') },
|
||||
function(err, result) {
|
||||
console.log(result.toObject());
|
||||
|
||||
result.resetKeys(function(err, result) {
|
||||
console.log(result.toObject());
|
||||
|
||||
result.resetKeys(function (err, result) {
|
||||
console.log(result.toObject());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var loopback = require('../../');
|
||||
var app = loopback();
|
||||
|
||||
|
@ -25,4 +27,4 @@ Color.all(function () {
|
|||
|
||||
app.listen(3000);
|
||||
|
||||
console.log('a list of colors is available at http://localhost:3000/colors');
|
||||
g.log('a list of colors is available at {{http://localhost:3000/colors}}');
|
||||
|
|
3
index.js
3
index.js
|
@ -3,6 +3,9 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var SG = require('strong-globalize');
|
||||
SG.SetRootDir(__dirname, {autonomousMsgLoading: 'all'});
|
||||
|
||||
/**
|
||||
* loopback ~ public api
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
{
|
||||
"3b46d3a780fd6ae5f95ade489a0efffe": "Current context is not supported in the browser.",
|
||||
"7e0fca41d098607e1c9aa353c67e0fa1": "Invalid Access Token",
|
||||
"320c482401afa1207c04343ab162e803": "Invalid principal type: {0}",
|
||||
"c2b5d51f007178170ca3952d59640ca4": "Cannot rectify {0} changes:\n{1}",
|
||||
"5858e63efaa0e4ad86b61c0459ea32fa": "You must connect the {{Email}} Model to a {{Mail}} connector",
|
||||
"0caffe1d763c8cca6a61814abe33b776": "Email is required",
|
||||
"1b2a6076dccbe91a56f1672eb3b8598c": "The response body contains properties of the {{AccessToken}} created on login.\nDepending on the value of `include` parameter, the body may contain additional properties:\n\n - `user` - `U+007BUserU+007D` - Data of the currently logged in user. {{(`include=user`)}}\n\n",
|
||||
"2362ba55796c733e337af169922327a2": "Related objects to include in the response. See the description of return value for more details.",
|
||||
"306999d39387d87b2638199ff0bed8ad": "Reset password for a user with email.",
|
||||
"3aae63bb7e8e046641767571c1591441": "login failed as the email has not been verified",
|
||||
"3caaa84fc103d6d5612173ae6d43b245": "Invalid token: {0}",
|
||||
"42e3fa18945255412ebc6561e2c6f1dc": "Confirm a user registration with email verification token.",
|
||||
"430b6326d7ebf6600a39f614ef516bc8": "Do not supply this argument, it is automatically extracted from request headers.",
|
||||
"44a6c8b1ded4ed653d19ddeaaf89a606": "Email not found",
|
||||
"5e81ad3847a290dc650b47618b9cbc7e": "login failed",
|
||||
"83cfabbe3aa84ce52e0f5ed7c3b2e9b3": "Login a user with username/email and password.",
|
||||
"8608c28f5e6df0008266e3c497836176": "Logout a user with access token.",
|
||||
"860d1a0b8bd340411fb32baa72867989": "The transport does not support HTTP redirects.",
|
||||
"895b1f941d026870b3cc8e6af087c197": "{{username}} or {{email}} is required",
|
||||
"a50d10fc6e0959b220e085454c40381e": "User not found: {0}",
|
||||
"ba96498b10c179f9cd75f75c8def4f70": "{{realm}} is required",
|
||||
"c34fa20eea0091747fcc9eda204b8d37": "could not find {{accessToken}}",
|
||||
"c68a93f0a9524fed4ff64372fc90c55f": "Must provide a valid email",
|
||||
"f58cdc481540cd1f69a4aa4da2e37981": "Invalid password: {0}",
|
||||
"f0bd73df8714cefb925e3b8da2f4c5f6": "result:{0}",
|
||||
"10e01c895dc0b2fecc385f9f462f1ca6": "a list of colors is available at {{http://localhost:3000/colors}}",
|
||||
"8a27e0c9ce3ebf0e0c3978efb456e13e": "Request to host {0}",
|
||||
"a40684f5a9f546115258b76938d1de37": "A list of colors is available at {{http://localhost:3000/colors}}",
|
||||
"1e85f822b547a75d7d385048030e4ecb": "Created: {0}",
|
||||
"7d5e7ed0efaedf3f55f380caae0df8b8": "My first mobile application",
|
||||
"04bd8af876f001ceaf443aad6a9002f9": "Authentication requires model {0} to be defined.",
|
||||
"095afbf2f1f0e5be678f5dac5c54e717": "Access Denied",
|
||||
"2d3071e3b18681c80a090dc0efbdb349": "could not find {0} with id {1}",
|
||||
"316e5b82c203cf3de31a449ee07d0650": "Expected boolean, got {0}",
|
||||
"57b87ae0e65f6ab7a2e3e6cbdfca49a4": "Cannot create data source {0}: {1}",
|
||||
"7e287fc885d9fdcf42da3a12f38572c1": "Authorization Required",
|
||||
"d5552322de5605c58b62f47ad26d2716": "{{`app.boot`}} was removed, use the new module {{loopback-boot}} instead",
|
||||
"1d7833c3ca2f05fdad8fad7537531c40": "\t SUBJECT:{0}",
|
||||
"275f22ab95671f095640ca99194b7635": "\t FROM:{0}",
|
||||
"3d63008ccfb2af1db2142e8cc2716ace": "Warning: No email transport specified for sending email. Setup a transport to send mail messages.",
|
||||
"4a4f04a4e480fc5d4ee73b84d9a4b904": "Sending Mail:",
|
||||
"63a091ced88001ab6acb58f61ec041c5": "\t TEXT:{0}",
|
||||
"93ba9a1d03da3b7696332d3f155c5bb7": "\t HTML:{0}",
|
||||
"ecb06666ef95e5db27a5ac1d6a17923b": "\t TO:{0}",
|
||||
"f0aed00a3d3d0b97d6594e4b70e0c201": "\t TRANSPORT:{0}",
|
||||
"0da38687fed24275c1547e815914a8e3": "Delete a related item by id for {0}.",
|
||||
"0e4f89f8dde1e88cbfc6c1d88f0f77cb": "Criteria to match model instances",
|
||||
"22fe62fa8d595b72c62208beddaa2a56": "Update a related item by id for {0}.",
|
||||
"528325f3cbf1b0ab9a08447515daac9a": "Update {0} of this model.",
|
||||
"543d19bad5e47ee1e9eb8af688e857b4": "Foreign key for {0}.",
|
||||
"598ff0255ffd1d1b71e8de55dbe2c034": "Check the existence of {0} relation to an item by id.",
|
||||
"5a36cc6ba0cc27c754f6c5ed6015ea3c": "Remove the {0} relation to an item by id.",
|
||||
"5fa3afb425819ebde958043e598cb664": "could not find a model with {{id}} {0}",
|
||||
"61e5deebaf44d68f4e6a508f30cc31a3": "Relation `{0}` does not exist for model `{1}`",
|
||||
"651f0b3cbba001635152ec3d3d954d0a": "Find a related item by id for {0}.",
|
||||
"7bc7b301ad9c4fc873029d57fb9740fe": "Queries {0} of {1}.",
|
||||
"7c837b88fd0e509bd3fc722d7ddf0711": "Foreign key for {0}",
|
||||
"830cb6c862f8f364e9064cea0026f701": "Fetches hasOne relation {0}.",
|
||||
"855ecd4a64885ba272d782435f72a4d4": "Unknown \"{0}\" id \"{1}\".",
|
||||
"86254879d01a60826a851066987703f2": "Add a related item by id for {0}.",
|
||||
"8ae418c605b6a45f2651be9b1677c180": "Invalid remote method: `{0}`",
|
||||
"9e3cbc1d5a9347cdcf6d1b4a6dbb55b7": "Fetches belongsTo relation {0}.",
|
||||
"c0057a569ff9d3b509bac61a4b2f605d": "Deletes all {0} of this model.",
|
||||
"cd0412f2f33a4a2a316acc834f3f21a6": "must specify an {{id}} or {{data}}",
|
||||
"d6f43b266533b04d442bdb3955622592": "Creates a new instance in {0} of this model.",
|
||||
"da13d3cdf21330557254670dddd8c5c7": "Counts {0} of {1}.",
|
||||
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "Unknown \"{0}\" {{id}} \"{1}\".",
|
||||
"f66ae3cf379b2fce28575a3282defe1a": "Deletes {0} of this model.",
|
||||
"03f79fa268fe199de2ce4345515431c1": "No change record found for {0} with id {1}",
|
||||
"0f1c71f74b040bfbe8d384a414e31f03": "Get a set of deltas and conflicts since the given checkpoint.",
|
||||
"15254dec061d023d6c030083a0cef50f": "Create a new instance of the model and persist it into the data source.",
|
||||
"16a11368d55b85a209fc6aea69ee5f7a": "Delete all matching records.",
|
||||
"1bc1d489ddf347af47af3d9b1fc7cc15": "Run multiple updates at once. Note: this is not atomic.",
|
||||
"1bc7d8283c9abda512692925c8d8e3c0": "Get the current checkpoint.",
|
||||
"1caa7cc61266e7aef7db7d2f0e27ac3e": "Update the properties of the most recent change record kept for this instance.",
|
||||
"2a7df74fe6e8462e617b79d5fbb536ea": "Get the most recent change record for this instance.",
|
||||
"2a9684b3d5b3b67af74bac74eb1b0843": "Find all instances of the model matched by filter from the data source.",
|
||||
"2e50838caf0c927735eb15d12866bdd7": "Get the changes to a model since a given checkpoint.Provide a filter object to reduce the number of results returned.",
|
||||
"4203ab415ec66a78d3164345439ba76e": "Cannot call {0}.{1}(). The {2} method has not been setup. The {{PersistedModel}} has not been correctly attached to a {{DataSource}}!",
|
||||
"51ea9b6245bb5e672b236d640ca3b048": "An object of Change property name/value pairs",
|
||||
"55ddedd4c501348f82cb89db02ec85c1": "An object of model property name/value pairs",
|
||||
"5aaa76c72ae1689fd3cf62589784a4ba": "Update attributes for a model instance and persist it into the data source.",
|
||||
"5f659bbc15e6e2b249fa33b3879b5f69": "Find a model instance by {{id}} from the data source.",
|
||||
"62e8b0a733417978bab22c8dacf5d7e6": "Cannot apply bulk updates, the connector does not correctly report the number of updated records.",
|
||||
"6329e0ac1de3c250ebb1df5afd5a2a7b": "The number of instances updated",
|
||||
"6bc376432cd9972cf991aad3de371e78": "Missing data for change: {0}",
|
||||
"79295ac04822d2e9702f0dd1d0240336": "Update instances of the model matched by {{where}} from the data source.",
|
||||
"7f2fde7f0f860ead224b11ba8d75aa1c": "Create an update list from a delta list.",
|
||||
"89b57e764c2267129294b07589dbfdc2": "Delete a model instance by {{id}} from the data source.",
|
||||
"8bab6720ecc58ec6412358c858a53484": "Bulk update failed, the connector has modified unexpected number of records: {0}",
|
||||
"a98b6cc6547706b5c6bffde0ed5fd55c": "Find first instance of the model matched by filter from the data source.",
|
||||
"c46d4aba1f14809c16730faa46933495": "Filter defining fields and include",
|
||||
"c65600640f206f585d300b4bcb699d95": "Create a checkpoint.",
|
||||
"cf64c7afc74d3a8120abcd028f98c770": "Update an existing model instance or insert a new one into the data source.",
|
||||
"dcb6261868ff0a7b928aa215b07d068c": "Create a change stream.",
|
||||
"e43e320a435ec1fa07648c1da0d558a7": "Check whether a model instance exists in the data source.",
|
||||
"e92aa25b6b864e3454b65a7c422bd114": "Bulk update failed, the connector has deleted unexpected number of records: {0}",
|
||||
"ea63d226b6968e328bdf6876010786b5": "Cannot apply bulk updates, the connector does not correctly report the number of deleted records.",
|
||||
"f1d4ac54357cc0932f385d56814ba7e4": "Conflict",
|
||||
"f37d94653793e33f4203e45b4a1cf106": "Count instances of the model matched by where from the data source.",
|
||||
"0731d0109e46c21a4e34af3346ed4856": "This behaviour may change in the next major version.",
|
||||
"2e110abee2c95bcfc2dafd48be7e2095": "Cannot configure {0}: {{config.dataSource}} must be an instance of {{DataSource}}",
|
||||
"308e1d484516a33df788f873e65faaff": "Model `{0}` is extending deprecated `DataModel. Use `PersistedModel` instead.",
|
||||
"3438fab56cc7ab92dfd88f0497e523e0": "The relations property of `{0}` configuration must be an object",
|
||||
"4cac5f051ae431321673e04045d37772": "Model `{0}` is extending an unknown model `{1}`. Using `PersistedModel` as the base.",
|
||||
"734a7bebb65e10899935126ba63dd51f": "The options property of `{0}` configuration must be an object",
|
||||
"779467f467862836e19f494a37d6ab77": "The acls property of `{0}` configuration must be an array of objects",
|
||||
"80a32e80cbed65eba2103201a7c94710": "Model not found: {0}",
|
||||
"83cbdc2560ba9f09155ccfc63e08f1a1": "Property `{0}` cannot be reconfigured for `{1}`",
|
||||
"97795efe0c3eb7f35ce8cf8cfe70682b": "The configuration of `{0}` is missing {{`dataSource`}} property.\nUse `null` or `false` to mark models not attached to any data source.",
|
||||
"a80038252430df2754884bf3c845c4cf": "Remoting metadata for \"{0}.{1}\" is missing \"isStatic\" flag, the method is registered as an instance method.",
|
||||
"dc568bee32deb0f6eaf63e73b20e8ceb": "Ignoring non-object \"methods\" setting of \"{0}\".",
|
||||
"3aecb24fa8bdd3f79d168761ca8a6729": "Unknown {{middleware}} phase {0}"
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var DataSource = require('loopback-datasource-juggler').DataSource;
|
||||
var Registry = require('./registry');
|
||||
var assert = require('assert');
|
||||
|
@ -237,8 +239,8 @@ app.dataSource = function(name, config) {
|
|||
return ds;
|
||||
} catch (err) {
|
||||
if (err.message) {
|
||||
err.message = 'Cannot create data source ' + JSON.stringify(name) +
|
||||
': ' + err.message;
|
||||
err.message = g.f('Cannot create data source %s: %s',
|
||||
JSON.stringify(name), err.message);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
@ -322,7 +324,7 @@ app.enableAuth = function(options) {
|
|||
var Model = app.registry.findModel(m);
|
||||
if (!Model) {
|
||||
throw new Error(
|
||||
'Authentication requires model ' + m + ' to be defined.');
|
||||
g.f('Authentication requires model %s to be defined.', m));
|
||||
}
|
||||
|
||||
if (m.dataSource || m.app) return;
|
||||
|
@ -378,17 +380,17 @@ app.enableAuth = function(options) {
|
|||
|
||||
var messages = {
|
||||
403: {
|
||||
message: 'Access Denied',
|
||||
code: 'ACCESS_DENIED'
|
||||
message: g.f('Access Denied'),
|
||||
code: 'ACCESS_DENIED',
|
||||
},
|
||||
404: {
|
||||
message: ('could not find ' + modelName + ' with id ' + modelId),
|
||||
code: 'MODEL_NOT_FOUND'
|
||||
message: (g.f('could not find %s with id %s', modelName, modelId)),
|
||||
code: 'MODEL_NOT_FOUND',
|
||||
},
|
||||
401: {
|
||||
message: 'Authorization Required',
|
||||
code: 'AUTHORIZATION_REQUIRED'
|
||||
}
|
||||
message: g.f('Authorization Required'),
|
||||
code: 'AUTHORIZATION_REQUIRED',
|
||||
},
|
||||
};
|
||||
|
||||
var e = new Error(messages[errStatusCode].message || messages[403].message);
|
||||
|
@ -408,7 +410,7 @@ app.enableAuth = function(options) {
|
|||
|
||||
app.boot = function(options) {
|
||||
throw new Error(
|
||||
'`app.boot` was removed, use the new module loopback-boot instead');
|
||||
g.f('{{`app.boot`}} was removed, use the new module {{loopback-boot}} instead'));
|
||||
};
|
||||
|
||||
function dataSourcesFromConfig(name, config, connectorRegistry, registry) {
|
||||
|
@ -486,7 +488,7 @@ function setSharedMethodSharedProperties(model, app, modelConfigs) {
|
|||
var settingValue = settings[setting];
|
||||
var settingValueType = typeof settingValue;
|
||||
if (settingValueType !== 'boolean')
|
||||
throw new TypeError('Expected boolean, got ' + settingValueType);
|
||||
throw new TypeError(g.f('Expected boolean, got %s', settingValueType));
|
||||
});
|
||||
|
||||
// set sharedMethod.shared using the merged settings
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* Dependencies.
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var mailer = require('nodemailer');
|
||||
var assert = require('assert');
|
||||
var debug = require('debug')('loopback:connector:mail');
|
||||
|
@ -149,22 +151,22 @@ Mailer.send = function(options, fn) {
|
|||
}
|
||||
|
||||
if (debug.enabled || settings && settings.debug) {
|
||||
console.log('Sending Mail:');
|
||||
g.log('Sending Mail:');
|
||||
if (options.transport) {
|
||||
console.log('\t TRANSPORT:', options.transport);
|
||||
console.log(g.f('\t TRANSPORT:%s', options.transport));
|
||||
}
|
||||
console.log('\t TO:', options.to);
|
||||
console.log('\t FROM:', options.from);
|
||||
console.log('\t SUBJECT:', options.subject);
|
||||
console.log('\t TEXT:', options.text);
|
||||
console.log('\t HTML:', options.html);
|
||||
g.log('\t TO:%s', options.to);
|
||||
g.log('\t FROM:%s', options.from);
|
||||
g.log('\t SUBJECT:%s', options.subject);
|
||||
g.log('\t TEXT:%s', options.text);
|
||||
g.log('\t HTML:%s', options.html);
|
||||
}
|
||||
|
||||
if (transport) {
|
||||
assert(transport.sendMail, 'You must supply an Email.settings.transports containing a valid transport');
|
||||
transport.sendMail(options, fn);
|
||||
} else {
|
||||
console.warn('Warning: No email transport specified for sending email.' +
|
||||
g.warn('Warning: No email transport specified for sending email.' +
|
||||
' Setup a transport to send mail messages.');
|
||||
process.nextTick(function() {
|
||||
fn(null, options);
|
||||
|
|
89
lib/model.js
89
lib/model.js
|
@ -6,6 +6,9 @@
|
|||
/*!
|
||||
* Module Dependencies.
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var assert = require('assert');
|
||||
var RemoteObjects = require('strong-remoting');
|
||||
var SharedClass = require('strong-remoting').SharedClass;
|
||||
|
@ -168,14 +171,14 @@ module.exports = function(registry) {
|
|||
} else if (model) {
|
||||
fn(null, model);
|
||||
} else {
|
||||
err = new Error('could not find a model with id ' + id);
|
||||
err = new Error(g.f('could not find a model with {{id}} %s', id));
|
||||
err.statusCode = 404;
|
||||
err.code = 'MODEL_NOT_FOUND';
|
||||
fn(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fn(new Error('must specify an id or data'));
|
||||
fn(new Error(g.f('must specify an {{id}} or {{data}}')));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -449,8 +452,8 @@ module.exports = function(registry) {
|
|||
http: {verb: 'get', path: '/' + pathName},
|
||||
accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}},
|
||||
accessType: 'READ',
|
||||
description: 'Fetches belongsTo relation ' + relationName + '.',
|
||||
returns: {arg: relationName, type: modelName, root: true}
|
||||
description: g.f('Fetches belongsTo relation %s.', relationName),
|
||||
returns: {arg: relationName, type: modelName, root: true},
|
||||
}, fn);
|
||||
};
|
||||
|
||||
|
@ -458,7 +461,7 @@ module.exports = function(registry) {
|
|||
if (ctx.result !== null) return cb();
|
||||
|
||||
var fk = ctx.getArgByName('fk');
|
||||
var msg = 'Unknown "' + toModelName + '" id "' + fk + '".';
|
||||
var msg = g.f('Unknown "%s" id "%s".', toModelName, fk);
|
||||
var error = new Error(msg);
|
||||
error.statusCode = error.status = 404;
|
||||
error.code = 'MODEL_NOT_FOUND';
|
||||
|
@ -473,7 +476,7 @@ module.exports = function(registry) {
|
|||
isStatic: false,
|
||||
http: {verb: 'get', path: '/' + pathName},
|
||||
accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}},
|
||||
description: 'Fetches hasOne relation ' + relationName + '.',
|
||||
description: g.f('Fetches hasOne relation %s.', relationName),
|
||||
accessType: 'READ',
|
||||
returns: {arg: relationName, type: relation.modelTo.modelName, root: true},
|
||||
rest: {after: convertNullToNotFoundError.bind(null, toModelName)}
|
||||
|
@ -483,7 +486,7 @@ module.exports = function(registry) {
|
|||
isStatic: false,
|
||||
http: {verb: 'post', path: '/' + pathName},
|
||||
accepts: {arg: 'data', type: toModelName, http: {source: 'body'}},
|
||||
description: 'Creates a new instance in ' + relationName + ' of this model.',
|
||||
description: g.f('Creates a new instance in %s of this model.', relationName),
|
||||
accessType: 'WRITE',
|
||||
returns: {arg: 'data', type: toModelName, root: true}
|
||||
});
|
||||
|
@ -492,7 +495,7 @@ module.exports = function(registry) {
|
|||
isStatic: false,
|
||||
http: {verb: 'put', path: '/' + pathName},
|
||||
accepts: {arg: 'data', type: toModelName, http: {source: 'body'}},
|
||||
description: 'Update ' + relationName + ' of this model.',
|
||||
description: g.f('Update %s of this model.', relationName),
|
||||
accessType: 'WRITE',
|
||||
returns: {arg: 'data', type: toModelName, root: true}
|
||||
});
|
||||
|
@ -500,8 +503,8 @@ module.exports = function(registry) {
|
|||
define('__destroy__' + relationName, {
|
||||
isStatic: false,
|
||||
http: {verb: 'delete', path: '/' + pathName},
|
||||
description: 'Deletes ' + relationName + ' of this model.',
|
||||
accessType: 'WRITE'
|
||||
description: g.f('Deletes %s of this model.', relationName),
|
||||
accessType: 'WRITE',
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -514,9 +517,10 @@ module.exports = function(registry) {
|
|||
isStatic: false,
|
||||
http: {verb: 'get', path: '/' + pathName + '/:fk'},
|
||||
accepts: {arg: 'fk', type: 'any',
|
||||
description: 'Foreign key for ' + relationName, required: true,
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'}},
|
||||
description: 'Find a related item by id for ' + relationName + '.',
|
||||
description: g.f('Find a related item by id for %s.', relationName),
|
||||
accessType: 'READ',
|
||||
returns: {arg: 'result', type: toModelName, root: true},
|
||||
rest: {after: convertNullToNotFoundError.bind(null, toModelName)}
|
||||
|
@ -526,10 +530,11 @@ module.exports = function(registry) {
|
|||
define('__destroyById__' + relationName, {
|
||||
isStatic: false,
|
||||
http: {verb: 'delete', path: '/' + pathName + '/:fk'},
|
||||
accepts: {arg: 'fk', type: 'any',
|
||||
description: 'Foreign key for ' + relationName, required: true,
|
||||
accepts: { arg: 'fk', type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'}},
|
||||
description: 'Delete a related item by id for ' + relationName + '.',
|
||||
description: g.f('Delete a related item by id for %s.', relationName),
|
||||
accessType: 'WRITE',
|
||||
returns: []
|
||||
}, destroyByIdFunc);
|
||||
|
@ -540,11 +545,12 @@ module.exports = function(registry) {
|
|||
http: {verb: 'put', path: '/' + pathName + '/:fk'},
|
||||
accepts: [
|
||||
{arg: 'fk', type: 'any',
|
||||
description: 'Foreign key for ' + relationName, required: true,
|
||||
http: {source: 'path'}},
|
||||
{arg: 'data', type: toModelName, http: {source: 'body'}}
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: { source: 'path' }},
|
||||
{arg: 'data', type: toModelName, http: {source: 'body'}},
|
||||
],
|
||||
description: 'Update a related item by id for ' + relationName + '.',
|
||||
description: g.f('Update a related item by id for %s.', relationName),
|
||||
accessType: 'WRITE',
|
||||
returns: {arg: 'result', type: toModelName, root: true}
|
||||
}, updateByIdFunc);
|
||||
|
@ -562,10 +568,11 @@ module.exports = function(registry) {
|
|||
define('__link__' + relationName, {
|
||||
isStatic: false,
|
||||
http: {verb: 'put', path: '/' + pathName + '/rel/:fk'},
|
||||
accepts: [{arg: 'fk', type: 'any',
|
||||
description: 'Foreign key for ' + relationName, required: true,
|
||||
accepts: [{ arg: 'fk', type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'}}].concat(accepts),
|
||||
description: 'Add a related item by id for ' + relationName + '.',
|
||||
description: g.f('Add a related item by id for %s.', relationName),
|
||||
accessType: 'WRITE',
|
||||
returns: {arg: relationName, type: modelThrough.modelName, root: true}
|
||||
}, addFunc);
|
||||
|
@ -575,9 +582,10 @@ module.exports = function(registry) {
|
|||
isStatic: false,
|
||||
http: {verb: 'delete', path: '/' + pathName + '/rel/:fk'},
|
||||
accepts: {arg: 'fk', type: 'any',
|
||||
description: 'Foreign key for ' + relationName, required: true,
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'}},
|
||||
description: 'Remove the ' + relationName + ' relation to an item by id.',
|
||||
description: g.f('Remove the %s relation to an item by id.', relationName),
|
||||
accessType: 'WRITE',
|
||||
returns: []
|
||||
}, removeFunc);
|
||||
|
@ -589,9 +597,10 @@ module.exports = function(registry) {
|
|||
isStatic: false,
|
||||
http: {verb: 'head', path: '/' + pathName + '/rel/:fk'},
|
||||
accepts: {arg: 'fk', type: 'any',
|
||||
description: 'Foreign key for ' + relationName, required: true,
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'}},
|
||||
description: 'Check the existence of ' + relationName + ' relation to an item by id.',
|
||||
description: g.f('Check the existence of %s relation to an item by id.', relationName),
|
||||
accessType: 'READ',
|
||||
returns: {arg: 'exists', type: 'boolean', root: true},
|
||||
rest: {
|
||||
|
@ -600,7 +609,7 @@ module.exports = function(registry) {
|
|||
if (ctx.result === false) {
|
||||
var modelName = ctx.method.sharedClass.name;
|
||||
var id = ctx.getArgByName('id');
|
||||
var msg = 'Unknown "' + modelName + '" id "' + id + '".';
|
||||
var msg = g.f('Unknown "%s" {{id}} "%s".', modelName, id);
|
||||
var error = new Error(msg);
|
||||
error.statusCode = error.status = 404;
|
||||
error.code = 'MODEL_NOT_FOUND';
|
||||
|
@ -634,7 +643,7 @@ module.exports = function(registry) {
|
|||
isStatic: isStatic,
|
||||
http: {verb: 'get', path: '/' + pathName},
|
||||
accepts: {arg: 'filter', type: 'object'},
|
||||
description: 'Queries ' + scopeName + ' of ' + this.modelName + '.',
|
||||
description: g.f('Queries %s of %s.', scopeName, this.modelName),
|
||||
accessType: 'READ',
|
||||
returns: {arg: scopeName, type: [toModelName], root: true}
|
||||
});
|
||||
|
@ -643,7 +652,7 @@ module.exports = function(registry) {
|
|||
isStatic: isStatic,
|
||||
http: {verb: 'post', path: '/' + pathName},
|
||||
accepts: {arg: 'data', type: toModelName, http: {source: 'body'}},
|
||||
description: 'Creates a new instance in ' + scopeName + ' of this model.',
|
||||
description: g.f('Creates a new instance in %s of this model.', scopeName),
|
||||
accessType: 'WRITE',
|
||||
returns: {arg: 'data', type: toModelName, root: true}
|
||||
});
|
||||
|
@ -651,15 +660,16 @@ module.exports = function(registry) {
|
|||
define('__delete__' + scopeName, {
|
||||
isStatic: isStatic,
|
||||
http: {verb: 'delete', path: '/' + pathName},
|
||||
description: 'Deletes all ' + scopeName + ' of this model.',
|
||||
accessType: 'WRITE'
|
||||
description: g.f('Deletes all %s of this model.', scopeName),
|
||||
accessType: 'WRITE',
|
||||
});
|
||||
|
||||
define('__count__' + scopeName, {
|
||||
isStatic: isStatic,
|
||||
http: {verb: 'get', path: '/' + pathName + '/count'},
|
||||
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
|
||||
description: 'Counts ' + scopeName + ' of ' + this.modelName + '.',
|
||||
accepts: {arg: 'where', type: 'object',
|
||||
description: g.f('Criteria to match model instances')},
|
||||
description: g.f('Counts %s of %s.', scopeName, this.modelName),
|
||||
accessType: 'READ',
|
||||
returns: {arg: 'count', type: 'number'}
|
||||
});
|
||||
|
@ -708,9 +718,9 @@ module.exports = function(registry) {
|
|||
acceptArgs = [
|
||||
{
|
||||
arg: paramName, type: 'any', http: { source: 'path' },
|
||||
description: 'Foreign key for ' + relation.name + '.',
|
||||
required: true
|
||||
}
|
||||
description: g.f('Foreign key for %s.', relation.name),
|
||||
required: true,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
httpPath = pathName;
|
||||
|
@ -738,12 +748,12 @@ module.exports = function(registry) {
|
|||
|
||||
var getterFn = relation.modelFrom.prototype[getterName];
|
||||
if (typeof getterFn !== 'function') {
|
||||
throw new Error('Invalid remote method: `' + getterName + '`');
|
||||
throw new Error(g.f('Invalid remote method: `%s`', getterName));
|
||||
}
|
||||
|
||||
var nestedFn = relation.modelTo.prototype[method.name];
|
||||
if (typeof nestedFn !== 'function') {
|
||||
throw new Error('Invalid remote method: `' + method.name + '`');
|
||||
throw new Error(g.f('Invalid remote method: `%s`', method.name));
|
||||
}
|
||||
|
||||
var opts = {};
|
||||
|
@ -836,7 +846,8 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
} else {
|
||||
throw new Error('Relation `' + relationName + '` does not exist for model `' + this.modelName + '`');
|
||||
var msg = g.f('Relation `%s` does not exist for model `%s`', relationName, this.modelName);
|
||||
throw new Error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* Module Dependencies.
|
||||
*/
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
var runtime = require('./runtime');
|
||||
var assert = require('assert');
|
||||
var async = require('async');
|
||||
|
@ -65,9 +66,10 @@ module.exports = function(registry) {
|
|||
|
||||
function throwNotAttached(modelName, methodName) {
|
||||
throw new Error(
|
||||
'Cannot call ' + modelName + '.' + methodName + '().' +
|
||||
' The ' + methodName + ' method has not been setup.' +
|
||||
' The PersistedModel has not been correctly attached to a DataSource!'
|
||||
g.f('Cannot call %s.%s().' +
|
||||
' The %s method has not been setup.' +
|
||||
' The {{PersistedModel}} has not been correctly attached to a {{DataSource}}!',
|
||||
modelName, methodName, methodName)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -82,7 +84,7 @@ module.exports = function(registry) {
|
|||
|
||||
var modelName = ctx.method.sharedClass.name;
|
||||
var id = ctx.getArgByName('id');
|
||||
var msg = 'Unknown "' + modelName + '" id "' + id + '".';
|
||||
var msg = g.f('Unknown "%s" {{id}} "%s".', modelName, id);
|
||||
var error = new Error(msg);
|
||||
error.statusCode = error.status = 404;
|
||||
error.code = 'MODEL_NOT_FOUND';
|
||||
|
@ -558,7 +560,7 @@ module.exports = function(registry) {
|
|||
}
|
||||
|
||||
setRemoting(PersistedModel, 'create', {
|
||||
description: 'Create a new instance of the model and persist it into the data source.',
|
||||
description: g.f('Create a new instance of the model and persist it into the data source.'),
|
||||
accessType: 'WRITE',
|
||||
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
|
||||
returns: {arg: 'data', type: typeName, root: true},
|
||||
|
@ -567,7 +569,8 @@ module.exports = function(registry) {
|
|||
|
||||
setRemoting(PersistedModel, 'upsert', {
|
||||
aliases: ['updateOrCreate'],
|
||||
description: 'Update an existing model instance or insert a new one into the data source.',
|
||||
description: g.f('Update an existing model instance or insert a new one ' +
|
||||
'into the data source.'),
|
||||
accessType: 'WRITE',
|
||||
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
|
||||
returns: {arg: 'data', type: typeName, root: true},
|
||||
|
@ -575,7 +578,7 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'exists', {
|
||||
description: 'Check whether a model instance exists in the data source.',
|
||||
description: g.f('Check whether a model instance exists in the data source.'),
|
||||
accessType: 'READ',
|
||||
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true},
|
||||
returns: {arg: 'exists', type: 'boolean'},
|
||||
|
@ -606,13 +609,13 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'findById', {
|
||||
description: 'Find a model instance by id from the data source.',
|
||||
description: g.f('Find a model instance by {{id}} from the data source.'),
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{ arg: 'id', type: 'any', description: 'Model id', required: true,
|
||||
http: {source: 'path'}},
|
||||
{ arg: 'filter', type: 'object',
|
||||
description: 'Filter defining fields and include'}
|
||||
description: g.f('Filter defining fields and include') },
|
||||
],
|
||||
returns: {arg: 'data', type: typeName, root: true},
|
||||
http: {verb: 'get', path: '/:id'},
|
||||
|
@ -620,7 +623,7 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'find', {
|
||||
description: 'Find all instances of the model matched by filter from the data source.',
|
||||
description: g.f('Find all instances of the model matched by filter from the data source.'),
|
||||
accessType: 'READ',
|
||||
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
|
||||
returns: {arg: 'data', type: [typeName], root: true},
|
||||
|
@ -628,7 +631,7 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'findOne', {
|
||||
description: 'Find first instance of the model matched by filter from the data source.',
|
||||
description: g.f('Find first instance of the model matched by filter from the data source.'),
|
||||
accessType: 'READ',
|
||||
accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, include, order, offset, and limit'},
|
||||
returns: {arg: 'data', type: typeName, root: true},
|
||||
|
@ -637,7 +640,7 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'destroyAll', {
|
||||
description: 'Delete all matching records.',
|
||||
description: g.f('Delete all matching records.'),
|
||||
accessType: 'WRITE',
|
||||
accepts: {arg: 'where', type: 'object', description: 'filter.where object'},
|
||||
returns: {
|
||||
|
@ -652,17 +655,17 @@ module.exports = function(registry) {
|
|||
|
||||
setRemoting(PersistedModel, 'updateAll', {
|
||||
aliases: ['update'],
|
||||
description: 'Update instances of the model matched by where from the data source.',
|
||||
description: g.f('Update instances of the model matched by {{where}} from the data source.'),
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
{arg: 'where', type: 'object', http: {source: 'query'},
|
||||
description: 'Criteria to match model instances'},
|
||||
{arg: 'where', type: 'object', http: { source: 'query'},
|
||||
description: g.f('Criteria to match model instances')},
|
||||
{arg: 'data', type: 'object', http: {source: 'body'},
|
||||
description: 'An object of model property name/value pairs'},
|
||||
description: g.f('An object of model property name/value pairs')},
|
||||
],
|
||||
returns: {
|
||||
arg: 'count',
|
||||
description: 'The number of instances updated',
|
||||
description: g.f('The number of instances updated'),
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
|
@ -671,7 +674,7 @@ module.exports = function(registry) {
|
|||
|
||||
setRemoting(PersistedModel, 'deleteById', {
|
||||
aliases: ['destroyById', 'removeById'],
|
||||
description: 'Delete a model instance by id from the data source.',
|
||||
description: g.f('Delete a model instance by {{id}} from the data source.'),
|
||||
accessType: 'WRITE',
|
||||
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true,
|
||||
http: {source: 'path'}},
|
||||
|
@ -680,7 +683,7 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'count', {
|
||||
description: 'Count instances of the model matched by where from the data source.',
|
||||
description: g.f('Count instances of the model matched by where from the data source.'),
|
||||
accessType: 'READ',
|
||||
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
|
||||
returns: {arg: 'count', type: 'number'},
|
||||
|
@ -688,7 +691,8 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel.prototype, 'updateAttributes', {
|
||||
description: 'Update attributes for a model instance and persist it into the data source.',
|
||||
description: g.f('Update attributes for a model instance and persist it into ' +
|
||||
'the data source.'),
|
||||
accessType: 'WRITE',
|
||||
accepts: {arg: 'data', type: 'object', http: {source: 'body'}, description: 'An object of model property name/value pairs'},
|
||||
returns: {arg: 'data', type: typeName, root: true},
|
||||
|
@ -697,7 +701,7 @@ module.exports = function(registry) {
|
|||
|
||||
if (options.trackChanges || options.enableRemoteReplication) {
|
||||
setRemoting(PersistedModel, 'diff', {
|
||||
description: 'Get a set of deltas and conflicts since the given checkpoint.',
|
||||
description: g.f('Get a set of deltas and conflicts since the given checkpoint.'),
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'},
|
||||
|
@ -709,8 +713,8 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'changes', {
|
||||
description: 'Get the changes to a model since a given checkpoint.' +
|
||||
'Provide a filter object to reduce the number of results returned.',
|
||||
description: g.f('Get the changes to a model since a given checkpoint.' +
|
||||
'Provide a filter object to reduce the number of results returned.'),
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{arg: 'since', type: 'number', description: 'Only return changes since this checkpoint'},
|
||||
|
@ -721,7 +725,7 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'checkpoint', {
|
||||
description: 'Create a checkpoint.',
|
||||
description: g.f('Create a checkpoint.'),
|
||||
// The replication algorithm needs to create a source checkpoint,
|
||||
// even though it is otherwise not making any source changes.
|
||||
// We need to allow this method for users that don't have full
|
||||
|
@ -732,14 +736,14 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'currentCheckpoint', {
|
||||
description: 'Get the current checkpoint.',
|
||||
description: g.f('Get the current checkpoint.'),
|
||||
accessType: 'READ',
|
||||
returns: {arg: 'checkpoint', type: 'object', root: true},
|
||||
http: {verb: 'get', path: '/checkpoint'}
|
||||
});
|
||||
|
||||
setRemoting(PersistedModel, 'createUpdates', {
|
||||
description: 'Create an update list from a delta list.',
|
||||
description: g.f('Create an update list from a delta list.'),
|
||||
// This operation is read-only, it does not change any local data.
|
||||
// It is called by the replication algorithm to compile a list
|
||||
// of changes to apply on the target.
|
||||
|
@ -750,14 +754,14 @@ module.exports = function(registry) {
|
|||
});
|
||||
|
||||
setRemoting(PersistedModel, 'bulkUpdate', {
|
||||
description: 'Run multiple updates at once. Note: this is not atomic.',
|
||||
description: g.f('Run multiple updates at once. Note: this is not atomic.'),
|
||||
accessType: 'WRITE',
|
||||
accepts: {arg: 'updates', type: 'array'},
|
||||
http: {verb: 'post', path: '/bulk-update'}
|
||||
});
|
||||
|
||||
setRemoting(PersistedModel, 'findLastChange', {
|
||||
description: 'Get the most recent change record for this instance.',
|
||||
description: g.f('Get the most recent change record for this instance.'),
|
||||
accessType: 'READ',
|
||||
accepts: {
|
||||
arg: 'id', type: 'any', required: true, http: { source: 'path' },
|
||||
|
@ -769,8 +773,8 @@ module.exports = function(registry) {
|
|||
|
||||
setRemoting(PersistedModel, 'updateLastChange', {
|
||||
description: [
|
||||
'Update the properties of the most recent change record',
|
||||
'kept for this instance.'
|
||||
g.f('Update the properties of the most recent change record ' +
|
||||
'kept for this instance.'),
|
||||
],
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
|
@ -780,7 +784,7 @@ module.exports = function(registry) {
|
|||
},
|
||||
{
|
||||
arg: 'data', type: 'object', http: {source: 'body'},
|
||||
description: 'An object of Change property name/value pairs'
|
||||
description: g.f('An object of Change property name/value pairs'),
|
||||
},
|
||||
],
|
||||
returns: { arg: 'result', type: this.Change.modelName, root: true },
|
||||
|
@ -806,7 +810,7 @@ module.exports = function(registry) {
|
|||
}
|
||||
|
||||
setRemoting(PersistedModel, 'createChangeStream', {
|
||||
description: 'Create a change stream.',
|
||||
description: g.f('Create a change stream.'),
|
||||
accessType: 'READ',
|
||||
http: [
|
||||
{verb: 'post', path: '/change-stream'},
|
||||
|
@ -1148,7 +1152,7 @@ module.exports = function(registry) {
|
|||
if (err) return cb(err);
|
||||
if (!inst) {
|
||||
return cb &&
|
||||
cb(new Error('Missing data for change: ' + change.modelId));
|
||||
cb(new Error(g.f('Missing data for change: %s', change.modelId)));
|
||||
}
|
||||
if (inst.toObject) {
|
||||
update.data = inst.toObject();
|
||||
|
@ -1216,7 +1220,7 @@ module.exports = function(registry) {
|
|||
async.parallel(tasks, function(err) {
|
||||
if (err) return callback(err);
|
||||
if (conflicts.length) {
|
||||
err = new Error('Conflict');
|
||||
err = new Error(g.f('Conflict'));
|
||||
err.statusCode = 409;
|
||||
err.details = { conflicts: conflicts };
|
||||
return callback(err);
|
||||
|
@ -1280,16 +1284,16 @@ module.exports = function(registry) {
|
|||
case undefined:
|
||||
case null:
|
||||
return cb(new Error(
|
||||
'Cannot apply bulk updates, ' +
|
||||
g.f('Cannot apply bulk updates, ' +
|
||||
'the connector does not correctly report ' +
|
||||
'the number of updated records.'));
|
||||
'the number of updated records.')));
|
||||
|
||||
default:
|
||||
debug('%s.updateAll modified unexpected number of instances: %j',
|
||||
Model.modelName, count);
|
||||
return cb(new Error(
|
||||
'Bulk update failed, the connector has modified unexpected ' +
|
||||
'number of records: ' + JSON.stringify(count)));
|
||||
g.f('Bulk update failed, the connector has modified unexpected ' +
|
||||
'number of records: %s', JSON.stringify(count))));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1362,16 +1366,16 @@ module.exports = function(registry) {
|
|||
case undefined:
|
||||
case null:
|
||||
return cb(new Error(
|
||||
'Cannot apply bulk updates, ' +
|
||||
g.f('Cannot apply bulk updates, ' +
|
||||
'the connector does not correctly report ' +
|
||||
'the number of deleted records.'));
|
||||
'the number of deleted records.')));
|
||||
|
||||
default:
|
||||
debug('%s.deleteAll modified unexpected number of instances: %j',
|
||||
Model.modelName, count);
|
||||
return cb(new Error(
|
||||
'Bulk update failed, the connector has deleted unexpected ' +
|
||||
'number of records: ' + JSON.stringify(count)));
|
||||
g.f('Bulk update failed, the connector has deleted unexpected ' +
|
||||
'number of records: %s', JSON.stringify(count))));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1586,8 +1590,8 @@ module.exports = function(registry) {
|
|||
this.findLastChange(id, function(err, inst) {
|
||||
if (err) return cb(err);
|
||||
if (!inst) {
|
||||
err = new Error('No change record found for ' +
|
||||
self.modelName + ' with id ' + id);
|
||||
err = new Error(g.f('No change record found for %s with id %s',
|
||||
self.modelName, id));
|
||||
err.statusCode = 404;
|
||||
return cb(err);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
var assert = require('assert');
|
||||
var extend = require('util')._extend;
|
||||
var juggler = require('loopback-datasource-juggler');
|
||||
|
@ -113,11 +114,11 @@ Registry.prototype.createModel = function(name, properties, options) {
|
|||
|
||||
if (BaseModel === undefined) {
|
||||
if (baseName === 'DataModel') {
|
||||
console.warn('Model `%s` is extending deprecated `DataModel. ' +
|
||||
g.warn('Model `%s` is extending deprecated `DataModel. ' +
|
||||
'Use `PersistedModel` instead.', name);
|
||||
BaseModel = this.getModel('PersistedModel');
|
||||
} else {
|
||||
console.warn('Model `%s` is extending an unknown model `%s`. ' +
|
||||
g.warn('Model `%s` is extending an unknown model `%s`. ' +
|
||||
'Using `PersistedModel` as the base.', name, baseName);
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
|
|||
relations[key] = extend(relations[key] || {}, config.relations[key]);
|
||||
});
|
||||
} else if (config.relations != null) {
|
||||
console.warn('The relations property of `%s` configuration ' +
|
||||
g.warn('The relations property of `%s` configuration ' +
|
||||
'must be an object', modelName);
|
||||
}
|
||||
|
||||
|
@ -208,7 +209,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
|
|||
addACL(acls, acl);
|
||||
});
|
||||
} else if (config.acls != null) {
|
||||
console.warn('The acls property of `%s` configuration ' +
|
||||
g.warn('The acls property of `%s` configuration ' +
|
||||
'must be an array of objects', modelName);
|
||||
}
|
||||
|
||||
|
@ -225,12 +226,12 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
|
|||
if (!(p in excludedProperties)) {
|
||||
settings[p] = config.options[p];
|
||||
} else {
|
||||
console.warn('Property `%s` cannot be reconfigured for `%s`',
|
||||
g.warn('Property `%s` cannot be reconfigured for `%s`',
|
||||
p, modelName);
|
||||
}
|
||||
}
|
||||
} else if (config.options != null) {
|
||||
console.warn('The options property of `%s` configuration ' +
|
||||
g.warn('The options property of `%s` configuration ' +
|
||||
'must be an object', modelName);
|
||||
}
|
||||
|
||||
|
@ -238,8 +239,8 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
|
|||
// configuration, so that the datasource picks up updated relations
|
||||
if (config.dataSource) {
|
||||
assert(config.dataSource instanceof DataSource,
|
||||
'Cannot configure ' + ModelCtor.modelName +
|
||||
': config.dataSource must be an instance of DataSource');
|
||||
g.f('Cannot configure %s: {{config.dataSource}} must be an instance ' +
|
||||
'of {{DataSource}}', ModelCtor.modelName));
|
||||
ModelCtor.attachTo(config.dataSource);
|
||||
debug('Attached model `%s` to dataSource `%s`',
|
||||
modelName, config.dataSource.name);
|
||||
|
@ -249,8 +250,8 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
|
|||
} else {
|
||||
debug('Model `%s` is not attached to any DataSource, possibly by a mistake.',
|
||||
modelName);
|
||||
console.warn(
|
||||
'The configuration of `%s` is missing `dataSource` property.\n' +
|
||||
g.warn(
|
||||
'The configuration of `%s` is missing {{`dataSource`}} property.\n' +
|
||||
'Use `null` or `false` to mark models not attached to any data source.',
|
||||
modelName);
|
||||
}
|
||||
|
@ -262,7 +263,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
|
|||
Registry.prototype._defineRemoteMethods = function(ModelCtor, methods) {
|
||||
if (!methods) return;
|
||||
if (typeof methods !== 'object') {
|
||||
console.warn('Ignoring non-object "methods" setting of "%s".',
|
||||
g.warn('Ignoring non-object "methods" setting of "%s".',
|
||||
ModelCtor.modelName);
|
||||
return;
|
||||
}
|
||||
|
@ -270,11 +271,11 @@ Registry.prototype._defineRemoteMethods = function(ModelCtor, methods) {
|
|||
Object.keys(methods).forEach(function(key) {
|
||||
var meta = methods[key];
|
||||
if (typeof meta.isStatic !== 'boolean') {
|
||||
console.warn('Remoting metadata for "%s.%s" is missing "isStatic" ' +
|
||||
g.warn('Remoting metadata for "%s.%s" is missing "isStatic" ' +
|
||||
'flag, the method is registered as an instance method.',
|
||||
ModelCtor.modelName,
|
||||
key);
|
||||
console.warn('This behaviour may change in the next major version.');
|
||||
g.warn('This behaviour may change in the next major version.');
|
||||
}
|
||||
ModelCtor.remoteMethod(key, meta);
|
||||
});
|
||||
|
@ -306,7 +307,7 @@ Registry.prototype.getModel = function(modelName) {
|
|||
var model = this.findModel(modelName);
|
||||
if (model) return model;
|
||||
|
||||
throw new Error('Model not found: ' + modelName);
|
||||
throw new Error(g.f('Model not found: %s', modelName));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
var assert = require('assert');
|
||||
var express = require('express');
|
||||
var merge = require('util')._extend;
|
||||
|
@ -188,7 +190,7 @@ proto.middleware = function(name, paths, handler) {
|
|||
}
|
||||
|
||||
if (this._requestHandlingPhases.indexOf(name) === -1)
|
||||
throw new Error('Unknown middleware phase ' + name);
|
||||
throw new Error(g.f('Unknown {{middleware}} phase %s', name));
|
||||
|
||||
debug('use %s %s %s', fullPhaseName, paths, handlerName);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
"nodemailer-stub-transport": "^1.0.0",
|
||||
"serve-favicon": "^2.2.0",
|
||||
"stable": "^0.1.5",
|
||||
"strong-globalize": "^2.6.2",
|
||||
"strong-remoting": "^2.21.0",
|
||||
"uid2": "0.0.3",
|
||||
"underscore.string": "^3.0.3"
|
||||
|
|
Loading…
Reference in New Issue