-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Modify remoting metadata of data-access methods in PersistedModel and relation method in Model and add an "options" argument to "accepts" list.
- Loading branch information
Showing
6 changed files
with
607 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
'use strict'; | ||
var g = require('./globalize'); | ||
var assert = require('assert'); | ||
var debug = require('debug')('loopback:model'); | ||
var RemoteObjects = require('strong-remoting'); | ||
var SharedClass = require('strong-remoting').SharedClass; | ||
var extend = require('util')._extend; | ||
|
@@ -136,15 +137,29 @@ module.exports = function(registry) { | |
); | ||
|
||
// support remoting prototype methods | ||
ModelCtor.sharedCtor = function(data, id, fn) { | ||
ModelCtor.sharedCtor = function(data, id, options, fn) { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
bajtos
Author
Member
|
||
var ModelCtor = this; | ||
|
||
if (typeof data === 'function') { | ||
var isRemoteInvocationWithOptions = typeof data !== 'object' && | ||
typeof id === 'object' && | ||
typeof options === 'function'; | ||
if (isRemoteInvocationWithOptions) { | ||
// sharedCtor(id, options, fn) | ||
fn = options; | ||
options = id; | ||
id = data; | ||
data = null; | ||
} else if (typeof data === 'function') { | ||
// sharedCtor(fn) | ||
fn = data; | ||
data = null; | ||
id = null; | ||
options = null; | ||
} else if (typeof id === 'function') { | ||
// sharedCtor(data, fn) | ||
// sharedCtor(id, fn) | ||
fn = id; | ||
options = null; | ||
|
||
if (typeof data !== 'object') { | ||
id = data; | ||
|
@@ -161,7 +176,8 @@ module.exports = function(registry) { | |
} else if (data) { | ||
fn(null, new ModelCtor(data)); | ||
} else if (id) { | ||
ModelCtor.findById(id, function(err, model) { | ||
var filter = {}; | ||
ModelCtor.findById(id, filter, options, function(err, model) { | ||
if (err) { | ||
fn(err); | ||
} else if (model) { | ||
|
@@ -183,6 +199,7 @@ module.exports = function(registry) { | |
{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 = [ | ||
|
@@ -232,6 +249,14 @@ module.exports = function(registry) { | |
// resolve relation functions | ||
sharedClass.resolve(function resolver(define) { | ||
var relations = ModelCtor.relations || {}; | ||
var defineRaw = define; | ||
define = function(name, options, fn) { | ||
if (options.accepts) { | ||
options = extend({}, options); | ||
options.accepts = setupOptionsArgs(options.accepts); | ||
} | ||
defineRaw(name, options, fn); | ||
}; | ||
|
||
// get the relations | ||
for (var relationName in relations) { | ||
|
@@ -439,7 +464,7 @@ module.exports = function(registry) { | |
|
||
return accepts.map(function(arg) { | ||
if (arg.http && arg.http === 'optionsFromRequest') { | ||
// deep clone to preserve the input value | ||
// clone to preserve the input value | ||
arg = extend({}, arg); | ||
arg.http = createOptionsViaModelMethod; | ||
} | ||
|
@@ -454,6 +479,7 @@ module.exports = function(registry) { | |
return EMPTY_OPTIONS; | ||
if (typeof ModelCtor.createOptionsFromRemotingContext !== 'function') | ||
return EMPTY_OPTIONS; | ||
debug('createOptionsFromRemotingContext for %s', ctx.method.stringName); | ||
return ModelCtor.createOptionsFromRemotingContext(ctx); | ||
} | ||
|
||
|
@@ -494,7 +520,10 @@ module.exports = function(registry) { | |
define('__get__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'get', path: '/' + pathName}, | ||
accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}}, | ||
accepts: [ | ||
{arg: 'refresh', type: 'boolean', http: {source: 'query'}}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
accessType: 'READ', | ||
description: format('Fetches belongsTo relation %s.', relationName), | ||
returns: {arg: relationName, type: modelName, root: true}, | ||
|
@@ -519,7 +548,10 @@ module.exports = function(registry) { | |
define('__get__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'get', path: '/' + pathName}, | ||
accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}}, | ||
accepts: [ | ||
{arg: 'refresh', type: 'boolean', http: {source: 'query'}}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Fetches hasOne relation %s.', relationName), | ||
accessType: 'READ', | ||
returns: {arg: relationName, type: relation.modelTo.modelName, root: true}, | ||
|
@@ -529,7 +561,13 @@ module.exports = function(registry) { | |
define('__create__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'post', path: '/' + pathName}, | ||
accepts: {arg: 'data', type: 'object', model: toModelName, http: {source: 'body'}}, | ||
accepts: [ | ||
{ | ||
arg: 'data', type: 'object', model: toModelName, | ||
http: {source: 'body'}, | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Creates a new instance in %s of this model.', relationName), | ||
accessType: 'WRITE', | ||
returns: {arg: 'data', type: toModelName, root: true}, | ||
|
@@ -538,7 +576,13 @@ module.exports = function(registry) { | |
define('__update__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'put', path: '/' + pathName}, | ||
accepts: {arg: 'data', type: 'object', model: toModelName, http: {source: 'body'}}, | ||
accepts: [ | ||
{ | ||
arg: 'data', type: 'object', model: toModelName, | ||
http: {source: 'body'}, | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Update %s of this model.', relationName), | ||
accessType: 'WRITE', | ||
returns: {arg: 'data', type: toModelName, root: true}, | ||
|
@@ -547,6 +591,9 @@ module.exports = function(registry) { | |
define('__destroy__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'delete', path: '/' + pathName}, | ||
accepts: [ | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Deletes %s of this model.', relationName), | ||
accessType: 'WRITE', | ||
}); | ||
|
@@ -560,10 +607,15 @@ module.exports = function(registry) { | |
define('__findById__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'get', path: '/' + pathName + '/:fk'}, | ||
accepts: {arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}}, | ||
accepts: [ | ||
{ | ||
arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}, | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Find a related item by id for %s.', relationName), | ||
accessType: 'READ', | ||
returns: {arg: 'result', type: toModelName, root: true}, | ||
|
@@ -574,10 +626,15 @@ module.exports = function(registry) { | |
define('__destroyById__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'delete', path: '/' + pathName + '/:fk'}, | ||
accepts: {arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}}, | ||
accepts: [ | ||
{ | ||
arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}, | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Delete a related item by id for %s.', relationName), | ||
accessType: 'WRITE', | ||
returns: [], | ||
|
@@ -593,6 +650,7 @@ module.exports = function(registry) { | |
required: true, | ||
http: {source: 'path'}}, | ||
{arg: 'data', type: 'object', model: toModelName, http: {source: 'body'}}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Update a related item by id for %s.', relationName), | ||
accessType: 'WRITE', | ||
|
@@ -618,7 +676,10 @@ module.exports = function(registry) { | |
accepts: [{arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}}].concat(accepts), | ||
http: {source: 'path'}}, | ||
].concat(accepts).concat([ | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
]), | ||
description: format('Add a related item by id for %s.', relationName), | ||
accessType: 'WRITE', | ||
returns: {arg: relationName, type: modelThrough.modelName, root: true}, | ||
|
@@ -628,10 +689,15 @@ module.exports = function(registry) { | |
define('__unlink__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'delete', path: '/' + pathName + '/rel/:fk'}, | ||
accepts: {arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}}, | ||
accepts: [ | ||
{ | ||
arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}, | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Remove the %s relation to an item by id.', relationName), | ||
accessType: 'WRITE', | ||
returns: [], | ||
|
@@ -643,10 +709,15 @@ module.exports = function(registry) { | |
define('__exists__' + relationName, { | ||
isStatic: false, | ||
http: {verb: 'head', path: '/' + pathName + '/rel/:fk'}, | ||
accepts: {arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}}, | ||
accepts: [ | ||
{ | ||
arg: 'fk', type: 'any', | ||
description: format('Foreign key for %s', relationName), | ||
required: true, | ||
http: {source: 'path'}, | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Check the existence of %s relation to an item by id.', relationName), | ||
accessType: 'READ', | ||
returns: {arg: 'exists', type: 'boolean', root: true}, | ||
|
@@ -689,7 +760,10 @@ module.exports = function(registry) { | |
define('__get__' + scopeName, { | ||
isStatic: isStatic, | ||
http: {verb: 'get', path: '/' + pathName}, | ||
accepts: {arg: 'filter', type: 'object'}, | ||
accepts: [ | ||
{arg: 'filter', type: 'object'}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Queries %s of %s.', scopeName, this.modelName), | ||
accessType: 'READ', | ||
returns: {arg: scopeName, type: [toModelName], root: true}, | ||
|
@@ -698,13 +772,16 @@ module.exports = function(registry) { | |
define('__create__' + scopeName, { | ||
isStatic: isStatic, | ||
http: {verb: 'post', path: '/' + pathName}, | ||
accepts: { | ||
arg: 'data', | ||
type: 'object', | ||
allowArray: true, | ||
model: toModelName, | ||
http: {source: 'body'}, | ||
}, | ||
accepts: [ | ||
{ | ||
arg: 'data', | ||
type: 'object', | ||
allowArray: true, | ||
model: toModelName, | ||
http: {source: 'body'}, | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Creates a new instance in %s of this model.', scopeName), | ||
accessType: 'WRITE', | ||
returns: {arg: 'data', type: toModelName, root: true}, | ||
|
@@ -713,15 +790,30 @@ module.exports = function(registry) { | |
define('__delete__' + scopeName, { | ||
isStatic: isStatic, | ||
http: {verb: 'delete', path: '/' + pathName}, | ||
accepts: [ | ||
{ | ||
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; }, | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('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'}, | ||
accepts: [ | ||
{ | ||
arg: 'where', type: 'object', | ||
description: 'Criteria to match model instances', | ||
}, | ||
{arg: 'options', type: 'object', http: 'optionsFromRequest'}, | ||
], | ||
description: format('Counts %s of %s.', scopeName, this.modelName), | ||
accessType: 'READ', | ||
returns: {arg: 'count', type: 'number'}, | ||
|
Oops, something went wrong.
Hi @bajtos it seems that some Angular 2 and SDK for LoopBack 2 users are having issues with this.
But I'm totally sure this should work with LB2, it is supposed to? if so, I believe this may be an optional parameter, so if it is supposed to work with both LB2 and LB3 maybe the fix would be to set the options parameter to optional in typescript?
Thoughts?