- GraphQL File Upload support
- Works in browsers and NodeJS
- Zero dependencies
- Small size (around 2Kb gzipped)
- Full Typescript support
- Supports queries generated by graphql-tag
- Supports GraphQL GET requests
- Perfect for React apps in combination with react-query. See Next.js example
npm install awesome-graphql-client
import { AwesomeGraphQLClient } from 'awesome-graphql-client'
const client = new AwesomeGraphQLClient({ endpoint: '/graphql' })
// Also query can be an output from graphql-tag (see examples below)
const GetUsers = `
query getUsers {
users {
id
}
}
`
const UploadUserAvatar = `
mutation uploadUserAvatar($userId: Int!, $file: Upload!) {
updateUser(id: $userId, input: { avatar: $file }) {
id
}
}
`
client
.request(GetUsers)
.then(data =>
client.request(UploadUserAvatar, {
id: data.users[0].id,
file: document.querySelector('input#avatar').files[0],
}),
)
.then(data => console.log(data.updateUser.id))
.catch(error => console.log(error))
const { AwesomeGraphQLClient } = require('awesome-graphql-client')
const FormData = require('form-data')
const { createReadStream } = require('fs')
const http = require('http')
const fetch = require('node-fetch')
const client = new AwesomeGraphQLClient({
endpoint: 'http://localhost:8080/graphql',
fetch,
FormData, // Required only if you're using file upload
fetchOptions: {
// Using HTTP Keep-Alive will make requests ~2x faster in NodeJS:
// https://github.com/Ethan-Arrowood/undici-fetch/blob/main/benchmarks.md#fetch
agent: new http.Agent({ keepAlive: true }),
},
})
// Also query can be an output from graphql-tag (see examples below)
const UploadUserAvatar = `
mutation uploadUserAvatar($userId: Int!, $file: Upload!) {
updateUser(id: $userId, input: { avatar: $file }) {
id
}
}
`
client
.request(UploadUserAvatar, { file: createReadStream('./avatar.img'), userId: 10 })
.then(data => console.log(data.updateUser.id))
.catch(error => console.log(error))
For even better performance check out undici example
- API
- Examples
Usage:
import { AwesomeGraphQLClient } from 'awesome-graphql-client'
const client = new AwesomeGraphQLClient(config)
endpoint
: string - The URL to your GraphQL endpoint (required)fetch
: Function - Fetch polyfill (necessary in NodeJS, see example)fetchOptions
: object - Overrides for fetch optionsFormData
: object - FormData polyfill (necessary in NodeJS if you are using file upload, see example)formatQuery
: function(query: any): string - Custom query formatter (see example)onError
: function(error: GraphQLRequestError | Error): void - Provided callback will be called before throwing an error (see example)isFileUpload
: function(value: unknown): boolean - Custom predicate function for checking if value is a file (see example)
client.setFetchOptions(fetchOptions: FetchOptions)
: Sets fetch options. See examples belowclient.getFetchOptions()
: Returns current fetch optionsclient.setEndpoint(): string
: Sets a new GraphQL endpointclient.getEndpoint(): string
: Returns current GraphQL endpointclient.request(query, variables?, fetchOptions?): Promise<data>
: Sends GraphQL Request and returns data or throws an errorclient.requestSafe(query, variables?, fetchOptions?): Promise<{ data, response } | { error }>
: Sends GraphQL Request and returns object with 'ok: true', 'data' and 'response' or with 'ok: false' and 'error' fields. See examples below. Notice: this function never throws.
message
: string - Error messagequery
: string - GraphQL queryvariables
: string | undefined - GraphQL variablesresponse
: Response - response returned from fetch
interface getUser {
user: { id: number; login: string } | null
}
interface getUserVariables {
id: number
}
const query = `
query getUser($id: Int!) {
user {
id
login
}
}
`
const client = new AwesomeGraphQLClient({
endpoint: 'http://localhost:3000/graphql',
})
client
.request<getUser, getUserVariables>(query, { id: 10 })
.then(data => console.log(data))
.catch(error => console.log(error))
client.requestSafe<getUser, getUserVariables>(query, { id: 10 }).then(result => {
if (!result.ok) {
throw result.error
}
console.log(`Status ${result.response.status}`, `Data ${result.data.user}`)
})
You can generate types from queries by using GraphQL Code Generator with TypedDocumentNode plugin
# queries.graphql
query getUser($id: Int!) {
user {
id
login
}
}
// index.ts
import { TypedDocumentNode } from '@graphql-typed-document-node/core'
import { AwesomeGraphQLClient } from 'awesome-graphql-client'
import { print } from 'graphql/language/printer'
import { GetCharactersDocument } from './generated'
const gqlClient = new AwesomeGraphQLClient({
endpoint: 'https://rickandmortyapi.com/graphql',
formatQuery: (query: TypedDocumentNode) => print(query),
})
// AwesomeGraphQLClient will infer all types from the passed query automagically:
gqlClient
.request(GetCharactersDocument, { name: 'Rick' })
.then(data => console.log(data))
.catch(error => console.log(error))
Check out full example at examples/typed-document-node
import { AwesomeGraphQLClient, GraphQLRequestError } from 'awesome-graphql-client'
const client = new AwesomeGraphQLClient({
endpoint: '/graphql',
onError(error) {
if (error instanceof GraphQLRequestError) {
console.error(error.message)
console.groupCollapsed('Operation:')
console.log({ query: error.query, variables: error.variables })
console.groupEnd()
} else {
console.error(error)
}
},
})
Internally it uses URLSearchParams API. Consider polyfilling URL standard for this feature to work in IE
client
.request(query, variables, { method: 'GET' })
.then(data => console.log(data))
.catch(err => console.log(err))
import { AwesomeGraphQLClient } from 'awesome-graphql-client'
import { DocumentNode } from 'graphql/language/ast'
import { print } from 'graphql/language/printer'
import gql from 'graphql-tag'
const client = new AwesomeGraphQLClient({
endpoint: '/graphql',
formatQuery: (query: DocumentNode | string) =>
typeof query === 'string' ? query : print(query),
})
const query = gql`
query me {
me {
login
}
}
`
client
.request(query)
.then(data => console.log(data))
.catch(err => console.log(err))
Recommended approach if you're using graphql-tag
only for syntax highlighting and static analysis such as linting and types generation. It has less computational cost and makes overall smaller bundles. GraphQL fragments are supported too.
import { AwesomeGraphQLClient, gql } from 'awesome-graphql-client'
const client = new AwesomeGraphQLClient({ endpoint: '/graphql' })
const query = gql`
query me {
me {
login
}
}
`
client
.request(query)
.then(data => console.log(data))
.catch(err => console.log(err))
Perfect for Typescript projects. See example above
const { AwesomeGraphQLClient } = require('awesome-graphql-client')
const nodeFetch = require('node-fetch')
const client = new AwesomeGraphQLClient({
endpoint: 'http://localhost:8080/graphql',
fetch: require('fetch-cookie')(nodeFetch),
})
const { AwesomeGraphQLClient, isFileUpload } = require('awesome-graphql-client')
const client = new AwesomeGraphQLClient({
endpoint: 'http://localhost:8080/graphql',
// By default File, Blob, Buffer, Promise and stream-like instances are considered as files.
// You can expand this behaviour by adding a custom predicate
isFileUpload: value => isFileUpload(value) || value instanceof MyCustomFile,
})
https://github.com/lynxtaa/awesome-graphql-client/tree/master/examples