For an Apollo GraphQL Server custom data source, what's the best way to add a default where clause to every database query e.g.
where isDeleted = false
Using Apollo GraphQL Server, I have created a custom data source. The data source simply gets data from a database.
class CustomDataSource extends DataSource {
I've extended CustomDataSource so that project specific details can be added to it. i.e. CustomDataSource should be vanilla and re-usable across projects while MyProjectDataSource can contain project specific business rules.
class MyProjectDataSource extends CustomDataSource {
My GraphQL queries accept a filter parameter and CustomDataSource applies the filter to the database query.
type Query {
users(filter: JSON): [User]
}
My customDataSource is top heavy so does contain joins to return all query data.
Implementation Ideas
- MyProjectDataSource to change/override filter argument and then call CustomDataSource. Changing the query argument is straight forward but it's unclear if it's possible (or advisable) to change child field arguments. I'm using npm module graphql-parse-resolve-info for field look ahead.
async get(args, info) {
args.filter = 'where isDeleted = false'
return super.get(args, info);
}
MyProjectDataSource to override CustomDataSource functions. Con: seems overly complicated. Maybe exposing a "getFilter" function that could be overwritten could work but overriding functions feels like a sledge hammer approach.
Add a new defaultFilter parameter. Con: we don't want to expose this parameter to the app.
Create a defaultFilter directive. Con: Complicates schema. Needs to be manually added across entire schema. Unclear how to implement in MyProjectDataSource and has the same implementation cons as 2 above.
Use NodeJS eventEmitter to allow CustomDataSource to override filter argument. Con: Must bake in hooks to CustomDataSource for all project specific rules.
// CustomDataSource to emit event (and pass filter argument).
eventEmitter.emit('filter', ...
// MyDataSource to listen for event (and override filter argument).
eventEmitter.on('filter', ...
- Create a custom filter data type (instead of being of type JSON). Maybe this filter class could expose a defaultFilter property. Con: Feels like a complex road for adding a simple requirement.