Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

awesome-graphql-client

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

awesome-graphql-client

GraphQL Client with file upload support for NodeJS and browser

  • 2.1.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
4.2K
decreased by-24.56%
Maintainers
1
Weekly downloads
 
Created
Source
Logo

CI/CD npm version Codecov

Awesome GraphQL Client

GraphQL Client with file upload support for NodeJS and browser

Features

  • 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

Install

npm install awesome-graphql-client

Quick Start

Browser

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

NodeJS

NodeJS 20
const { openAsBlob } = require('node:fs')
const { AwesomeGraphQLClient } = require('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))
NodeJS 18
const { createReadStream, statSync } = require('node:fs')
const path = require('node:path')
const { Readable } = require('node:stream')
const { AwesomeGraphQLClient } = require('awesome-graphql-client')

class StreamableFile extends Blob {
  constructor(filePath) {
    const { mtime, size } = statSync(filePath)

    super([])

    this.name = path.parse(filePath).base
    this.lastModified = mtime.getTime()
    this.#filePath = filePath

    Object.defineProperty(this, 'size', {
      value: size,
      writable: false,
    })
    Object.defineProperty(this, Symbol.toStringTag, {
      value: 'File',
      writable: false,
    })
  }

  stream() {
    return Readable.toWeb(createReadStream(this.#filePath))
  }
}

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

client
  .request(UploadUserAvatar, { file: new StreamableFile('./avatar.png'), userId: 10 })
  .then(data => console.log(data.updateUser.id))
  .catch(error => console.log(error))

Table of Contents

API

AwesomeGraphQLClient

Usage:

import { AwesomeGraphQLClient } from 'awesome-graphql-client'
const client = new AwesomeGraphQLClient(config)

config properties

  • endpoint: string - The URL to your GraphQL endpoint (required)
  • fetch: Function - Fetch polyfill
  • fetchOptions: object - Overrides for fetch options
  • FormData: object - FormData polyfill
  • 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 methods

  • client.setFetchOptions(fetchOptions: FetchOptions): Sets fetch options. See examples below
  • client.getFetchOptions(): Returns current fetch options
  • client.setEndpoint(): string: Sets a new GraphQL endpoint
  • client.getEndpoint(): string: Returns current GraphQL endpoint
  • client.request(query, variables?, fetchOptions?): Promise<data>: Sends GraphQL Request and returns data or throws an error
  • client.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.

GraphQLRequestError

instance fields

  • message: string - Error message
  • query: string - GraphQL query
  • variables: string | undefined - GraphQL variables
  • response: Response - response returned from fetch
  • fieldErrors: GraphQLFieldError[] - GraphQL field errors

Examples

Typescript

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

Typescript with TypedDocumentNode (even better!)

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

Error Logging

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

GraphQL GET Requests

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

GraphQL Tag

Approach #1: Use formatQuery

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

Approach #2: Use fake graphql-tag

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

Approach #3: Use TypedDocumentNode instead

Perfect for Typescript projects. See example above

Cookies in NodeJS

const { AwesomeGraphQLClient } = require('awesome-graphql-client')
const fetchCookie = require('fetch-cookie')

const client = new AwesomeGraphQLClient({
  endpoint: 'http://localhost:8080/graphql',
  fetch: fetchCookie(globalThis.fetch),
})

Custom isFileUpload Predicate

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

More Examples

https://github.com/lynxtaa/awesome-graphql-client/tree/master/examples

Keywords

FAQs

Package last updated on 15 Oct 2024

Did you know?

Socket

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.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc