Open charpeni opened 1 year ago
Here's the implementation: https://github.com/dotansimha/graphql-code-generator/pull/9380.
Our team also has the same pain points in our incremental adoption as well.
For others who may need a solution, we ended up generating both masked (src/gql
) and fragmentMasking: false
(types src/gql/unmasked
), and then wrote a couple of helpers to utilize them:
In src/gql/full
import { ResultOf } from '@graphql-typed-document-node/core'
import type { graphql as graphqlUnmasked } from 'gql/unmasked'
import type * as UnmaskedNamespace from 'gql/unmasked/graphql'
import { graphql as graphqlMasked } from './gql'
export const graphql = graphqlMasked as typeof graphqlUnmasked
type Unmasked = typeof UnmaskedNamespace
type GraphqlNodeName = {
[Key in keyof Unmasked as Key]: (
Key extends `${infer FragmentName}FragmentDoc` ? FragmentName :
Key extends `${infer DocumentName}Document` ? DocumentName :
never
)
}[keyof Unmasked]
export type FullResultOf<
Name extends GraphqlNodeName,
FragmentName = `${Name}FragmentDoc`,
DocumentName = `${Name}Document`
> = (
FragmentName extends keyof Unmasked ? ResultOf<Unmasked[FragmentName]> :
DocumentName extends keyof Unmasked ? ResultOf<Unmasked[DocumentName]> :
never
)
Then to fetch the types you can either:
Use the normal types, just importing graphql
from gql/full
import { graphql } from 'gql/full'
import { ResultOf } from '@graphql-typed-document-node/core'
const Fragment = graphql(`
fragment TestFragment_UserFragment on User {
id
...NameCard_UserFragment
}
`)
type FullUser = ResultOf<typeof Fragment>
Or you can look up the type via its name
import { FullResultOf } from 'gql/full'
const Fragment = graphql(`
fragment TestFragment_UserFragment on User {
id
...NameCard_UserFragment
}
`)
type FullUser = FullResultOf<'TestFragment_UserFragment'>
I've built an implementation that takes @charpeni's implementation further, and I've tested for:
The implementation can be found here.
Is your feature request related to a problem? Please describe.
I recently migrated a project to
client-preset
(fromgql-tag-operations-preset
) and would like to turn on Fragment Masking for it. Unfortunately, because of existing fragments that are not using Fragment Masking, we already have a thousand errors to handle to be able to.When you enable Fragment Masking, all fragments, and operations are automatically masked, even though not all fragments or operations use Fragment Masking.
I would like the ability to unmask fragments recursively to support an incremental adoption of Fragment Masking.
Also related to:
Nested Fragment:
<UserAvatar>
Fragment:
<UserCard>
Query:
<ExampleComponent>
Describe the solution you'd like
We could expose the following utility type:
UnmaskResultOf<TypedDocumentNode>
.This would check if whether we're inside an operation or directly within a fragment and then recursively flatten fragments by resolving
$fragmentRefs
and merging them to the root fragment.See the implementation on TypeScript Playground: Link.
Describe alternatives you've considered
No response
Is your feature request related to a problem? Please describe.
No response