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

apollo-pusher-subscriptions

v1.0.1

Published

A modern, configurable Apollo Link for handling GraphQL subscriptions via Pusher. Built with TypeScript and designed for Laravel Lighthouse.

Readme

apollo-pusher-subscriptions

A modern, configurable Apollo Link for handling GraphQL subscriptions via Pusher. Built with TypeScript and designed for Laravel Lighthouse, but configurable for any GraphQL server that uses Pusher for real-time subscriptions.

✨ Features

  • 🚀 Modern Implementation - Clean Observable patterns, proper TypeScript support
  • ⚙️ Configurable - Works with Lighthouse out of the box, easily configurable for other GraphQL servers
  • 🔧 Type Safe - Full TypeScript support with proper interfaces
  • 🧹 Memory Safe - Proper cleanup of both Apollo and Pusher subscriptions
  • 📦 Lightweight - Zero dependencies beyond Apollo Client and Pusher JS
  • 🎯 Battle Tested - Used in production applications

📦 Installation

npm install apollo-pusher-subscriptions @apollo/client pusher-js rxjs
# or
yarn add apollo-pusher-subscriptions @apollo/client pusher-js rxjs
# or
pnpm add apollo-pusher-subscriptions @apollo/client pusher-js rxjs

🚀 Quick Start

With Laravel Lighthouse (Default)

import { ApolloClient, InMemoryCache, ApolloLink } from "@apollo/client/core";
import Pusher from "pusher-js";
import PusherLink from "apollo-pusher-subscriptions";

// Configure Pusher
const pusher = new Pusher("your-app-key", {
  cluster: "your-cluster",
  // ... other Pusher options
});

// Create the Pusher link
const pusherLink = new PusherLink({ pusher });

// Create Apollo Client
const client = new ApolloClient({
  link: ApolloLink.from([
    // ... other links (auth, error handling, etc.)
    pusherLink,
    httpLink, // Your HTTP link should come last
  ]),
  cache: new InMemoryCache(),
});

With Custom GraphQL Server

const pusherLink = new PusherLink({
  pusher,
  subscriptionPath: "extensions.subscriptions.channel", // Custom path
  eventName: "graphql-subscription", // Custom event name
  initialDataCondition: (data) => data.data !== null, // Custom condition
});

⚙️ Configuration Options

interface PusherLinkOptions {
  pusher: Pusher; // Required: Pusher client instance
  decompress?: (result: string) => GraphQLResponse; // Optional: Decompression function
  subscriptionPath?: string; // Optional: Path to subscription channel
  eventName?: string; // Optional: Pusher event name
  initialDataCondition?: (data: any) => boolean; // Optional: When to pass initial data
}

Configuration Details

| Option | Default | Description | | ---------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------- | | pusher | - | Required. Your configured Pusher client instance | | decompress | undefined | Function to decompress compressed subscription payloads | | subscriptionPath | 'lighthouse_subscriptions.channel' | Dot-notation path to find the subscription channel in response extensions | | eventName | 'lighthouse-subscription' | Name of the Pusher event to listen for | | initialDataCondition | (data) => data.data && Object.keys(data.data).length > 0 | Function to determine when to pass initial subscription data |

🏗️ Framework Examples

Laravel Lighthouse

// Default configuration works out of the box
const pusherLink = new PusherLink({ pusher });

Your Lighthouse GraphQL schema:

type Subscription {
  postUpdated(id: ID!): Post
    @subscription(class: "App\\GraphQL\\Subscriptions\\PostUpdated")
}

Hasura

const pusherLink = new PusherLink({
  pusher,
  subscriptionPath: "extensions.hasura.channel",
  eventName: "hasura-subscription",
});

Custom GraphQL Server

const pusherLink = new PusherLink({
  pusher,
  subscriptionPath: "extensions.subscriptions.pusher_channel",
  eventName: "subscription-update",
  initialDataCondition: (data) => Boolean(data.data),
});

💡 Usage Examples

Basic Subscription

import { gql } from "@apollo/client/core";

const SUBSCRIPTION = gql`
  subscription OnCommentAdded($postId: ID!) {
    commentAdded(postId: $postId) {
      id
      content
      user {
        name
      }
    }
  }
`;

// In your component/composable
const { data, loading, error } = useSubscription(SUBSCRIPTION, {
  variables: { postId: "1" },
});

With Compression Support

import pako from "pako"; // or your preferred compression library

const pusherLink = new PusherLink({
  pusher,
  decompress: (compressedResult: string) => {
    const decompressed = pako.inflate(compressedResult, { to: "string" });
    return JSON.parse(decompressed);
  },
});

Advanced Configuration

const pusherLink = new PusherLink({
  pusher,
  subscriptionPath: "meta.subscription.channel",
  eventName: "subscription-data",
  initialDataCondition: (data) => {
    // Only pass initial data if it's not empty and not an error
    return data.data && !data.errors && Object.keys(data.data).length > 0;
  },
  decompress: (result: string) => JSON.parse(atob(result)), // Base64 decode
});

🔧 Integration Patterns

With Authentication

const authLink = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      authorization: `Bearer ${getToken()}`,
    },
  });
  return forward(operation);
});

const client = new ApolloClient({
  link: ApolloLink.from([authLink, pusherLink, httpLink]),
  cache: new InMemoryCache(),
});

With Error Handling

import { ErrorLink } from "@apollo/client/link/error";

const errorLink = new ErrorLink(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, locations, path }) =>
      console.log(
        `GraphQL error: Message: ${message}, Location: ${locations}, Path: ${path}`
      )
    );
  }
  if (networkError) console.log(`Network error: ${networkError}`);
});

const client = new ApolloClient({
  link: ApolloLink.from([errorLink, pusherLink, httpLink]),
  cache: new InMemoryCache(),
});

Framework-Specific Examples

Vue 3 + Nuxt

// plugins/apollo.client.ts
export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig();

  const pusher = new Pusher(config.public.pusherKey, {
    cluster: config.public.pusherCluster,
  });

  const pusherLink = new PusherLink({ pusher });

  const client = new ApolloClient({
    link: ApolloLink.from([pusherLink, httpLink]),
    cache: new InMemoryCache(),
  });

  return {
    provide: {
      apollo: client,
    },
  };
});

React

import { ApolloProvider } from "@apollo/client";

const pusher = new Pusher(process.env.REACT_APP_PUSHER_KEY, {
  cluster: process.env.REACT_APP_PUSHER_CLUSTER,
});

const pusherLink = new PusherLink({ pusher });

const client = new ApolloClient({
  link: ApolloLink.from([pusherLink, httpLink]),
  cache: new InMemoryCache(),
});

function App() {
  return (
    <ApolloProvider client={client}>
      <YourApp />
    </ApolloProvider>
  );
}

🐛 Troubleshooting

Subscriptions Not Working

  1. Check Pusher Configuration: Ensure your Pusher credentials are correct
  2. Verify Subscription Path: Make sure subscriptionPath matches your server's response format
  3. Check Event Name: Verify the eventName matches what your server broadcasts
  4. Network Issues: Ensure Pusher can connect (check firewall, proxy settings)

Memory Leaks

The library automatically handles cleanup, but ensure you're properly unsubscribing:

const subscription = client.subscribe({ query: SUBSCRIPTION });

// Later, when component unmounts or subscription is no longer needed
subscription.unsubscribe();

TypeScript Issues

Make sure you have the correct types installed:

npm install --save-dev @types/pusher-js

🔍 Debugging

Enable debug mode for detailed logging:

// Enable Pusher logging
Pusher.logToConsole = true;

const pusher = new Pusher("key", {
  cluster: "cluster",
  enabledTransports: ["ws", "wss"],
});

📊 Performance Considerations

  • Connection Pooling: Reuse the same Pusher instance across multiple PusherLink instances
  • Subscription Cleanup: The library automatically handles cleanup, but always unsubscribe when components unmount
  • Batching: Consider using Apollo's batching for mutations while keeping subscriptions separate

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT License - see LICENSE file for details.

🙏 Acknowledgments

  • Built for the Laravel Lighthouse GraphQL community
  • Inspired by the need for a modern, type-safe Pusher integration
  • Thanks to the Apollo Client team for excellent GraphQL tooling