npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

graphql-request-less-graphql

v0.1.0

Published

Minimal GraphQL client supporting Node and browsers for scripts or simple apps (without requiring [graphql](https://www.npmjs.com/package/graphql))

Downloads

2

Readme

graphql-request-less-graphql

Minimal GraphQL client supporting Node and browsers for scripts or simple apps (without requiring graphql)

GitHub Action npm version

Features

  • Most simple & lightweight GraphQL client
  • Promise-based API (works with async / await)
  • TypeScript support
  • Isomorphic (works with Node / browsers)

Install

npm add graphql-request graphql

Quickstart

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))

Usage

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))

Node Version Support

We only officially support LTS Node versions. We also make an effort to support two additional versions:

  1. The latest even Node version if it is not LTS already.
  2. The odd Node version directly following the latest even version.

You are free to try using other versions of Node (e.g. 13.x) with graphql-request but at your own risk.

Community

GraphQL Code Generator's GraphQL-Request TypeScript Plugin

A GraphQL-Codegen plugin that generates a graphql-request ready-to-use SDK, which is fully-typed.

Examples

Authentication via HTTP header

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))

TypeScript Source

Incrementally setting headers

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',
})

Set endpoint

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)

passing-headers-in-each-request

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)

Passing dynamic headers to the client

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)

Passing more options to 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))

TypeScript Source

Custom JSON serializer

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'
}

Using GraphQL Document variables

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))

Making a GET request

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))

GraphQL Mutations

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))

TypeScript Source

Error handling

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))

TypeScript Source

Using 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))

Cookie support for 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))

TypeScript Source

Using a custom fetch method

npm 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))

Receiving a raw response

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))

File Upload

Browser

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],
})

Node

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'),
})

TypeScript Source

Batching

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))

Cancellation

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()

Middleware

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 })

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 })

ErrorPolicy

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' })

None (default)

Allow no errors at all. If you receive a GraphQL error the client will throw.

Ignore

Ignore incoming errors and resolve like no errors occurred

All

Return both the errors and data, only works with rawRequest.

FAQ

Why do I have to install graphql?

You don't! However, by using this package you forgo the benefit of using gql from graphql-tag and all the benefits of graphql validation.

Do I need to wrap my GraphQL documents inside the 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.

What's the difference between 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.