Skip to content
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

Add TypedDocumentNode string alternative #9137

Merged
merged 35 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4a7b339
Add unit tests
beerose Mar 8, 2023
504367a
Add TypedDocumentNode string alternative
beerose Mar 8, 2023
c7105db
Temporarily use snapshot version of @graphql-typed-document-node/core
beerose Mar 9, 2023
13e48a9
chore(dependencies): updated changesets for modified dependencies
github-actions[bot] Mar 9, 2023
02ed2b3
Update fragment-masking.ts files
beerose Mar 9, 2023
2d5a4e7
Update fragment-masking in dev-test dir
beerose Mar 9, 2023
590b2e2
Update @graphql-typed-document-node/core version in examples
beerose Mar 9, 2023
8e4e93f
Merge branch 'master' into typed-document-string
beerose Mar 9, 2023
7a5d42d
Update test after latest implememntation changes
beerose Mar 9, 2023
3892ba2
Changeset
beerose Mar 10, 2023
ef28588
Modify existing example
beerose Mar 10, 2023
961251f
Update typescript-graphql-request example
beerose Mar 13, 2023
dbd2053
Merge branch 'master' into typed-document-string
beerose Mar 13, 2023
8005ea3
Add failing test for duplicated fragments
beerose Mar 13, 2023
2c6ee68
Inline fragments in string document mode
beerose Mar 13, 2023
7b073f3
Update example with fragment inlining
beerose Mar 13, 2023
db98f71
Support __meta__ with typed document string
beerose Mar 13, 2023
346e1e5
Add TypedDocumentString class to handle metadata
beerose Mar 14, 2023
4e732da
Fix import
beerose Mar 14, 2023
82b75f0
Remove unused import
beerose Mar 14, 2023
56170f6
Merge branch 'master' into typed-document-string
beerose Mar 14, 2023
e3120b3
Update @graphql-typed-document-node/core version
beerose Mar 14, 2023
8b5ad73
Merge branch 'master' into typed-document-string
beerose Mar 15, 2023
f960ccf
chore(dependencies): updated changesets for modified dependencies
github-actions[bot] Mar 15, 2023
ed34330
Update react-query example — use fetch insetad of http executor
beerose Mar 15, 2023
0283daf
Merge branch 'master' into typed-document-string
beerose Mar 15, 2023
cfd9380
Add docs
beerose Mar 15, 2023
a97276b
Update @graphql-typed-document-node/code version
beerose Mar 20, 2023
2e99784
chore(dependencies): updated changesets for modified dependencies
github-actions[bot] Mar 20, 2023
bdc1e7d
Add more info to the dosc
beerose Mar 20, 2023
e954bea
Merge branch 'master' into typed-document-string
beerose Mar 20, 2023
0f155b4
Update docs
beerose Mar 21, 2023
5771e6d
Update changeset
beerose Mar 21, 2023
5ce6b4f
Update versions in changeset
beerose Mar 21, 2023
a86f4bc
Merge branch 'master' into typed-document-string
beerose Mar 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@graphql-codegen/client-preset": patch
---
dependencies updates:
- Updated dependency [`@graphql-typed-document-node/core@3.2.0-alpha-20230309104331-975d9d2` ↗︎](https://www.npmjs.com/package/@graphql-typed-document-node/core/v/3.2.0) (from `3.1.2`, in `dependencies`)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: update with the latest version when a PR to @graphql-typed-document-node/core is accepted and released

42 changes: 20 additions & 22 deletions dev-test/gql-tag-operations/graphql/fragment-masking.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,46 @@
import { ResultOf, TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
import { ResultOf, DocumentTypeDecoration } from '@graphql-typed-document-node/core';

export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocumentType extends DocumentNode<
infer TType,
any
>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> =
TDocumentType extends DocumentTypeDecoration<infer TType, any>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
Comment on lines -3 to +8
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this considered a breaking change for the codegen or not? @n1ru4l @saihaj

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, people shouldn't use this type with anything else than our generated stuff.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed should be fine

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, as I think about it a bit more, this change kinda requires people to upgrade their typed document node version. 🤔

In graphql-yoga we treat peerDependency upgrades depending on the type of change.

e.g.
X.1.1 bump of a peer dependency would be a breaking change
1.X.1 bump of a peer dependency would be a minor change
1.1.X bump of a peer dependency would be a patch change

So I think we should treat this the same here (minor change).

Here the special case is that it is not listed as a peer dependency, but theoretically, it could be one, as people will need to install it, otherwise, their code won't compile with strict package manages like pnpm and yarn that do no hoisting. 🤔

Then, however, whether it should be a peer dependency or not also depends on the location where the code is generated.

So the safest option would be to ship this as a breaking change. I am sure people will open issues if we don't...

: never
: never
: never;
: never;

// return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentNode<TType, any>>
| ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
| FragmentType<DocumentTypeDecoration<TType, any>>
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined
): TType | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}

export function makeFragmentData<F extends DocumentNode, FT extends ResultOf<F>>(
export function makeFragmentData<F extends DocumentTypeDecoration<any, any>, FT extends ResultOf<F>>(
data: FT,
_fragment: F
): FragmentType<F> {
Expand Down
2 changes: 1 addition & 1 deletion examples/persisted-documents/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"@graphql-yoga/plugin-persisted-operations": "1.7.2"
},
"devDependencies": {
"@graphql-typed-document-node/core": "3.1.2",
"@graphql-typed-document-node/core": "3.2.0-alpha-20230309104331-975d9d2",
"jest": "28.1.3",
"babel-jest": "28.1.3",
"@graphql-codegen/cli": "3.2.2",
Expand Down
42 changes: 20 additions & 22 deletions examples/persisted-documents/src/gql/fragment-masking.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,46 @@
import { ResultOf, TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
import { ResultOf, DocumentTypeDecoration } from '@graphql-typed-document-node/core';

export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocumentType extends DocumentNode<
infer TType,
any
>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> =
TDocumentType extends DocumentTypeDecoration<infer TType, any>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never
: never;
: never;

// return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentNode<TType, any>>
| ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
| FragmentType<DocumentTypeDecoration<TType, any>>
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined
): TType | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}

export function makeFragmentData<F extends DocumentNode, FT extends ResultOf<F>>(
export function makeFragmentData<F extends DocumentTypeDecoration<any, any>, FT extends ResultOf<F>>(
data: FT,
_fragment: F
): FragmentType<F> {
Expand Down
42 changes: 20 additions & 22 deletions examples/react/apollo-client-swc-plugin/src/gql/fragment-masking.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,46 @@
import { ResultOf, TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
import { ResultOf, DocumentTypeDecoration } from '@graphql-typed-document-node/core';

export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocumentType extends DocumentNode<
infer TType,
any
>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> =
TDocumentType extends DocumentTypeDecoration<infer TType, any>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never
: never;
: never;

// return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentNode<TType, any>>
| ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
| FragmentType<DocumentTypeDecoration<TType, any>>
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined
): TType | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}

export function makeFragmentData<F extends DocumentNode, FT extends ResultOf<F>>(
export function makeFragmentData<F extends DocumentTypeDecoration<any, any>, FT extends ResultOf<F>>(
data: FT,
_fragment: F
): FragmentType<F> {
Expand Down
42 changes: 20 additions & 22 deletions examples/react/apollo-client/src/gql/fragment-masking.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,46 @@
import { ResultOf, TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
import { ResultOf, DocumentTypeDecoration } from '@graphql-typed-document-node/core';

export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocumentType extends DocumentNode<
infer TType,
any
>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> =
TDocumentType extends DocumentTypeDecoration<infer TType, any>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never
: never;
: never;

// return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentNode<TType, any>>
| ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
| FragmentType<DocumentTypeDecoration<TType, any>>
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined
): TType | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}

export function makeFragmentData<F extends DocumentNode, FT extends ResultOf<F>>(
export function makeFragmentData<F extends DocumentTypeDecoration<any, any>, FT extends ResultOf<F>>(
data: FT,
_fragment: F
): FragmentType<F> {
Expand Down
42 changes: 20 additions & 22 deletions examples/react/graphql-request/src/gql/fragment-masking.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,46 @@
import { ResultOf, TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
import { ResultOf, DocumentTypeDecoration } from '@graphql-typed-document-node/core';

export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocumentType extends DocumentNode<
infer TType,
any
>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> =
TDocumentType extends DocumentTypeDecoration<infer TType, any>
? TType extends { ' $fragmentName'?: infer TKey }
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never
: never;
: never;

// return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>> | null | undefined
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>,
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentNode<TType, any>>
| ReadonlyArray<FragmentType<DocumentNode<TType, any>>>
| FragmentType<DocumentTypeDecoration<TType, any>>
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined
): TType | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}

export function makeFragmentData<F extends DocumentNode, FT extends ResultOf<F>>(
export function makeFragmentData<F extends DocumentTypeDecoration<any, any>, FT extends ResultOf<F>>(
data: FT,
_fragment: F
): FragmentType<F> {
Expand Down
Loading