-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Changes from 3 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
4a7b339
Add unit tests
beerose 504367a
Add TypedDocumentNode string alternative
beerose c7105db
Temporarily use snapshot version of @graphql-typed-document-node/core
beerose 13e48a9
chore(dependencies): updated changesets for modified dependencies
github-actions[bot] 02ed2b3
Update fragment-masking.ts files
beerose 2d5a4e7
Update fragment-masking in dev-test dir
beerose 590b2e2
Update @graphql-typed-document-node/core version in examples
beerose 8e4e93f
Merge branch 'master' into typed-document-string
beerose 7a5d42d
Update test after latest implememntation changes
beerose 3892ba2
Changeset
beerose ef28588
Modify existing example
beerose 961251f
Update typescript-graphql-request example
beerose dbd2053
Merge branch 'master' into typed-document-string
beerose 8005ea3
Add failing test for duplicated fragments
beerose 2c6ee68
Inline fragments in string document mode
beerose 7b073f3
Update example with fragment inlining
beerose db98f71
Support __meta__ with typed document string
beerose 346e1e5
Add TypedDocumentString class to handle metadata
beerose 4e732da
Fix import
beerose 82b75f0
Remove unused import
beerose 56170f6
Merge branch 'master' into typed-document-string
beerose e3120b3
Update @graphql-typed-document-node/core version
beerose 8b5ad73
Merge branch 'master' into typed-document-string
beerose f960ccf
chore(dependencies): updated changesets for modified dependencies
github-actions[bot] ed34330
Update react-query example — use fetch insetad of http executor
beerose 0283daf
Merge branch 'master' into typed-document-string
beerose cfd9380
Add docs
beerose a97276b
Update @graphql-typed-document-node/code version
beerose 2e99784
chore(dependencies): updated changesets for modified dependencies
github-actions[bot] bdc1e7d
Add more info to the dosc
beerose e954bea
Merge branch 'master' into typed-document-string
beerose 0f155b4
Update docs
beerose 5771e6d
Update changeset
beerose 5ce6b4f
Update versions in changeset
beerose a86f4bc
Merge branch 'master' into typed-document-string
beerose File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Using GraphQL Code Generator with URQL and React | ||
|
||
This example illustrates using GraphQL Code Generator in a React application using the URQL GraphQL Client. | ||
|
||
You will find the TypeScript-based codegen configuration in [`codegen.ts`](./codegen.ts). | ||
|
||
This simple codegen configuration generates types and helpers in the [`src/gql`](./src/gql/) folder that help you to get typed GraphQL Queries and Mutations seamlessly ⚡️ | ||
|
||
<br /> | ||
|
||
For a step-by-step implementation tutorial, please refer to the related guide: | ||
|
||
https://www.the-guild.dev/graphql/codegen/docs/guides/react-vue-angular | ||
|
||
-- | ||
|
||
Please note that the `client` preset used in this example is compatible with `@urql/core` (since `1.15.0`), `@urql/preact` (since `1.4.0`) and `urql` (since `1.11.0`). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
import { type CodegenConfig } from '@graphql-codegen/cli'; | ||
|
||
const config: CodegenConfig = { | ||
schema: 'https://swapi-graphql.netlify.app/.netlify/functions/index', | ||
documents: ['src/**/*.tsx', '!src/gql/**/*'], | ||
generates: { | ||
'./src/gql/': { | ||
preset: 'client', | ||
config: { | ||
documentMode: 'string', | ||
}, | ||
}, | ||
}, | ||
hooks: { afterAllFileWrite: ['prettier --write'] }, | ||
}; | ||
|
||
export default config; |
10 changes: 10 additions & 0 deletions
10
examples/react/urql-string-document-mode/cypress.config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
import { defineConfig } from 'cypress'; | ||
|
||
export default defineConfig({ | ||
e2e: { | ||
setupNodeEvents(_on, _config) { | ||
// implement node event listeners here | ||
}, | ||
}, | ||
}); |
6 changes: 6 additions & 0 deletions
6
examples/react/urql-string-document-mode/cypress/e2e/end2end.cy.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
describe('template spec', () => { | ||
it('renders everything correctly', () => { | ||
cy.visit('http://localhost:3000'); | ||
cy.get('h3').should('contain', 'A New Hope'); | ||
}); | ||
}); |
1 change: 1 addition & 0 deletions
1
examples/react/urql-string-document-mode/cypress/support/commands.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/// <reference types="cypress" /> |
1 change: 1 addition & 0 deletions
1
examples/react/urql-string-document-mode/cypress/support/e2e.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import './commands'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite App</title> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "example-react-urql-string-document-node", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0", | ||
"urql": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "^18.0.17", | ||
"@types/react-dom": "^18.0.10", | ||
"@graphql-codegen/cli": "^3.2.2", | ||
"@graphql-codegen/client-preset": "^2.1.1", | ||
"@vitejs/plugin-react": "^3.1.0", | ||
"typescript": "4.9.5", | ||
"serve": "14.2.0", | ||
"cypress": "12.6.0", | ||
"start-server-and-test": "2.0.0", | ||
"vite": "^4.1.0" | ||
}, | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "vite build", | ||
"start": "serve -s dist", | ||
"test": "cypress run", | ||
"test:end2end": "start-server-and-test start http://localhost:3000 test", | ||
"codegen": "graphql-codegen --config codegen.ts" | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
.App { | ||
text-align: center; | ||
} | ||
|
||
.App-logo { | ||
height: 40vmin; | ||
pointer-events: none; | ||
} | ||
|
||
@media (prefers-reduced-motion: no-preference) { | ||
.App-logo { | ||
animation: App-logo-spin infinite 20s linear; | ||
} | ||
} | ||
|
||
.App-header { | ||
background-color: #282c34; | ||
min-height: 100vh; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
font-size: calc(10px + 2vmin); | ||
color: white; | ||
} | ||
|
||
.App-link { | ||
color: #61dafb; | ||
} | ||
|
||
@keyframes App-logo-spin { | ||
from { | ||
transform: rotate(0deg); | ||
} | ||
to { | ||
transform: rotate(360deg); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { TypedDocumentString } from '@graphql-typed-document-node/core'; | ||
|
||
import './App.css'; | ||
import Film from './Film'; | ||
import { graphql } from './gql'; | ||
import { AnyVariables, OperationContext, RequestPolicy, TypedDocumentNode, useQuery, UseQueryResponse } from 'urql'; | ||
import type { DocumentNode } from 'graphql'; | ||
|
||
const allFilmsWithVariablesQueryDocument = graphql(/* GraphQL */ ` | ||
query allFilmsWithVariablesQuery($first: Int!) { | ||
allFilms(first: $first) { | ||
edges { | ||
node { | ||
...FilmItem | ||
} | ||
} | ||
} | ||
} | ||
`); | ||
|
||
declare module 'urql' { | ||
// @ts-expect-error this is just temporary until we update types in urql | ||
beerose marked this conversation as resolved.
Show resolved
Hide resolved
|
||
export type UseQueryArgs<Variables extends AnyVariables = AnyVariables, Data = any> = { | ||
query: string | DocumentNode | TypedDocumentNode<Data, Variables> | TypedDocumentString<Data, Variables>; | ||
requestPolicy?: RequestPolicy; | ||
context?: Partial<OperationContext>; | ||
pause?: boolean; | ||
} & (Variables extends void | ||
? { | ||
variables?: Variables; | ||
} | ||
: Variables extends { | ||
[P in keyof Variables]: Variables[P] | null; | ||
} | ||
? { | ||
variables?: Variables; | ||
} | ||
: { | ||
variables: Variables; | ||
}); | ||
|
||
export function useQuery<Data = any, Variables extends AnyVariables = AnyVariables>( | ||
args: UseQueryArgs<Variables, Data> | ||
): UseQueryResponse<Data, Variables>; | ||
} | ||
|
||
function App() { | ||
const [{ data }] = useQuery({ | ||
query: allFilmsWithVariablesQueryDocument, | ||
variables: { | ||
first: 10, | ||
}, | ||
}); | ||
|
||
return ( | ||
<div className="App"> | ||
{data && <ul>{data.allFilms?.edges?.map((e, i) => e?.node && <Film film={e?.node} key={`film-${i}`} />)}</ul>} | ||
</div> | ||
); | ||
} | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { FragmentType, useFragment } from './gql/fragment-masking'; | ||
import { graphql } from './gql'; | ||
|
||
export const FilmFragment = graphql(/* GraphQL */ ` | ||
fragment FilmItem on Film { | ||
id | ||
title | ||
releaseDate | ||
producers | ||
} | ||
`); | ||
|
||
const Film = (props: { | ||
/* tweet property has the correct type 🎉 */ | ||
film: FragmentType<typeof FilmFragment>; | ||
}) => { | ||
const film = useFragment(FilmFragment, props.film); | ||
return ( | ||
<div> | ||
<h3>{film.title}</h3> | ||
<p>{film.releaseDate}</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Film; |
48 changes: 48 additions & 0 deletions
48
examples/react/urql-string-document-mode/src/gql/fragment-masking.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { ResultOf, DocumentTypeDecoration } from '@graphql-typed-document-node/core'; | ||
|
||
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; | ||
|
||
// return non-nullable if `fragmentType` is non-nullable | ||
export function useFragment<TType>( | ||
_documentNode: DocumentTypeDecoration<TType, any>, | ||
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | ||
): TType; | ||
// return nullable if `fragmentType` is nullable | ||
export function useFragment<TType>( | ||
_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: 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: DocumentTypeDecoration<TType, any>, | ||
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined | ||
): ReadonlyArray<TType> | null | undefined; | ||
export function useFragment<TType>( | ||
_documentNode: DocumentTypeDecoration<TType, any>, | ||
fragmentType: | ||
| 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 DocumentTypeDecoration<any, any>, FT extends ResultOf<F>>( | ||
data: FT, | ||
_fragment: F | ||
): FragmentType<F> { | ||
return data as FragmentType<F>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* eslint-disable */ | ||
import * as types from './graphql'; | ||
|
||
/** | ||
* Map of all GraphQL operations in the project. | ||
* | ||
* This map has several performance disadvantages: | ||
* 1. It is not tree-shakeable, so it will include all operations in the project. | ||
* 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle. | ||
* 3. It does not support dead code elimination, so it will add unused operations. | ||
* | ||
* Therefore it is highly recommended to use the babel or swc plugin for production. | ||
*/ | ||
const documents = { | ||
'\n query allFilmsWithVariablesQuery($first: Int!) {\n allFilms(first: $first) {\n edges {\n node {\n ...FilmItem\n }\n }\n }\n }\n': | ||
types.AllFilmsWithVariablesQueryDocument, | ||
'\n fragment FilmItem on Film {\n id\n title\n releaseDate\n producers\n }\n': | ||
types.FilmItemFragmentDoc, | ||
}; | ||
|
||
/** | ||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. | ||
*/ | ||
export function graphql( | ||
source: '\n query allFilmsWithVariablesQuery($first: Int!) {\n allFilms(first: $first) {\n edges {\n node {\n ...FilmItem\n }\n }\n }\n }\n' | ||
): typeof import('./graphql').AllFilmsWithVariablesQueryDocument; | ||
/** | ||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. | ||
*/ | ||
export function graphql( | ||
source: '\n fragment FilmItem on Film {\n id\n title\n releaseDate\n producers\n }\n' | ||
): typeof import('./graphql').FilmItemFragmentDoc; | ||
|
||
export function graphql(source: string) { | ||
return (documents as any)[source] ?? {}; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we want a new example or just modify an existing one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think urql is not a good example because it actually requires the AST at runtime anyways 🤔 .
We can add or modify a react-query or similar example that does not require the AST.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it, though? It accepts both string and AST and seems to work fine (I modified the original urql example). Unless I'm missing something.
Regarding the
react-query
example — it currently uses@graphql-tools/executor-http
, but I could replace it withfetch
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, urql uses graphql internally and thus will just parse the string to the ast at runtime
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I am fine with replacing executor HTTP in react-query!