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.tsThe 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
}For more information, see https://typed-graphql-builder.spion.dev