Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
graphql-request
Advanced tools
Minimal GraphQL client supporting Node and browsers for scripts or simple apps
The graphql-request npm package is a minimal GraphQL client for Node.js and browsers, providing a simple and flexible way to execute GraphQL queries, mutations, and subscriptions. It is designed for making HTTP requests to a GraphQL server, and it's a lightweight alternative to more complex GraphQL clients like Apollo Client or Relay.
Simple Query Execution
Execute a simple GraphQL query and log the result.
const { request } = require('graphql-request');
const query = `{ hello }`;
request('https://api.graph.cool/simple/v1/movies', query).then((data) => console.log(data));
Mutation Execution
Execute a GraphQL mutation to create a new resource and log the result.
const { request } = require('graphql-request');
const mutation = `mutation ($title: String!) { createMovie(title: $title) { id } }`;
const variables = { title: 'Inception' };
request('https://api.graph.cool/simple/v1/movies', mutation, variables).then((data) => console.log(data));
Error Handling
Handle errors that may occur during the execution of a GraphQL request.
const { request } = require('graphql-request');
const query = `{ hello }`;
request('https://api.graph.cool/simple/v1/movies', query).catch((error) => console.error(error.response.errors));
GraphQL Subscriptions
Set up a GraphQL subscription to listen for real-time updates.
const { SubscriptionClient } = require('graphql-request');
const ws = require('ws');
const subscriptionClient = new SubscriptionClient('wss://api.graph.cool/simple/v1/movies', { reconnect: true }, ws);
const query = `subscription { newMovie { id title } }`;
const observer = subscriptionClient.request({ query }).subscribe({
next(data) { console.log(data); },
error(err) { console.error(err); }
});
Apollo Client is a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. It is more feature-rich than graphql-request, offering advanced features like caching, optimistic UI updates, and integration with various view layers.
urql is a highly customizable and versatile GraphQL client for React applications. It includes features like caching, pagination, and subscriptions. It is similar to graphql-request in its simplicity and ease of use but offers more extensibility and integration with the React ecosystem.
Relay is a framework for building data-driven React applications with GraphQL. It provides a powerful and opinionated set of tools for fetching, storing, and managing GraphQL data. Relay is more complex than graphql-request and is designed for use cases that require fine-grained control over data management and performance optimization.
Minimal GraphQL client supporting Node and browsers for scripts or simple apps
fetch
require
instead of import
node
fetch
methodasync
/ await
)npm add graphql-request graphql
Send a GraphQL query with a single line of code. ▶️ Try it out.
import { request, gql } from 'graphql-request'
const query = gql`
{
company {
ceo
}
roadster {
apoapsis_au
}
}
`
request('https://api.spacex.land/graphql/', query).then((data) => console.log(data))
import { request, GraphQLClient } from 'graphql-request'
// Run GraphQL queries/mutations using a static function
request(endpoint, query, variables).then((data) => console.log(data))
// ... or create a GraphQL client instance to send requests
const client = new GraphQLClient(endpoint, { headers: {} })
client.request(query, variables).then((data) => console.log(data))
You can also use the single argument function variant:
request({
url: endpoint,
document: query,
variables: variables,
requestHeaders: headers,
}).then((data) => console.log(data))
We only officially support LTS Node versions. We also make an effort to support two additional versions:
You are free to try using other versions of Node (e.g. 13.x
) with graphql-request
but at your own risk.
graphql-request@^5
supports TypedDocumentNode
, the typed counterpart of graphql
's DocumentNode
.
Installing and configuring GraphQL Code Generator requires a few steps in order to get end-to-end typed GraphQL operations using the provided graphql()
helper:
import request from 'graphql-request'
import { graphql } from './gql/gql'
const getMovieQueryDocument = graphql(/* GraphQL */ `
query getMovie($title: String!) {
Movie(title: $title) {
releaseDate
actors {
name
}
}
}
`)
const data = await request(
'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr',
getMovieQueryDocument,
// variables are type-checked!
{ title: 'Inception' }
)
// `data.Movie` is typed!
The complete example is available in the GraphQL Code Generator repository
Visit GraphQL Code Generator's dedicated guide to get started: https://www.the-guild.dev/graphql/codegen/docs/guides/react-vue.
import { GraphQLClient, gql } from 'graphql-request'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const graphQLClient = new GraphQLClient(endpoint, {
headers: {
authorization: 'Bearer MY_TOKEN',
},
})
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
const data = await graphQLClient.request(query)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
If you want to set headers after the GraphQLClient has been initialised, you can use the setHeader()
or setHeaders()
functions.
import { GraphQLClient } from 'graphql-request'
const client = new GraphQLClient(endpoint)
// Set a single header
client.setHeader('authorization', 'Bearer MY_TOKEN')
// Override all existing headers
client.setHeaders({
authorization: 'Bearer MY_TOKEN',
anotherheader: 'header_value',
})
If you want to change the endpoint after the GraphQLClient has been initialised, you can use the setEndpoint()
function.
import { GraphQLClient } from 'graphql-request'
const client = new GraphQLClient(endpoint)
client.setEndpoint(newEndpoint)
It is possible to pass custom headers for each request. request()
and rawRequest()
accept a header object as the third parameter
import { GraphQLClient } from 'graphql-request'
const client = new GraphQLClient(endpoint)
const query = gql`
query getMovie($title: String!) {
Movie(title: $title) {
releaseDate
actors {
name
}
}
}
`
const variables = {
title: 'Inception',
}
const requestHeaders = {
authorization: 'Bearer MY_TOKEN',
}
// Overrides the clients headers with the passed values
const data = await client.request(query, variables, requestHeaders)
It's possible to recalculate the global client headers dynamically before each request.
To do that, pass a function that returns the headers to the headers
property when creating a new GraphQLClient
.
import { GraphQLClient } from 'graphql-request'
const client = new GraphQLClient(endpoint, {
headers: () => ({ 'X-Sent-At-Time': Date.now() }),
})
const query = gql`
query getCars {
cars {
name
}
}
`
// Function saved in the client runs and calculates fresh headers before each request
const data = await client.request(query)
fetch
import { GraphQLClient, gql } from 'graphql-request'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const graphQLClient = new GraphQLClient(endpoint, {
credentials: 'include',
mode: 'cors',
})
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
const data = await graphQLClient.request(query)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
If you want to use non-standard JSON types, you can use your own JSON serializer to replace JSON.parse
/JSON.stringify
used by the GraphQLClient
.
An original use case for this feature is BigInt
support:
import JSONbig from 'json-bigint'
import { GraphQLClient, gql } from 'graphql-request'
async function main() {
const jsonSerializer = JSONbig({ useNativeBigInt: true })
const graphQLClient = new GraphQLClient(endpoint, { jsonSerializer })
const data = await graphQLClient.request(
gql`
{
someBigInt
}
`
)
console.log(typeof data.someBigInt) // if >MAX_SAFE_INTEGER then 'bigint' else 'number'
}
import { request, gql } from 'graphql-request'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const query = gql`
query getMovie($title: String!) {
Movie(title: $title) {
releaseDate
actors {
name
}
}
}
`
const variables = {
title: 'Inception',
}
const data = await request(endpoint, query, variables)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
Queries can be sent as an HTTP GET request:
import { GraphQLClient, gql } from 'graphql-request'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const graphQLClient = new GraphQLClient(endpoint, {
method: 'GET',
jsonSerializer: {
parse: JSON.parse,
stringify: JSON.stringify,
},
})
const query = gql`
query getMovie($title: String!) {
Movie(title: $title) {
releaseDate
actors {
name
}
}
}
`
const variables = {
title: 'Inception',
}
const data = await graphQLClient.request(query, variables)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
import { GraphQLClient, gql } from 'graphql-request'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const graphQLClient = new GraphQLClient(endpoint, {
headers: {
authorization: 'Bearer MY_TOKEN',
},
})
const mutation = gql`
mutation AddMovie($title: String!, $releaseDate: Int!) {
insert_movies_one(object: { title: $title, releaseDate: $releaseDate }) {
title
releaseDate
}
}
`
const variables = {
title: 'Inception',
releaseDate: 2010,
}
const data = await graphQLClient.request(mutation, variables)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
import { request, gql } from 'graphql-request'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
fullname # "Cannot query field 'fullname' on type 'Actor'. Did you mean 'name'?"
}
}
}
`
try {
const data = await request(endpoint, query)
console.log(JSON.stringify(data, undefined, 2))
} catch (error) {
console.error(JSON.stringify(error, undefined, 2))
process.exit(1)
}
}
main().catch((error) => console.error(error))
require
instead of import
const { request, gql } = require('graphql-request')
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
const data = await request(endpoint, query)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
node
npm install fetch-cookie
require('fetch-cookie/node-fetch')(require('node-fetch'))
import { GraphQLClient, gql } from 'graphql-request'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const graphQLClient = new GraphQLClient(endpoint, {
headers: {
authorization: 'Bearer MY_TOKEN',
},
})
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
const data = await graphQLClient.rawRequest(query)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
fetch
methodnpm install fetch-cookie
import { GraphQLClient, gql } from 'graphql-request'
import crossFetch from 'cross-fetch'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
// a cookie jar scoped to the client object
const fetch = require('fetch-cookie')(crossFetch)
const graphQLClient = new GraphQLClient(endpoint, { fetch })
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
const data = await graphQLClient.rawRequest(query)
console.log(JSON.stringify(data, undefined, 2))
}
main().catch((error) => console.error(error))
The request
method will return the data
or errors
key from the response.
If you need to access the extensions
key you can use the rawRequest
method:
import { rawRequest, gql } from 'graphql-request'
async function main() {
const endpoint = 'https://api.graph.cool/simple/v1/cixos23120m0n0173veiiwrjr'
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
const { data, errors, extensions, headers, status } = await rawRequest(endpoint, query)
console.log(JSON.stringify({ data, errors, extensions, headers, status }, undefined, 2))
}
main().catch((error) => console.error(error))
import { request } from 'graphql-request'
const UploadUserAvatar = gql`
mutation uploadUserAvatar($userId: Int!, $file: Upload!) {
updateUser(id: $userId, input: { avatar: $file })
}
`
request('/api/graphql', UploadUserAvatar, {
userId: 1,
file: document.querySelector('input#avatar').files[0],
})
import { createReadStream } from 'fs'
import { request } from 'graphql-request'
const UploadUserAvatar = gql`
mutation uploadUserAvatar($userId: Int!, $file: Upload!) {
updateUser(id: $userId, input: { avatar: $file })
}
`
request('/api/graphql', UploadUserAvatar, {
userId: 1,
file: createReadStream('./avatar.img'),
})
It is possible with graphql-request
to use batching via the batchRequests()
function. Example available at examples/batching-requests.ts
import { batchRequests } from 'graphql-request'
;(async function () {
const endpoint = 'https://api.spacex.land/graphql/'
const query1 = /* GraphQL */ `
query ($id: ID!) {
capsule(id: $id) {
id
landings
}
}
`
const query2 = /* GraphQL */ `
{
rockets(limit: 10) {
active
}
}
`
const data = await batchRequests(endpoint, [
{ document: query1, variables: { id: 'C105' } },
{ document: query2 },
])
console.log(JSON.stringify(data, undefined, 2))
})().catch((error) => console.error(error))
It is possible to cancel a request using an AbortController
signal.
You can define the signal
in the GraphQLClient
constructor:
const abortController = new AbortController()
const client = new GraphQLClient(endpoint, { signal: abortController.signal })
client.request(query)
abortController.abort()
You can also set the signal per request (this will override an existing GraphQLClient signal):
const abortController = new AbortController()
const client = new GraphQLClient(endpoint)
client.request({ document: query, signal: abortController.signal })
abortController.abort()
In Node environment, AbortController
is supported since version v14.17.0.
For Node.js v12 you can use abort-controller polyfill.
import 'abort-controller/polyfill'
const abortController = new AbortController()
It's possible to use a middleware to pre-process any request or handle raw response.
Request middleware example (set actual auth token to each request):
function middleware(request: RequestInit) {
const token = getToken()
return {
...request,
headers: { ...request.headers, 'x-auth-token': token },
}
}
const client = new GraphQLClient(endpoint, { requestMiddleware: middleware })
It's also possible to use an async function as a request middleware. The resolved data will be passed to the request:
async function middleware(request: RequestInit) {
const token = await getToken()
return {
...request,
headers: { ...request.headers, 'x-auth-token': token },
}
}
const client = new GraphQLClient(endpoint, { requestMiddleware: middleware })
Response middleware example (log request trace id if error caused):
function middleware(response: Response<unknown>) {
if (response.errors) {
const traceId = response.headers.get('x-b3-traceid') || 'unknown'
console.error(
`[${traceId}] Request error:
status ${response.status}
details: ${response.errors}`
)
}
}
const client = new GraphQLClient(endpoint, { responseMiddleware: middleware })
By default GraphQLClient will throw when an error is received. However, sometimes you still want to resolve the (partial) data you received.
You can define errorPolicy
in the GraphQLClient
constructor.
const client = new GraphQLClient(endpoint, { errorPolicy: 'all' })
Allow no errors at all. If you receive a GraphQL error the client will throw.
Ignore incoming errors and resolve like no errors occurred
Return both the errors and data, only works with rawRequest
.
graphql
?graphql-request
uses methods exposed by the graphql
package to handle some internal logic. On top of that, for TypeScript users, some types are used from the graphql
package to provide better typings.
gql
template exported by graphql-request
?No. It is there for convenience so that you can get the tooling support like prettier formatting and IDE syntax highlighting. You can use gql
from graphql-tag
if you need it for some reason too.
graphql-request
, Apollo and Relay?graphql-request
is the most minimal and simplest to use GraphQL client. It's perfect for small scripts or simple apps.
Compared to GraphQL clients like Apollo or Relay, graphql-request
doesn't have a built-in cache and has no integrations for frontend frameworks. The goal is to keep the package and API as minimal as possible.
FAQs
Minimal GraphQL client supporting Node and browsers for scripts or simple apps.
The npm package graphql-request receives a total of 3,566,193 weekly downloads. As such, graphql-request popularity was classified as popular.
We found that graphql-request demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.