-
Notifications
You must be signed in to change notification settings - Fork 118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
custom crud resolvers #550
Comments
That's great! And similarly, it might be also useful to add middleware like t.crud.createOneUser({
alias: 'signUp',
authorize(parent, args, ctx, info) {
// ...
},
}) or maybe a general middleware to add logics both before and after the default resolver: t.crud.createOneUser({
alias: 'signUp',
async middleware(next, parent, args, ctx, info) {
// do something
await next()
// do something else and return
},
}) |
Hey @beeplin we'd probably treat that as a separate feature for consideration. @BjoernRave could you share how your use-case is resolved by this feature? Based on what you said in Slack, we're not sure it does. |
Actually, I quite love the idea of a framework named I think in most situations, the CRUD is still just a CRUD, you can attach your logic The argument is:
The API looks like this, instead of exposing a resolver, we add two properties mutationType({
definition(t) {
t.crud.createOneUser({
alias: 'signUp'
before: [isAdminUser],
after:[removePassword]
})
},
}) The
|
So, resolver middleware is already in flight with the new nexus plugins system. The degree to which it isn't enough to satisfy resolver auth requirements is not clear to me yet. I'm not discounting the ideas here. But I'd like to see very clear alignment with the underlying nexus middleware system. |
I would love to be able to define custom resolvers too. In my case, when I call |
Another use case for having a custom resolve function is to be able to check if a mutation caller has a right to |
Is there a workaround today to doing AuthN/Z with |
I have a use case for custom resolvers. What I especially would also need then is a feature to extend the input arguments. I'm using Postgres with PostGIS to implement a search which finds job offers in the near area specified by coordinates (latitude, longitude) and a radius. I now implemented a very dirty hack to accomplish my area search. The explanation of my hackExcerpt from my schema.prisma:
My queryType for Query is implemented like this: export const Query = queryType({
definition(t) {
// ...
t.crud.jobOffers({
filtering: {
// many filtering fields
},
pagination: true,
})
// ...
},
}) To have a way to pass additional arguments in my jobOffers query I added the field const JobOfferInAreaCenterInput = inputObjectType({
name: 'JobOfferInAreaCenterInput',
description: 'Defines the center of the area search',
definition(t): void {
t.int('radius', {
description: 'Radius in meters',
required: true,
})
t.float('lat', {
description: 'Latitude',
required: true,
})
t.float('lng', {
description: 'Longitude',
required: true,
})
}
})
export const JobOffer = objectType({
name: 'JobOffer',
definition(t) {
// many other fields
t.field('inArea', {
type: 'Boolean',
description: 'Dummy type for area search.\nThis is used ONLY for jobOffers query.\nYou MUST pass the center argument as a variable named $areaSearchCenter\n\nThis is a dirty hack.',
args: {
center: JobOfferInAreaCenterInput,
},
resolve: () => true
})
},
}) Now I wrote a nexus plugin (used in Nexus.makeSchema) which intercepts the jobOffers resolver: import { plugin } from 'nexus'
interface Area {
radius: number
lat: number
lng: number
}
export const jobOffersAreaSearchExtension = plugin({
name: 'JobOffersAreaSearchExtension',
onCreateFieldResolver(config) {
if (config.fieldConfig.name !== 'jobOffers') {
return
}
return async (root, args, ctx, info, next) => {
const areaSearchCenter: Area | undefined = info.variableValues.areaSearchCenter
if (!areaSearchCenter) {
return next(root, args, ctx, info)
}
// TODO: pg can be replaced with prisma client raw queries when this issue is resolved:
// https://github.com/prisma/migrate/issues/357
const jobLocationsWithinArea = await ctx.pg.query(`
SELECT
*
FROM
prisma2_project."JobLocation"
WHERE
ST_DWithin(ST_MakePoint(lng, lat)::geography, ST_MakePoint($1, $2)::geography, $3)
`, [areaSearchCenter.lng, areaSearchCenter.lat, areaSearchCenter.radius])
let jobLocationsWithinAreaIds: string[] = jobLocationsWithinArea.rows.map((location: any) => location.id)
// locations are not specified as filterable for t.crud.jobOffers
// if it was specified, we would have to merge the args
args = {
...args,
where: {
...args.where,
locations: {
some: {
AND: {
id: {
in: jobLocationsWithinAreaIds
}
}
},
}
}
}
return next(root, args, ctx, info)
}
},
}) This makes it possible to query my jobOffers within a specified area: query GetAllJobOffers($areaSearchCenter: JobOfferInAreaCenterInput) {
jobOffers {
inArea(center: $areaSearchCenter)
id
locations {
id
zip
city
}
# many other fields
}
}
# With area search:
# {
# "areaSearchCenter": {
# "radius": 5000,
# "lng": 9.1919123,
# "lat": 48.786453
# }
# }
#
# Without area search:
# {
# "areaSearchCenter": null
# }
#
# Alternatively "areaSearchCenter" can not be passed at all |
Closed by #674 |
Idea originally (?) raised here #381 (comment). It has since been validated by no "wait we didn't think of X" moments, and multiple thumbs up from different users (both in GH and slack).
The text was updated successfully, but these errors were encountered: