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

snek-query

v0.0.114

Published

Powerful queryless GraphQL API client

Downloads

102

Readme

Snek-query

Snek-query is a simple and easy-to-use library for interacting with any GraphQL API. It abstracts away the complexities of manually constructing and sending GraphQL queries and mutations, providing a convenient and simplified interface for making these requests.

With Snek-query, you can quickly and easily fetch data from your GraphQL API and perform mutations such as creating or updating data. The library also handles authentication, error handling, and data parsing, allowing you to focus on writing the queries and mutations you need for your application.

Table of Contents

Installation

To install Snek-query, you can use npm:

npm install snek-query

or yarn

yarn add snek-query

Please note that this library requires Node.js version >=18

Usage

First, you need to generate the Query and Mutation object from your GraphQL schema by running the following command

yarn snek-query generate https://your-graphql-endpoint.com/graphql

To see all available options, you can run the command with the --help flag:

yarn snek-query generate --help

This command will generate a folder (by default named snek-query) that contains the generated file schema.generated.ts and an index.ts file.

The schema.generated.ts file contains the Query and Mutation objects that are generated based on the GraphQL schema of the endpoint provided to the command. The index.ts file contains an instance sq that is already configured with the schema.generated.ts and the options passed to the makeSnekQuery function when the yarn snek-query generate command was run.

Interact with the API

You can use this instance directly in your application by importing it from the generated snek-query folder. The sq object takes care of the boilerplate for you and provides convenient methods for making GraphQL queries and mutations.

To import the sq object:

import {sq} from './snek-query'

You can then use the sq object to make queries/mutations like this:

// Queries
const [bookTitles, bookTitlesError] = await sq.query(q => q.books.title)
if (bookTitlesError) {
  console.error(bookTitlesError)
} else {
  console.log(bookTitles)
}

const [shipIds, shipIdsError] = await sq.query(q => q.ships({limit: 10}).id)
if (shipIdsError) {
  console.error(shipIdsError)
} else {
  console.log(shipIds)
}

const [ages, agesError] = await sq.query(
  q => q.ship({id: 1}).members({first: 10}).age
)
if (agesError) {
  console.error(agesError)
} else {
  console.log(ages)
}

// Mutations
const [createdBook, createBookError] = await sq.mutate(q =>
  q.createBook({title: 'Book Title', author: 'Book Author'})
)
if (createBookError) {
  console.error(createBookError)
} else {
  console.log(createdBook)
}

Each function call to sq.query or sq.mutate returns an array of two values. The first value is the result of the query or mutation, and the second value is an error. If the query or mutation is successful, the second value will be undefined, otherwise it will be an array of GraphQLError objects, representing the errors that occurred.

Customizing the Snek-query instance

The sq object that is generated by the snek-query generate command has a default configuration. However, you can customize the behavior of the sq object by passing other options to the makeSnekQuery function.

import { makeSnekQuery } from 'snek-query'

const sq = makeSnekQuery({ Query, Mutation }, {
    apiURL: "https://api.spacex.land/graphql/",
    middlewares: [
        async ({context}) => {
          const token = await storage.get(AUTH_TOKEN_KEY)

          if (!token) return

          context.headers = {
            ...context.headers,
            Authorization: `JWT ${token}`
          }
        }
      ],
      onError: async ({graphQLErrors, networkError, operation, forward}) => {
        ... do something
        // forward request
      }
});

Snek-query storage

Snek-query also comes with a built-in, cross-platform key-value storage that can be used to store data in a way that is similar to using the localStorage API in the web, but works on Node.js and React Native environments as well.

You can use the storage object from snek-query to store and retrieve data in a way that is similar to using the localStorage API:

import {storage} from 'snek-query'

// set a value
await storage.set('key', 'value')

// get a value
const value = await storage.get('key')
console.log(value) // 'value'

// remove a value
await storage.remove('key')

The storage object has the following methods:

  • set(key: string, value: any): sets a value for the given key
  • get(key: string): retrieves the value for the given key
  • remove(key: string): removes the value for the given key
  • clear(): removes all stored values

It is important to note that the storage is asynchronous, so all the methods returns promises.

You can use this feature to store data such as authentication tokens or user preferences that need to be accessed across different parts of your application, without having to pass them around as props or using a global state management solution.

Network Status Utilities

Snek-query includes network status utilities that can be helpful when working with GraphQL APIs in various environments. These network status utilities are used internally by snek-query to handle network errors, but they can also be used in your own code to check the device's online status and subscribe to online/offline events.

Import Statements

Before using these utilities, you'll need to import them into your project:

import {isOnline, onOnline} from 'snek-query'

isOnline Function

The isOnline function can be used to check if the device is currently online. It provides a simple way to determine whether the device has internet connectivity.

async function checkOnlineStatus() {
  const online = await isOnline()
  if (online) {
    console.log('The device is online.')
  } else {
    console.log('The device is offline.')
  }
}

checkOnlineStatus()

onOnline Function

The onOnline function allows you to subscribe to online/offline events, making it easy to react to changes in network status. You can provide a callback function that will be called whenever the online status changes.

Example:

// Subscribe to online/offline events
const unsubscribe = onOnline(isOnline => {
  if (isOnline) {
    console.log('The device is online.')
  } else {
    console.log('The device is offline.')
  }
})

// Later, when you no longer need the subscription, unsubscribe
unsubscribe()

Please note that the onOnline function is designed to trigger events when the network status changes, so it won't provide the current network state on its initial call. It's best suited for reacting to network changes in your application.

Current limitations and workarounds

While snek-query is a powerful tool for interacting with APIs, there are a few limitations that you should be aware of. In this section, we will discuss one such limitation and its workaround.

Using enums

It is important to note that enums defined in schema.generated.ts are not directly compatible with the sq.query and sq.mutate functions. Instead, you should use the asEnumKey function to convert the enum to a compatible format.

Here is an example of what not to do:

import {sq} from './snek-query'

const [bookTitles, bookTitlesError] = await sq.query(
  q => q.books({orderBy: BookOrderByField.TITLE}).title
)

In the above example, BookOrderByField.TITLE will not work with sq.query as is. The correct way to use enums is to use the asEnumKey function to convert the enum to a compatible format, as shown in the example below:

import {asEnumKey} from 'snek-query'
import {sq} from './snek-query'

const [bookTitles, bookTitlesError] = await sq.query(
  q => q.books({orderBy: asEnumKey(null, 'TITLE')}).title
)

// or

const [bookTitles, bookTitlesError] = await sq.query(
  q => q.books({orderBy: asEnumKey(BookOrderByField, 'TITLE')}).title
)

Note that the asEnumKey function only works if the value passed to it is the actual string value of the key, and not the value itself. In other words, you should use the string value of the enum key as the argument for asEnumKey. If you use the value of the enum instead of the string value, the asEnumKey function may not work as expected.

Maintainers

Snek-query is actively maintained by:

Feel free to reach out to us with any questions or concerns.

Roadmap

  • Implement Pagination Hook
  • Optimize Query Performance (QueryOptimizer/Cache)
  • Enhance Query and Mutate Functionality with Built-in Array Support (e.g. .map, .sort, .find, .filter, .slice)
  • Handle Null Types with Ignoring or Placeholder Modes
  • Introduce Helper Functions:
    • all/resolve to retrieve all fields of a node (e.g. sq.query(q => all(q.userMe)))
    • interface to access fields by interface (e.g. interface(q.userMe, "InterfaceName") or q.userMe.INTERFACE)
    • alias to create a path alias (e.g. alias(q.userMe, "thisIsMe"))