graphql-compose / graphql-compose/graphql-compose-mongoose
Problem with mongooseResolvers generics
- Dominant language
- TypeScript
- Stars
- 706
- Forks
- 98
- PR merge metrics
- No merged PRs in 30d
Description
Hi, I am working on custom guards around resolvers including `findOne, findMany, etc.` I have hit a couple of problems:
1. The type of the arguments (`TArgs`) aren't exported, and so I cannot enforce consistent typing (for args) on the guarding resolver.
2. The `findMany` resolver declares its type as `Resolver`. This is inconsistent with the return value (the resolver returns `TDoc[]`, not `TDoc`), and so type enforcement breaks again.
For context, here is my Guard class:
```ts
export type GuardType = 'ingress' | 'egress'
export interface GuardInput {
context: TContext
args: TArgs
data?: TReturn
}
export interface GuardOutput {
args?: TArgs
data?: TReturn | false // set to false to remove all data
}
export abstract class Guard {
constructor(
public type: GuardType
) { }
abstract check(input: GuardInput): Promise | void>
}
export function guardResolver(
resolver: Resolver,
...guards: Guard[]
): Resolver {
const guardedResolver = (>schemaComposer).createResolver({
name: resolver.name,
type: resolver.getType(),
args: resolver.getArgs(),
resolve: async params => {
for (const guard of guards.filter(guard => guard.type == 'ingress')) {
const result = await guard.check({
args: params.args,
context: params.context
})
if (!result) continue
if (result.args) params.args = result.args
}
let data: TReturn | undefined = await resolver.resolve(params)
for (const guard of guards.filter(guard => guard.type == 'egress')) {
const result = await guard.check({
args: params.args,
context: params.context,
data
})
if (!result) continue
if (result.args) params.args = result.args
if (result.data !== null) { // data is being mutated
if (result.data === false) data = undefined
else data = result.data
}
}
return data
}
})
return guardedResolver
}
```
... and here is an example of how I use it:
```ts
export const chatQueries: ObjectTypeComposerFieldConfigMapDefinition = {
chatById: guardResolver(ChatTC.mongooseResolvers.findById(), new IsOwnChatGuard()),
chatMany: guardResolver(ChatTC.mongooseResolvers.findMany(), new ContainsOnlyOwnChatsGuard())
}
```
In the above example, at the moment, TS will raise an error for `ContainsOnlyOwnChatsGuard` because it expects `IChat[]` whereas `findMany()` declares that it will return `IChat` (despite the fact that it returns `IChat[]`). `console.log` of the output is below:
```bash
[
{ _id: 123456789, name: 'Chat' },
{ _id: 234567890, name: 'Chat' }
]
POST /graphql 200 147.473 ms - 964
```
I don't know the extent to which these problems exist in the library, any help is appreciated.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.