Skip to content

Commit

Permalink
fix(typescript): Fragment masking $fragmentName and ` $fragmentRef…
Browse files Browse the repository at this point in the history
…s` are optional (#8498)
  • Loading branch information
charlypoly committed Oct 18, 2022
1 parent f089e48 commit a46b8d9
Show file tree
Hide file tree
Showing 13 changed files with 55 additions and 46 deletions.
7 changes: 7 additions & 0 deletions .changeset/dry-pianos-grab.md
@@ -0,0 +1,7 @@
---
'@graphql-codegen/visitor-plugin-common': minor
'@graphql-codegen/client-preset': minor
'@graphql-codegen/gql-tag-operations-preset': minor
---

Fragment masking ` $fragmentName` and ` $fragmentRefs` are optionals
Expand Up @@ -4,9 +4,9 @@ export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocume
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
Expand Down
8 changes: 4 additions & 4 deletions dev-test/gql-tag-operations-masking-star-wars/gql/graphql.ts
Expand Up @@ -247,17 +247,17 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{
export type HeroDetailsWithFragmentQuery = {
__typename?: 'Query';
hero?:
| ({ __typename?: 'Droid' } & { ' $fragmentRefs': { HeroDetails_Droid_Fragment: HeroDetails_Droid_Fragment } })
| ({ __typename?: 'Human' } & { ' $fragmentRefs': { HeroDetails_Human_Fragment: HeroDetails_Human_Fragment } })
| ({ __typename?: 'Droid' } & { ' $fragmentRefs'?: { HeroDetails_Droid_Fragment: HeroDetails_Droid_Fragment } })
| ({ __typename?: 'Human' } & { ' $fragmentRefs'?: { HeroDetails_Human_Fragment: HeroDetails_Human_Fragment } })
| null;
};

type HeroDetails_Droid_Fragment = { __typename: 'Droid'; primaryFunction?: string | null; name: string } & {
' $fragmentName': 'HeroDetails_Droid_Fragment';
' $fragmentName'?: 'HeroDetails_Droid_Fragment';
};

type HeroDetails_Human_Fragment = { __typename: 'Human'; height?: number | null; name: string } & {
' $fragmentName': 'HeroDetails_Human_Fragment';
' $fragmentName'?: 'HeroDetails_Human_Fragment';
};

export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment;
Expand Down
4 changes: 2 additions & 2 deletions dev-test/gql-tag-operations-masking/gql/fragment-masking.ts
Expand Up @@ -4,9 +4,9 @@ export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocume
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
Expand Down
12 changes: 6 additions & 6 deletions dev-test/gql-tag-operations-masking/gql/graphql.ts
Expand Up @@ -106,26 +106,26 @@ export type User = {
};

export type TweetFragmentFragment = ({ __typename?: 'Tweet'; id: string; body: string } & {
' $fragmentRefs': { TweetAuthorFragmentFragment: TweetAuthorFragmentFragment };
}) & { ' $fragmentName': 'TweetFragmentFragment' };
' $fragmentRefs'?: { TweetAuthorFragmentFragment: TweetAuthorFragmentFragment };
}) & { ' $fragmentName'?: 'TweetFragmentFragment' };

export type TweetAuthorFragmentFragment = {
__typename?: 'Tweet';
id: string;
author: { __typename?: 'User'; id: string; username?: string | null };
} & { ' $fragmentName': 'TweetAuthorFragmentFragment' };
} & { ' $fragmentName'?: 'TweetAuthorFragmentFragment' };

export type TweetsFragmentFragment = {
__typename?: 'Query';
Tweets?: Array<
{ __typename?: 'Tweet'; id: string } & { ' $fragmentRefs': { TweetFragmentFragment: TweetFragmentFragment } }
{ __typename?: 'Tweet'; id: string } & { ' $fragmentRefs'?: { TweetFragmentFragment: TweetFragmentFragment } }
> | null;
} & { ' $fragmentName': 'TweetsFragmentFragment' };
} & { ' $fragmentName'?: 'TweetsFragmentFragment' };

export type TweetAppQueryQueryVariables = Exact<{ [key: string]: never }>;

export type TweetAppQueryQuery = { __typename?: 'Query' } & {
' $fragmentRefs': { TweetsFragmentFragment: TweetsFragmentFragment };
' $fragmentRefs'?: { TweetsFragmentFragment: TweetsFragmentFragment };
};

export const TweetAuthorFragmentFragmentDoc = {
Expand Down
4 changes: 2 additions & 2 deletions dev-test/gql-tag-operations/graphql/fragment-masking.ts
Expand Up @@ -4,9 +4,9 @@ export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocume
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
Expand Down
4 changes: 2 additions & 2 deletions dev-test/gql-tag-operations/graphql/graphql.ts
Expand Up @@ -110,14 +110,14 @@ export type FooQueryVariables = Exact<{ [key: string]: never }>;
export type FooQuery = { __typename?: 'Query'; Tweets?: Array<{ __typename?: 'Tweet'; id: string } | null> | null };

export type LelFragment = { __typename?: 'Tweet'; id: string; body?: string | null } & {
' $fragmentName': 'LelFragment';
' $fragmentName'?: 'LelFragment';
};

export type BarQueryVariables = Exact<{ [key: string]: never }>;

export type BarQuery = {
__typename?: 'Query';
Tweets?: Array<({ __typename?: 'Tweet' } & { ' $fragmentRefs': { LelFragment: LelFragment } }) | null> | null;
Tweets?: Array<({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null> | null;
};

export const LelFragmentDoc = {
Expand Down
Expand Up @@ -586,7 +586,7 @@ export class SelectionSetToObject<Config extends ParsedDocumentsConfig = ParsedD
if (this._config.inlineFragmentTypes === 'combine') {
fields.push(...fragmentsSpreadUsages);
} else if (this._config.inlineFragmentTypes === 'mask') {
fields.push(`{ ' $fragmentRefs': { ${fragmentsSpreadUsages.map(name => `'${name}': ${name}`).join(`;`)} } }`);
fields.push(`{ ' $fragmentRefs'?: { ${fragmentsSpreadUsages.map(name => `'${name}': ${name}`).join(`;`)} } }`);
}
}

Expand Down Expand Up @@ -683,7 +683,7 @@ export class SelectionSetToObject<Config extends ParsedDocumentsConfig = ParsedD

const fragmentTypeName = this.buildFragmentTypeName(fragmentName, fragmentSuffix);
const fragmentMaskPartial =
this._config.inlineFragmentTypes === 'mask' ? ` & { ' $fragmentName': '${fragmentTypeName}' }` : '';
this._config.inlineFragmentTypes === 'mask' ? ` & { ' $fragmentName'?: '${fragmentTypeName}' }` : '';

if (subTypes.length === 1) {
return new DeclarationBlock(declarationBlockConfig)
Expand All @@ -701,7 +701,9 @@ export class SelectionSetToObject<Config extends ParsedDocumentsConfig = ParsedD
.asKind('type')
.withName(t.name)
.withContent(
`${t.content}${this._config.inlineFragmentTypes === 'mask' ? ` & { ' $fragmentName': '${t.name}' }` : ''}`
`${t.content}${
this._config.inlineFragmentTypes === 'mask' ? ` & { ' $fragmentName'?: '${t.name}' }` : ''
}`
).string
),
new DeclarationBlock(declarationBlockConfig)
Expand Down
24 changes: 12 additions & 12 deletions packages/plugins/typescript/operations/tests/ts-documents.spec.ts
Expand Up @@ -2441,15 +2441,15 @@ describe('TypeScript Operations Plugin', () => {
export type TestQuery = { __typename?: 'Query', notifications: Array<(
{ __typename?: 'TextNotification' }
& { ' $fragmentRefs': { 'N_TextNotification_Fragment': N_TextNotification_Fragment } }
& { ' $fragmentRefs'?: { 'N_TextNotification_Fragment': N_TextNotification_Fragment } }
) | (
{ __typename?: 'ImageNotification' }
& { ' $fragmentRefs': { 'N_ImageNotification_Fragment': N_ImageNotification_Fragment } }
& { ' $fragmentRefs'?: { 'N_ImageNotification_Fragment': N_ImageNotification_Fragment } }
)> };
type N_TextNotification_Fragment = { __typename?: 'TextNotification', id: string } & { ' $fragmentName': 'N_TextNotification_Fragment' };
type N_TextNotification_Fragment = { __typename?: 'TextNotification', id: string } & { ' $fragmentName'?: 'N_TextNotification_Fragment' };
type N_ImageNotification_Fragment = { __typename?: 'ImageNotification', id: string } & { ' $fragmentName': 'N_ImageNotification_Fragment' };
type N_ImageNotification_Fragment = { __typename?: 'ImageNotification', id: string } & { ' $fragmentName'?: 'N_ImageNotification_Fragment' };
export type NFragment = N_TextNotification_Fragment | N_ImageNotification_Fragment;
`);
Expand Down Expand Up @@ -5862,20 +5862,20 @@ function test(q: GetEntityBrandDataQuery): void {
export type GetPeopleQuery = { __typename?: 'Query', people: (
{ __typename?: 'Character' }
& { ' $fragmentRefs': { 'PeopleInfo_Character_Fragment': PeopleInfo_Character_Fragment } }
& { ' $fragmentRefs'?: { 'PeopleInfo_Character_Fragment': PeopleInfo_Character_Fragment } }
) | (
{ __typename?: 'Jedi' }
& { ' $fragmentRefs': { 'PeopleInfo_Jedi_Fragment': PeopleInfo_Jedi_Fragment } }
& { ' $fragmentRefs'?: { 'PeopleInfo_Jedi_Fragment': PeopleInfo_Jedi_Fragment } }
) | (
{ __typename?: 'Droid' }
& { ' $fragmentRefs': { 'PeopleInfo_Droid_Fragment': PeopleInfo_Droid_Fragment } }
& { ' $fragmentRefs'?: { 'PeopleInfo_Droid_Fragment': PeopleInfo_Droid_Fragment } }
) };
type PeopleInfo_Character_Fragment = { __typename?: 'Character', name?: string | null } & { ' $fragmentName': 'PeopleInfo_Character_Fragment' };
type PeopleInfo_Character_Fragment = { __typename?: 'Character', name?: string | null } & { ' $fragmentName'?: 'PeopleInfo_Character_Fragment' };
type PeopleInfo_Jedi_Fragment = { __typename?: 'Jedi', side?: string | null } & { ' $fragmentName': 'PeopleInfo_Jedi_Fragment' };
type PeopleInfo_Jedi_Fragment = { __typename?: 'Jedi', side?: string | null } & { ' $fragmentName'?: 'PeopleInfo_Jedi_Fragment' };
type PeopleInfo_Droid_Fragment = { __typename?: 'Droid', model?: string | null } & { ' $fragmentName': 'PeopleInfo_Droid_Fragment' };
type PeopleInfo_Droid_Fragment = { __typename?: 'Droid', model?: string | null } & { ' $fragmentName'?: 'PeopleInfo_Droid_Fragment' };
export type PeopleInfoFragment = PeopleInfo_Character_Fragment | PeopleInfo_Jedi_Fragment | PeopleInfo_Droid_Fragment;
"
Expand Down Expand Up @@ -6434,10 +6434,10 @@ function test(q: GetEntityBrandDataQuery): void {
export type Unnamed_1_Query = { __typename?: 'Query', me?: (
{ __typename?: 'User' }
& { ' $fragmentRefs': { 'UserFragmentFragment': UserFragmentFragment } }
& { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } }
) | null };
export type UserFragmentFragment = { __typename?: 'User', id: string } & { ' $fragmentName': 'UserFragmentFragment' };
export type UserFragmentFragment = { __typename?: 'User', id: string } & { ' $fragmentName'?: 'UserFragmentFragment' };
`);
});
});
Expand Down
4 changes: 2 additions & 2 deletions packages/presets/client/src/fragment-masking-plugin.ts
Expand Up @@ -5,9 +5,9 @@ export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocume
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;`;
Expand Down
6 changes: 3 additions & 3 deletions packages/presets/client/tests/client-preset.spec.ts
Expand Up @@ -245,7 +245,7 @@ export * from "./fragment-masking"`);
export type BQuery = { __typename?: 'Query', b?: string | null };
export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName': 'CFragment' };
export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' };
export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode<CFragment, unknown>;
export const ADocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode<AQuery, AQueryVariables>;
Expand Down Expand Up @@ -454,9 +454,9 @@ export * from "./fragment-masking"`);
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
Expand Down
Expand Up @@ -5,9 +5,9 @@ export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocume
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;`;
Expand Down
Expand Up @@ -379,9 +379,9 @@ describe('gql-tag-operations-preset', () => {
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
Expand Down Expand Up @@ -477,9 +477,9 @@ describe('gql-tag-operations-preset', () => {
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
Expand Down Expand Up @@ -665,9 +665,9 @@ describe('gql-tag-operations-preset', () => {
infer TType,
any
>
? TType extends { ' $fragmentName': infer TKey }
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs': { [key in TKey]: TType } }
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
Expand Down

0 comments on commit a46b8d9

Please sign in to comment.