GraphQL Client with file upload support for NodeJS and browser
npm install awesome-graphql-client- 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
``sh`
npm install awesome-graphql-client
`js
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))
`
`js
import { openAsBlob } from 'node:fs'
import { AwesomeGraphQLClient } from 'awesome-graphql-client'
const client = new AwesomeGraphQLClient({
endpoint: 'http://localhost:8080/graphql',
})
// 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
}
}
const blob = await openAsBlob('./avatar.png')
client
.request(UploadUserAvatar, { file: new File([blob], 'avatar.png'), userId: 10 })
.then(data => console.log(data.updateUser.id))
.catch(error => console.log(error))
`
- API
- AwesomeGraphQLClient
- GraphQLRequestError
- gql
- isFileUpload
- Examples
- Typescript
- Error Logging
- GraphQL GET Requests
- GraphQL Tag
- Cookies in NodeJS
- Custom _isFileUpload_ Predicate
- More Examples
Usage:
`js`
import { AwesomeGraphQLClient } from 'awesome-graphql-client'
const client = new AwesomeGraphQLClient(config)
- endpoint: _string_ - The URL to your GraphQL endpoint (required)fetch
- : _Function_ - Fetch polyfillfetchOptions
- : _object_ - Overrides for fetch optionsFormData
- : _object_ - FormData polyfillformatQuery
- : _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
- : Sends GraphQL Request and returns data or throws an errorclient.requestSafe(query, variables?, fetchOptions?): Promise<{ ok: true, data, response } | { ok: false, error, partialData }>
- : Sends GraphQL Request and returns object with 'ok: true', 'data' and 'response' or with 'ok: false', 'error' and 'partialData' fields. See examples below. _Notice: this function never throws_.
- message: _string_ - Error messagequery
- : _string_ - GraphQL queryvariables
- : _string | undefined_ - GraphQL variablesresponse
- : _Response_ - response returned from fetchfieldErrors
- : _GraphQLFieldError[]_ - GraphQL field errors
`ts
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
.then(data => console.log(data))
.catch(error => console.log(error))
client.requestSafe
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
`graphql`queries.graphql
query getUser($id: Int!) {
user {
id
login
}
}
`ts
// 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
`js
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
`js`
client
.request(query, variables, { method: 'GET' })
.then(data => console.log(data))
.catch(err => console.log(err))
`ts
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.
`js
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
`js
import { AwesomeGraphQLClient } from 'awesome-graphql-client'
import fetchCookie from 'fetch-cookie'
const client = new AwesomeGraphQLClient({
endpoint: 'http://localhost:8080/graphql',
fetch: fetchCookie(globalThis.fetch),
})
`
`js
import { AwesomeGraphQLClient, isFileUpload } from '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