A GraphQL query builder that replaces gql
query strings or .graphql files in your code with pure TypeScript. Compatible with any TypedDocumentNode
-compatible library such as Apollo Client, Urql and graphql-request.
npx typed-graphql-builder \
--schema https://countries.trevorblades.com \
--output generated-api.ts
The schema can be an URL to a GraphQL endpoint with introspection support or a path to a .graphql
schema file.
The generated API depends on two small libraries that should be added to package.json
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
"graphql-tag": "^2.12.6",
}
The generated API exports query, mutation, subscription
to access the schema roots.
The query
function gives us access to the root query
object of our schema:
import { query } from './generated-api'
const continentQuery = query(q => [
q.continents(c => [
//
c.name,
c.code,
]),
])
The above code will generate a query of type TypedDocumentNode<{continents: Array<{name: string, country: string}>}, {}>
which corresponds to the following GraphQL query string:
query {
continents {
name
code
}
}
We can use input variables using the $
helper. Variable types are inferred automatically:
import { $, query } from './generated-api'
const countryQuery = query(q => [
q.countries({ filter: { continent: { eq: $('continentCode') } } }, c => [
c.code,
c.capital,
c.name,
c.languages(l => [l.name]),
]),
])
This will generate TypedDocumentNode<{ countries: Array<{...}>}, { continentCode?: string | null | undefined }>
, a typed document node that includes the input variable continentCode
.
Note: By default,
$
will allow nulls if the input type allows it in the desired position. Use$$
to force-require the variable to have a non-null value.
The GraphQL version of the above query is shown below:
query ($continentCode: String) {
countries(filter: { continent: { eq: $continentCode } }) {
code
capital
name
languages {
name
}
}
}
The queries written above can be used with any client library that supports TypedDocumentNode. For example, if using Apollo's useQuery
, we would write the following:
const CountryListComponent = () => {
const continents = useQuery(continentQuery)
const [continent, setContinent] = useState('EU')
const countryList = useQuery(countryQuery, {
variables: {
continent,
},
})
// render the country list here
}