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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@graphql-live/client

v0.1.9

Published

The client part of the GraphQLive package

Readme

@graphql-live/client

⚠ WARNING: Still under development.

Very tiny library to send live queries to a compatible GraphQL server (@graphql-live/server) using the @live directive and automatically get updates when fresh data is available. Under the hood, the client uses Socket.IO to communicate and receives JSON patches to perform surgical updates of previous results (side note : you don't have to think about it), thus optimizing bandwidth usage.

Of course, it also supports standard queries and mutations (subscriptions might come in the futur).

Install

yarn add @graphql-live/client

Usage

There are two ways to use this library :

  • As a standalone, or
  • As an add-on to your favorite GraphQL client library (Apollo, urql, etc.).

As a standalone

You first have to create a client :

import { createClient } from "@graphql-live/client";

const client = createClient({
  url: "http://localhost:8080"
});

This establishes a socket connection with the server at the given url. You can then execute (and subscribe to) a GraphQL operation using the Observable pattern by calling client.execute :

const operation = {
  operation: `
    query($id: ID!) @live {
      getUser(id: $id) {
        id
        name
        job
      }
    }
  `,
  variables: {
    id: "8dd870"
  }
};

// Option 1, by hand :
const observable = {
  subscribe: observer => ({
    unsubscribe: client.execute(operation, observer)
  })
};

// Option 2, with RxJS (could be another library as long as it implements the Observable pattern) :
const observable = Rx.Observable.create(observer =>
  client.execute(operation, observer)
);

// Then subscribe to results (this also sends the operation to the server) :
const subscription = observable.subscribe({
  next: result => doSomethingWith(result),
  complete: () => doAnotherThing()
});

// ...Finally, when you're no more interested in updates :
subscription.unsubscribe();

(Take note of the @live directive)

As an add-on

Most GraphQL client libraries support add-on systems (Apollo's links, urql's exchanges, etc.). Currently, @graphql-live/client ships with two such add-ons :

  1. LiveLink for Apollo :

    import { ApolloClient, InMemoryCache } from "@apollo/client";
    import { LiveLink } from "@graphql-live/client/dist/apollo";
    
    const client = new ApolloClient({
      cache: new InMemoryCache(),
      link: new LiveLink({
        url: "http://localhost:8080"
      })
    });
  2. liveExchange for urql :

    import { createClient, dedupExchange } from "urql";
    import { cacheExchange } from "@urql/exchange-graphcache";
    import { liveExchange } from "@graphql-live/client/dist/urql";
    
    const client = createClient({
      url: "http://localhost:8080",
      exchanges: [
        dedupExchange,
        cacheExchange(),
        liveExchange({
          url: "http://localhost:8080"
        })
      ]
    });

Custom context

You can add a custom context callback to your client config. It will be called right before an operation is sent to the server and it's return value can be used server-side to generate custom resolver context. This might typically be used to pass auth tokens, but really it could be any valid JSON.

const client = createClient({
  url: "http://localhost:8080",
  context() {
    return auth().currentUser.token;
  }
});

Note: createClient, LiveLink and liveExchange all accept the same options.

Custom path

You can pass any valid Socket.IO client options to the live query client, including a custom path :

const client = createClient({
  url: "http://localhost:8080",
  socketOptions: {
    path: "/api"
  }
});

API

createClient

declare function createClient<TContext = any>(
  options?: ClientOptions<TContext>
): {
  socket: Socket;
  destroy: () => void;
  execute: (operation: Operation, observer: ResultObserver) => () => void;
};

When you create a client, what you actually get back is an object containing the active socket, a destroy callback to release all listeners and disconnect the socket, and the execute function seen above.

LiveLink

declare class LiveLink<TContext = any> extends ApolloLink {
  constructor(options?: ClientOptions<TContext>);
}

liveExchange

declare function liveExchange<TContext = any>(
  options?: ClientOptions<TContext>
): Exchange;

Types

type ClientOptions<TContext = any> = {
  url?: string;
  socketOptions?: Partial<ManagerOptions & SocketOptions>;
  context?(payload: ContextPayload): TContext | Promise<TContext>;
};

type ContextPayload = {
  socket: Socket;
  operation: Operation;
};

type ResultObserver = {
  next?(value: ExecutionResult): void;
  error?(error: any): void;
  complete?(): void;
};

type Operation = {
  operation: string;
  operationName?: string | null;
  variables?: Record<string, any>;
};