-
-
Save KidkArolis/98c5305dfe3c0f259d34cc1061eeb522 to your computer and use it in GitHub Desktop.
/* | |
Install this hook in app.hooks.js | |
module.exports = app => { | |
app.hooks({ | |
before: { | |
all: [ | |
addParamsForward() | |
] | |
} | |
}) | |
} | |
Then use whenever you want to forward params, e.g. in a hook: | |
const { app, params } = context | |
app.service('another-service').find({ query: { id: 'x' }, ...params.forward() }) | |
app.service('another-service').get(id, params.forward()) | |
app.service('another-service').patch(id, {smth: 'x' }, params.forward()) | |
*/ | |
const { has } = require('lodash') | |
const paramsSeen = new WeakSet() | |
module.exports = function addParamsForward() { | |
return context => { | |
if (paramsSeen.has(context.params)) { | |
throw new Error( | |
`Params should never be shared across services, always use params.forward(). Fix calls to ${context.path}#${context.method}`, | |
) | |
} | |
paramsSeen.add(context.params) | |
context.params.forward = ({ only, omit = [] } = {}) => { | |
const { params } = context | |
const forwardedParams = { | |
caller: { | |
path: context.path, | |
method: context.method, | |
type: context.type, | |
}, | |
requestId: context.params.requestId, | |
forwarded: true, | |
} | |
;( | |
only || [ | |
'authenticated', | |
'user', | |
'transaction', | |
'skipEvents', | |
'permissions', | |
] | |
).forEach(param => { | |
if (has(params, param) && !omit.includes(param)) { | |
forwardedParams[param] = params[param] | |
} | |
}) | |
if (forwardedParams.authenticated) { | |
forwardedParams.authentication = params.authentication | |
} | |
return forwardedParams | |
} | |
} | |
} |
ah! it works, but still can't figure out why using spread ...params.forward()
will trigger the non-callable @@iterator
error. Other than that, it looks good now.
If you know what's causing the error, do let me know.
Thanks!
Because you can only spread properties in an object:
let a = { x: 'y' }
let b = { ...a }
Or you can spread arrays as arguments:
let a = ['x', 'y', 'z']
example(...a)
You can't spread an object as arguments:
// not valid!!
// throws non-callable @@iterator / is not iterable
let a = { x: 'y' }
example(...a)
In Feathers, params
is an object, params.forward() is also an object, so:
// invalid
service.get(1, ...params)
service.get(1, ...params.forward())
// valid
service.get(1, params)
service.get(1, params.forward())
service.get(1, { ...params })
service.get(1, { ...params.forward() })
// invalid
service.find(...params)
service.find(...params.forward())
// valid
service.find({ query: { email: 'x', }, ...params })
service.find({ query: { email: 'x', }, ...params.forward() })
That's it.
Thank you so much.
Hello @KidkArolis,
I noticed that in the forwardedParams.caller.type
is always before
, is that intended? I would imagine that it should be whoever called the forward()
?
// I have a hook x at the after-remove hook of service y
// now I call to remove
app.service('y').remove(id)
// within hook x, it calls service z (note hook x is in after-remove hook of service y)
app.service('z').remove(anotherId, params.forward());
So when I logs out the forwardedParams
before the return
in addParamsForward()
, the caller.type
is before
.
@bwgjoseph you're right, it could be fixed by readding addParamsForward() hook in after all, so that it uses updated the closed over context when computing forwardedParams.
@bwgjoseph, this is a convention I enforce in my Feathers applications - to never share the same params object between different service calls. This is because params object might get mutated in hooks affecting other services unexpectedly.
In your case, simple to fix, call params.forward() for each call, e.g.: