feat: change hasone relation error message
The current hasone error message is not appropriate one. So adds a better message.
This commit is contained in:
parent
2db09a3d00
commit
143182fe2b
374
lib/model.js
374
lib/model.js
|
@ -131,7 +131,8 @@ module.exports = function(registry) {
|
|||
ModelCtor.sharedCtor = function(data, id, options, fn) {
|
||||
const ModelCtor = this;
|
||||
|
||||
const isRemoteInvocationWithOptions = typeof data !== 'object' &&
|
||||
const isRemoteInvocationWithOptions =
|
||||
typeof data !== 'object' &&
|
||||
typeof id === 'object' &&
|
||||
typeof options === 'function';
|
||||
if (isRemoteInvocationWithOptions) {
|
||||
|
@ -187,15 +188,18 @@ module.exports = function(registry) {
|
|||
|
||||
const idDesc = ModelCtor.modelName + ' id';
|
||||
ModelCtor.sharedCtor.accepts = [
|
||||
{arg: 'id', type: 'any', required: true, http: {source: 'path'},
|
||||
description: idDesc},
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'any',
|
||||
required: true,
|
||||
http: {source: 'path'},
|
||||
description: idDesc,
|
||||
},
|
||||
// {arg: 'instance', type: 'object', http: {source: 'body'}}
|
||||
{arg: 'options', type: 'object', http: createOptionsViaModelMethod},
|
||||
];
|
||||
|
||||
ModelCtor.sharedCtor.http = [
|
||||
{path: '/:id'},
|
||||
];
|
||||
ModelCtor.sharedCtor.http = [{path: '/:id'}];
|
||||
|
||||
ModelCtor.sharedCtor.returns = {root: true};
|
||||
|
||||
|
@ -203,11 +207,11 @@ module.exports = function(registry) {
|
|||
extend(remotingOptions, options.remoting || {});
|
||||
|
||||
// create a sharedClass
|
||||
const sharedClass = ModelCtor.sharedClass = new SharedClass(
|
||||
const sharedClass = (ModelCtor.sharedClass = new SharedClass(
|
||||
ModelCtor.modelName,
|
||||
ModelCtor,
|
||||
remotingOptions,
|
||||
);
|
||||
));
|
||||
|
||||
// before remote hook
|
||||
ModelCtor.beforeRemote = function(name, fn) {
|
||||
|
@ -248,15 +252,20 @@ module.exports = function(registry) {
|
|||
};
|
||||
|
||||
if ('injectOptionsFromRemoteContext' in options) {
|
||||
console.warn(g.f(
|
||||
'%s is using model setting %s which is no longer available.',
|
||||
typeName, 'injectOptionsFromRemoteContext',
|
||||
));
|
||||
console.warn(g.f(
|
||||
'Please rework your app to use the offical solution for injecting ' +
|
||||
'"options" argument from request context,\nsee %s',
|
||||
'http://loopback.io/doc/en/lb3/Using-current-context.html',
|
||||
));
|
||||
console.warn(
|
||||
g.f(
|
||||
'%s is using model setting %s which is no longer available.',
|
||||
typeName,
|
||||
'injectOptionsFromRemoteContext',
|
||||
),
|
||||
);
|
||||
console.warn(
|
||||
g.f(
|
||||
'Please rework your app to use the offical solution for injecting ' +
|
||||
'"options" argument from request context,\nsee %s',
|
||||
'http://loopback.io/doc/en/lb3/Using-current-context.html',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// resolve relation functions
|
||||
|
@ -284,7 +293,8 @@ module.exports = function(registry) {
|
|||
} else if (
|
||||
relation.type === 'hasMany' ||
|
||||
relation.type === 'embedsMany' ||
|
||||
relation.type === 'referencesMany') {
|
||||
relation.type === 'referencesMany'
|
||||
) {
|
||||
ModelCtor.hasManyRemoting(relationName, relation, define);
|
||||
}
|
||||
// Automatically enable nestRemoting if the flag is set to true in the
|
||||
|
@ -345,19 +355,22 @@ module.exports = function(registry) {
|
|||
ctx = {};
|
||||
}
|
||||
|
||||
aclModel.checkAccessForContext({
|
||||
accessToken: token,
|
||||
model: this,
|
||||
property: sharedMethod.name,
|
||||
method: sharedMethod.name,
|
||||
sharedMethod: sharedMethod,
|
||||
modelId: modelId,
|
||||
accessType: this._getAccessTypeForMethod(sharedMethod),
|
||||
remotingContext: ctx,
|
||||
}, function(err, accessRequest) {
|
||||
if (err) return callback(err);
|
||||
callback(null, accessRequest.isAllowed());
|
||||
});
|
||||
aclModel.checkAccessForContext(
|
||||
{
|
||||
accessToken: token,
|
||||
model: this,
|
||||
property: sharedMethod.name,
|
||||
method: sharedMethod.name,
|
||||
sharedMethod: sharedMethod,
|
||||
modelId: modelId,
|
||||
accessType: this._getAccessTypeForMethod(sharedMethod),
|
||||
remotingContext: ctx,
|
||||
},
|
||||
function(err, accessRequest) {
|
||||
if (err) return callback(err);
|
||||
callback(null, accessRequest.isAllowed());
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -380,12 +393,15 @@ module.exports = function(registry) {
|
|||
|
||||
// Check the explicit setting of accessType
|
||||
if (method.accessType) {
|
||||
assert(method.accessType === ACL.READ ||
|
||||
method.accessType === ACL.REPLICATE ||
|
||||
method.accessType === ACL.WRITE ||
|
||||
method.accessType === ACL.EXECUTE, 'invalid accessType ' +
|
||||
method.accessType +
|
||||
'. It must be "READ", "REPLICATE", "WRITE", or "EXECUTE"');
|
||||
assert(
|
||||
method.accessType === ACL.READ ||
|
||||
method.accessType === ACL.REPLICATE ||
|
||||
method.accessType === ACL.WRITE ||
|
||||
method.accessType === ACL.EXECUTE,
|
||||
'invalid accessType ' +
|
||||
method.accessType +
|
||||
'. It must be "READ", "REPLICATE", "WRITE", or "EXECUTE"',
|
||||
);
|
||||
return method.accessType;
|
||||
}
|
||||
|
||||
|
@ -478,8 +494,7 @@ module.exports = function(registry) {
|
|||
};
|
||||
|
||||
function setupOptionsArgs(accepts, modelClass) {
|
||||
if (!Array.isArray(accepts))
|
||||
accepts = [accepts];
|
||||
if (!Array.isArray(accepts)) accepts = [accepts];
|
||||
|
||||
return accepts.map(function(arg) {
|
||||
if (arg.http && arg.http === 'optionsFromRequest') {
|
||||
|
@ -500,7 +515,10 @@ module.exports = function(registry) {
|
|||
*/
|
||||
const DEFAULT_OPTIONS = {
|
||||
// Default to `true` so that hidden properties cannot be used in query
|
||||
prohibitHiddenPropertiesInQuery: ModelCtor._getProhibitHiddenPropertiesInQuery({}, true),
|
||||
prohibitHiddenPropertiesInQuery: ModelCtor._getProhibitHiddenPropertiesInQuery(
|
||||
{},
|
||||
true,
|
||||
),
|
||||
// Default to `12` for the max depth of a query object
|
||||
maxDepthOfQuery: ModelCtor._getMaxDepthOfQuery({}, 12),
|
||||
// Default to `32` for the max depth of a data object
|
||||
|
@ -510,8 +528,10 @@ module.exports = function(registry) {
|
|||
if (typeof ModelCtor.createOptionsFromRemotingContext !== 'function')
|
||||
return DEFAULT_OPTIONS;
|
||||
debug('createOptionsFromRemotingContext for %s', ctx.method.stringName);
|
||||
return Object.assign(DEFAULT_OPTIONS,
|
||||
ModelCtor.createOptionsFromRemotingContext(ctx));
|
||||
return Object.assign(
|
||||
DEFAULT_OPTIONS,
|
||||
ModelCtor.createOptionsFromRemotingContext(ctx),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -524,8 +544,10 @@ module.exports = function(registry) {
|
|||
*/
|
||||
|
||||
Model.disableRemoteMethod = function(name, isStatic) {
|
||||
deprecated('Model.disableRemoteMethod is deprecated. ' +
|
||||
'Use Model.disableRemoteMethodByName instead.');
|
||||
deprecated(
|
||||
'Model.disableRemoteMethod is deprecated. ' +
|
||||
'Use Model.disableRemoteMethodByName instead.',
|
||||
);
|
||||
const key = this.sharedClass.getKeyFromMethodNameAndTarget(name, isStatic);
|
||||
this.sharedClass.disableMethodByName(key);
|
||||
this.emit('remoteMethodDisabled', this.sharedClass, key);
|
||||
|
@ -547,7 +569,8 @@ module.exports = function(registry) {
|
|||
let modelName = relation.modelTo && relation.modelTo.modelName;
|
||||
modelName = modelName || 'PersistedModel';
|
||||
const fn = this.prototype[relationName];
|
||||
const pathName = (relation.options.http && relation.options.http.path) || relationName;
|
||||
const pathName =
|
||||
(relation.options.http && relation.options.http.path) || relationName;
|
||||
define('__get__' + relationName, {
|
||||
isStatic: false,
|
||||
http: {verb: 'get', path: '/' + pathName},
|
||||
|
@ -565,7 +588,9 @@ module.exports = function(registry) {
|
|||
if (ctx.result !== null) return cb();
|
||||
|
||||
const fk = ctx.getArgByName('fk');
|
||||
const msg = g.f('Unknown "%s" id "%s".', toModelName, fk);
|
||||
const msg = fk ?
|
||||
g.f('Unknown "%s" id "%s".', toModelName, fk) :
|
||||
g.f('No "%s" instance(s) found', toModelName);
|
||||
const error = new Error(msg);
|
||||
error.statusCode = error.status = 404;
|
||||
error.code = 'MODEL_NOT_FOUND';
|
||||
|
@ -573,7 +598,8 @@ module.exports = function(registry) {
|
|||
}
|
||||
|
||||
Model.hasOneRemoting = function(relationName, relation, define) {
|
||||
const pathName = (relation.options.http && relation.options.http.path) || relationName;
|
||||
const pathName =
|
||||
(relation.options.http && relation.options.http.path) || relationName;
|
||||
const toModelName = relation.modelTo.modelName;
|
||||
|
||||
define('__get__' + relationName, {
|
||||
|
@ -585,7 +611,11 @@ module.exports = function(registry) {
|
|||
],
|
||||
description: g.f('Fetches hasOne relation %s.', relationName),
|
||||
accessType: 'READ',
|
||||
returns: {arg: relationName, type: relation.modelTo.modelName, root: true},
|
||||
returns: {
|
||||
arg: relationName,
|
||||
type: relation.modelTo.modelName,
|
||||
root: true,
|
||||
},
|
||||
rest: {after: convertNullToNotFoundError.bind(null, toModelName)},
|
||||
});
|
||||
|
||||
|
@ -594,12 +624,17 @@ module.exports = function(registry) {
|
|||
http: {verb: 'post', path: '/' + pathName},
|
||||
accepts: [
|
||||
{
|
||||
arg: 'data', type: 'object', model: toModelName,
|
||||
arg: 'data',
|
||||
type: 'object',
|
||||
model: toModelName,
|
||||
http: {source: 'body'},
|
||||
},
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
],
|
||||
description: g.f('Creates a new instance in %s of this model.', relationName),
|
||||
description: g.f(
|
||||
'Creates a new instance in %s of this model.',
|
||||
relationName,
|
||||
),
|
||||
accessType: 'WRITE',
|
||||
returns: {arg: 'data', type: toModelName, root: true},
|
||||
});
|
||||
|
@ -609,7 +644,9 @@ module.exports = function(registry) {
|
|||
http: {verb: 'put', path: '/' + pathName},
|
||||
accepts: [
|
||||
{
|
||||
arg: 'data', type: 'object', model: toModelName,
|
||||
arg: 'data',
|
||||
type: 'object',
|
||||
model: toModelName,
|
||||
http: {source: 'body'},
|
||||
},
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
|
@ -622,16 +659,15 @@ module.exports = function(registry) {
|
|||
define('__destroy__' + relationName, {
|
||||
isStatic: false,
|
||||
http: {verb: 'delete', path: '/' + pathName},
|
||||
accepts: [
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
],
|
||||
accepts: [{arg: 'options', type: 'object', http: 'optionsFromRequest'}],
|
||||
description: g.f('Deletes %s of this model.', relationName),
|
||||
accessType: 'WRITE',
|
||||
});
|
||||
};
|
||||
|
||||
Model.hasManyRemoting = function(relationName, relation, define) {
|
||||
const pathName = (relation.options.http && relation.options.http.path) || relationName;
|
||||
const pathName =
|
||||
(relation.options.http && relation.options.http.path) || relationName;
|
||||
const toModelName = relation.modelTo.modelName;
|
||||
|
||||
const findByIdFunc = this.prototype['__findById__' + relationName];
|
||||
|
@ -640,7 +676,8 @@ module.exports = function(registry) {
|
|||
http: {verb: 'get', path: '/' + pathName + '/:fk'},
|
||||
accepts: [
|
||||
{
|
||||
arg: 'fk', type: 'any',
|
||||
arg: 'fk',
|
||||
type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'},
|
||||
|
@ -659,7 +696,8 @@ module.exports = function(registry) {
|
|||
http: {verb: 'delete', path: '/' + pathName + '/:fk'},
|
||||
accepts: [
|
||||
{
|
||||
arg: 'fk', type: 'any',
|
||||
arg: 'fk',
|
||||
type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'},
|
||||
|
@ -676,11 +714,19 @@ module.exports = function(registry) {
|
|||
isStatic: false,
|
||||
http: {verb: 'put', path: '/' + pathName + '/:fk'},
|
||||
accepts: [
|
||||
{arg: 'fk', type: 'any',
|
||||
{
|
||||
arg: 'fk',
|
||||
type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'}},
|
||||
{arg: 'data', type: 'object', model: toModelName, http: {source: 'body'}},
|
||||
http: {source: 'path'},
|
||||
},
|
||||
{
|
||||
arg: 'data',
|
||||
type: 'object',
|
||||
model: toModelName,
|
||||
http: {source: 'body'},
|
||||
},
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
],
|
||||
description: g.f('Update a related item by id for %s.', relationName),
|
||||
|
@ -695,7 +741,9 @@ module.exports = function(registry) {
|
|||
if (relation.type === 'hasMany' && relation.modelThrough) {
|
||||
// Restrict: only hasManyThrough relation can have additional properties
|
||||
accepts.push({
|
||||
arg: 'data', type: 'object', model: modelThrough.modelName,
|
||||
arg: 'data',
|
||||
type: 'object',
|
||||
model: modelThrough.modelName,
|
||||
http: {source: 'body'},
|
||||
});
|
||||
}
|
||||
|
@ -704,13 +752,19 @@ module.exports = function(registry) {
|
|||
define('__link__' + relationName, {
|
||||
isStatic: false,
|
||||
http: {verb: 'put', path: '/' + pathName + '/rel/:fk'},
|
||||
accepts: [{arg: 'fk', type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'}},
|
||||
].concat(accepts).concat([
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
]),
|
||||
accepts: [
|
||||
{
|
||||
arg: 'fk',
|
||||
type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'},
|
||||
},
|
||||
]
|
||||
.concat(accepts)
|
||||
.concat([
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
]),
|
||||
description: g.f('Add a related item by id for %s.', relationName),
|
||||
accessType: 'WRITE',
|
||||
returns: {arg: relationName, type: modelThrough.modelName, root: true},
|
||||
|
@ -722,14 +776,18 @@ module.exports = function(registry) {
|
|||
http: {verb: 'delete', path: '/' + pathName + '/rel/:fk'},
|
||||
accepts: [
|
||||
{
|
||||
arg: 'fk', type: 'any',
|
||||
arg: 'fk',
|
||||
type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'},
|
||||
},
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
],
|
||||
description: g.f('Remove the %s relation to an item by id.', relationName),
|
||||
description: g.f(
|
||||
'Remove the %s relation to an item by id.',
|
||||
relationName,
|
||||
),
|
||||
accessType: 'WRITE',
|
||||
returns: [],
|
||||
}, removeFunc);
|
||||
|
@ -742,14 +800,18 @@ module.exports = function(registry) {
|
|||
http: {verb: 'head', path: '/' + pathName + '/rel/:fk'},
|
||||
accepts: [
|
||||
{
|
||||
arg: 'fk', type: 'any',
|
||||
arg: 'fk',
|
||||
type: 'any',
|
||||
description: g.f('Foreign key for %s', relationName),
|
||||
required: true,
|
||||
http: {source: 'path'},
|
||||
},
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
],
|
||||
description: g.f('Check the existence of %s relation to an item by id.', relationName),
|
||||
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: {
|
||||
|
@ -774,7 +836,8 @@ module.exports = function(registry) {
|
|||
|
||||
Model.scopeRemoting = function(scopeName, scope, define) {
|
||||
const pathName =
|
||||
(scope.options && scope.options.http && scope.options.http.path) || scopeName;
|
||||
(scope.options && scope.options.http && scope.options.http.path) ||
|
||||
scopeName;
|
||||
|
||||
let modelTo = scope.modelTo;
|
||||
|
||||
|
@ -795,7 +858,8 @@ module.exports = function(registry) {
|
|||
// createOnlyInstance flag in __create__ to indicate loopback-swagger
|
||||
// code to create a separate model instance for create operation only
|
||||
const updateOnlyProps = modelTo.getUpdateOnlyProperties ?
|
||||
modelTo.getUpdateOnlyProperties() : false;
|
||||
modelTo.getUpdateOnlyProperties() :
|
||||
false;
|
||||
const hasUpdateOnlyProps = updateOnlyProps && updateOnlyProps.length > 0;
|
||||
|
||||
define('__get__' + scopeName, {
|
||||
|
@ -824,7 +888,10 @@ module.exports = function(registry) {
|
|||
},
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
],
|
||||
description: g.f('Creates a new instance in %s of this model.', scopeName),
|
||||
description: g.f(
|
||||
'Creates a new instance in %s of this model.',
|
||||
scopeName,
|
||||
),
|
||||
accessType: 'WRITE',
|
||||
returns: {arg: 'data', type: toModelName, root: true},
|
||||
});
|
||||
|
@ -834,11 +901,14 @@ module.exports = function(registry) {
|
|||
http: {verb: 'delete', path: '/' + pathName},
|
||||
accepts: [
|
||||
{
|
||||
arg: 'where', type: 'object',
|
||||
arg: 'where',
|
||||
type: 'object',
|
||||
// The "where" argument is not exposed in the REST API
|
||||
// but we need to provide a value so that we can pass "options"
|
||||
// as the third argument.
|
||||
http: function(ctx) { return undefined; },
|
||||
http: function(ctx) {
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
],
|
||||
|
@ -851,7 +921,8 @@ module.exports = function(registry) {
|
|||
http: {verb: 'get', path: '/' + pathName + '/count'},
|
||||
accepts: [
|
||||
{
|
||||
arg: 'where', type: 'object',
|
||||
arg: 'where',
|
||||
type: 'object',
|
||||
description: 'Criteria to match model instances',
|
||||
},
|
||||
{arg: 'options', type: 'object', http: 'optionsFromRequest'},
|
||||
|
@ -863,18 +934,18 @@ module.exports = function(registry) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Enabled deeply-nested queries of related models via REST API.
|
||||
*
|
||||
* @param {String} relationName Name of the nested relation.
|
||||
* @options {Object} [options] It is optional. See below.
|
||||
* @param {String} pathName The HTTP path (relative to the model) at which your remote method is exposed.
|
||||
* @param {String} filterMethod The filter name.
|
||||
* @param {String} paramName The argument name that the remote method accepts.
|
||||
* @param {String} getterName The getter name.
|
||||
* @param {Boolean} hooks Whether to inherit before/after hooks.
|
||||
* @callback {Function} filterCallback The Optional filter function.
|
||||
* @param {Object} SharedMethod object. See [here](https://apidocs.strongloop.com/strong-remoting/#sharedmethod).
|
||||
* @param {Object} RelationDefinition object which includes relation `type`, `ModelConstructor` of `modelFrom`, `modelTo`, `keyFrom`, `keyTo` and more relation definitions.
|
||||
* Enabled deeply-nested queries of related models via REST API.
|
||||
*
|
||||
* @param {String} relationName Name of the nested relation.
|
||||
* @options {Object} [options] It is optional. See below.
|
||||
* @param {String} pathName The HTTP path (relative to the model) at which your remote method is exposed.
|
||||
* @param {String} filterMethod The filter name.
|
||||
* @param {String} paramName The argument name that the remote method accepts.
|
||||
* @param {String} getterName The getter name.
|
||||
* @param {Boolean} hooks Whether to inherit before/after hooks.
|
||||
* @callback {Function} filterCallback The Optional filter function.
|
||||
* @param {Object} SharedMethod object. See [here](https://apidocs.strongloop.com/strong-remoting/#sharedmethod).
|
||||
* @param {Object} RelationDefinition object which includes relation `type`, `ModelConstructor` of `modelFrom`, `modelTo`, `keyFrom`, `keyTo` and more relation definitions.
|
||||
*/
|
||||
|
||||
Model.nestRemoting = function(relationName, options, filterCallback) {
|
||||
|
@ -895,7 +966,8 @@ module.exports = function(registry) {
|
|||
const sharedToClass = relation.modelTo.sharedClass;
|
||||
const toModelName = relation.modelTo.modelName;
|
||||
|
||||
const pathName = options.pathName || relation.options.path || relationName;
|
||||
const pathName =
|
||||
options.pathName || relation.options.path || relationName;
|
||||
const paramName = options.paramName || 'nk';
|
||||
|
||||
const http = [].concat(sharedToClass.http || [])[0];
|
||||
|
@ -905,7 +977,9 @@ module.exports = function(registry) {
|
|||
httpPath = pathName + '/:' + paramName;
|
||||
acceptArgs = [
|
||||
{
|
||||
arg: paramName, type: 'any', http: {source: 'path'},
|
||||
arg: paramName,
|
||||
type: 'any',
|
||||
http: {source: 'path'},
|
||||
description: g.f('Foreign key for %s.', relation.name),
|
||||
required: true,
|
||||
},
|
||||
|
@ -921,18 +995,21 @@ module.exports = function(registry) {
|
|||
|
||||
// A method should return the method name to use, if it is to be
|
||||
// included as a nested method - a falsy return value will skip.
|
||||
const filter = filterCallback || options.filterMethod || function(method, relation) {
|
||||
const matches = method.name.match(regExp);
|
||||
if (matches) {
|
||||
return '__' + matches[1] + '__' + relation.name + '__' + matches[2];
|
||||
}
|
||||
};
|
||||
const filter =
|
||||
filterCallback ||
|
||||
options.filterMethod ||
|
||||
function(method, relation) {
|
||||
const matches = method.name.match(regExp);
|
||||
if (matches) {
|
||||
return '__' + matches[1] + '__' + relation.name + '__' + matches[2];
|
||||
}
|
||||
};
|
||||
|
||||
sharedToClass.methods().forEach(function(method) {
|
||||
let methodName;
|
||||
if (!method.isStatic && (methodName = filter(method, relation))) {
|
||||
const prefix = relation.multiple ? '__findById__' : '__get__';
|
||||
const getterName = options.getterName || (prefix + relationName);
|
||||
const getterName = options.getterName || prefix + relationName;
|
||||
|
||||
const getterFn = relation.modelFrom.prototype[getterName];
|
||||
if (typeof getterFn !== 'function') {
|
||||
|
@ -966,46 +1043,57 @@ module.exports = function(registry) {
|
|||
const lastArg = opts.accepts[opts.accepts.length - 1] || {};
|
||||
const hasOptionsFromContext =
|
||||
(lastArg.arg || lastArg.name) === 'options' &&
|
||||
lastArg.type === 'object' && lastArg.http;
|
||||
lastArg.type === 'object' &&
|
||||
lastArg.http;
|
||||
|
||||
if (relation.multiple) {
|
||||
sharedClass.defineMethod(methodName, opts, function(fkId) {
|
||||
const args = Array.prototype.slice.call(arguments, 1);
|
||||
const cb = args[args.length - 1];
|
||||
const contextOptions =
|
||||
hasOptionsFromContext && args[args.length - 2] || {};
|
||||
this[getterName](fkId, contextOptions, function(err, inst) {
|
||||
if (err) return cb(err);
|
||||
if (inst instanceof relation.modelTo) {
|
||||
try {
|
||||
nestedFn.apply(inst, args);
|
||||
} catch (err) {
|
||||
return cb(err);
|
||||
sharedClass.defineMethod(
|
||||
methodName,
|
||||
opts,
|
||||
function(fkId) {
|
||||
const args = Array.prototype.slice.call(arguments, 1);
|
||||
const cb = args[args.length - 1];
|
||||
const contextOptions =
|
||||
(hasOptionsFromContext && args[args.length - 2]) || {};
|
||||
this[getterName](fkId, contextOptions, function(err, inst) {
|
||||
if (err) return cb(err);
|
||||
if (inst instanceof relation.modelTo) {
|
||||
try {
|
||||
nestedFn.apply(inst, args);
|
||||
} catch (err) {
|
||||
return cb(err);
|
||||
}
|
||||
} else {
|
||||
cb(err, null);
|
||||
}
|
||||
} else {
|
||||
cb(err, null);
|
||||
}
|
||||
});
|
||||
}, method.isStatic);
|
||||
});
|
||||
},
|
||||
method.isStatic,
|
||||
);
|
||||
} else {
|
||||
sharedClass.defineMethod(methodName, opts, function() {
|
||||
const args = Array.prototype.slice.call(arguments);
|
||||
const cb = args[args.length - 1];
|
||||
const contextOptions =
|
||||
hasOptionsFromContext && args[args.length - 2] || {};
|
||||
this[getterName](contextOptions, function(err, inst) {
|
||||
if (err) return cb(err);
|
||||
if (inst instanceof relation.modelTo) {
|
||||
try {
|
||||
nestedFn.apply(inst, args);
|
||||
} catch (err) {
|
||||
return cb(err);
|
||||
sharedClass.defineMethod(
|
||||
methodName,
|
||||
opts,
|
||||
function() {
|
||||
const args = Array.prototype.slice.call(arguments);
|
||||
const cb = args[args.length - 1];
|
||||
const contextOptions =
|
||||
(hasOptionsFromContext && args[args.length - 2]) || {};
|
||||
this[getterName](contextOptions, function(err, inst) {
|
||||
if (err) return cb(err);
|
||||
if (inst instanceof relation.modelTo) {
|
||||
try {
|
||||
nestedFn.apply(inst, args);
|
||||
} catch (err) {
|
||||
return cb(err);
|
||||
}
|
||||
} else {
|
||||
cb(err, null);
|
||||
}
|
||||
} else {
|
||||
cb(err, null);
|
||||
}
|
||||
});
|
||||
}, method.isStatic);
|
||||
});
|
||||
},
|
||||
method.isStatic,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1025,9 +1113,15 @@ module.exports = function(registry) {
|
|||
sharedClass.methods().forEach(function(method) {
|
||||
const delegateTo = method.rest && method.rest.delegateTo;
|
||||
if (delegateTo && delegateTo.ctor == relation.modelTo) {
|
||||
const before = method.isStatic ? beforeListeners : beforeListeners['prototype'];
|
||||
const after = method.isStatic ? afterListeners : afterListeners['prototype'];
|
||||
const m = method.isStatic ? method.name : 'prototype.' + method.name;
|
||||
const before = method.isStatic ?
|
||||
beforeListeners :
|
||||
beforeListeners['prototype'];
|
||||
const after = method.isStatic ?
|
||||
afterListeners :
|
||||
afterListeners['prototype'];
|
||||
const m = method.isStatic ?
|
||||
method.name :
|
||||
'prototype.' + method.name;
|
||||
if (before && before[delegateTo.name]) {
|
||||
self.beforeRemote(m, function(ctx, result, next) {
|
||||
before[delegateTo.name]._listeners.call(null, ctx, next);
|
||||
|
@ -1042,7 +1136,11 @@ module.exports = function(registry) {
|
|||
});
|
||||
});
|
||||
} else {
|
||||
const msg = g.f('Relation `%s` does not exist for model `%s`', relationName, this.modelName);
|
||||
const msg = g.f(
|
||||
'Relation `%s` does not exist for model `%s`',
|
||||
relationName,
|
||||
this.modelName,
|
||||
);
|
||||
throw new Error(msg);
|
||||
}
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue