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

pusher-zod

v0.0.7

Published

pusher with typesafety using zod to parse the data

Downloads

8

Readme

Pusher-Zod

Pusher-Zod is a TypeScript package designed to enhance type safety for both server and client implementations when using Pusher (or Soketi). By integrating the powerful Zod library for runtime type validation, Pusher-Zod ensures that your Pusher event data adheres to the expected types, reducing the risk of runtime errors and providing a more robust development experience.

Installation

To install Pusher-Zod, use your package manager of choice:

npm install pusher-zod zod
# or
yarn add pusher-zod zod
# or
pnpm instal pusher-zod zod

Ressources

New methods added to the Pusher server and client instances

Client

instead of using subscribe you should use joinChannel. The channelID can be any string you want. The channelName must be one of the channels defined in the setup object :

client.joinChannel(channelName: string, channelID: string): Channel;
// with subscribe :
client.subscribe("channelName_channelID");

same logic for unsubscribe you should use leaveChannel:

client.leaveChannel(channelName: string, channelID: string): void;
// with unsubscribe :
client.unsubscribe("channelName_channelID");

When joining a channel with joinChannel you can now listen to events using the listen method. The event name must be one of the events defined in the setup object :

channel.listen("eventName", (data) => {});
// with bind but no typesafety :
channel.bind("eventName", (data) => {});

Server

instead of using trigger you should use invoke. The channelID can be any string you want. The channelName must be one of the channels defined in the setup object :

pusherServer.invoke(
  channelName: string,
  channelID: string | string[],
  eventName: string,
  data: any
);
// with trigger :
pusherServer.trigger("channelName_channelID", "eventName", data);

Even through bind/subcribe/unsubscribe or trigger are still available they are not type-safe and should not be used. Instead you should use listen/joinChannel/leaveChannel

Usage

First create a setup object that defines your Pusher channels and events with Zod schemas:

import pusherZod from "pusher-zod";
import { z } from "zod";

const setup = {
  chat: {
    message: z.object({
      user: z.string(),
      text: z.string(),
    }),
    messageDeleted: z.object({
      user: z.string(),
      messageId: z.string(),
    }),
  },
  // Add more channels and events as needed
};

// Optional : Define user events

const userEvents = {
  typing: z.object({
    user: z.string(),
  }),
  notification: z.object({
    user: z.string(),
    text: z.string(),
  }),
  booleanEvents: z.boolean(),
  numberEvents: z.number(),
  // Add more events as needed
};

// Export the client and server and import them where you need them
export const { TypeSafePusherClient, TypeSafePusherServer } = pusherZod({
  setup,
  userEvents, // optional
  channel_id_separator: "_", // Optional: Choose your own separator. For example, a channel could be called 'chat_conversationID'
});

Then create a Pusher client instance using the TypeSafePusherClient class. See the PusherJS docs for more information

import { TypeSafePusherClient } from "./pusher-zod-setup";

// For the options check the pusher-js docs
const Client = new TypeSafePusherClient({
    "app_key", // your app key
    // ...your options
})

// Subscribe to a channel. You will get a type error if you try to join a channel that is not defined. The ID can be any value you want.
const channel = Client.joinChannel("chat", "conversationID");

// listen to an event
channel.listen("message", (data) => {
  // data is parsed and validated using Parse from Zod
  console.log(data.user, data.text);
});

// user events are also type-safe
 channel.user.bind("typing", (data) => {
  // data is parsed and validated using Parse from Zod
  console.log(data.user);
});

Then create a Pusher server instance using the TypeSafePusherServer class:

import { TypeSafePusherServer } from "./pusher-zod-setup";

// For the options check the pusher-js docs
const pusherServer = new TypeSafePusherServer({
  appId: "YOUR_PUSHER_APP_ID",
  key: "YOUR_PUSHER_KEY",
  secret: "YOUR_PUSHER_SECRET",
  cluster: "YOUR_PUSHER_CLUSTER",
});

//  Use the invoke method for a type-safe way to trigger events

await pusherServer.invoke("channelName", "channelID", "event", {
  user: "user",
  text: "text",
});

// example:

await pusherServer.invoke("chat", "conversation1", "message", {
  user: "user",
  text: "text",
});

// Invoke like trigger also support multiple channels but instead you need to pass multiple channel ids

await pusherServer.invoke(
  "chat",
  ["conversation1", "conversation2", "conversation3"],
  "message",
  {
    user: "user",
    text: "text",
  }
);
// sendToUser method is also now typesafe

await pusherServer.sendToUser(
  "userID",
  "event",
  "data matching the event schema"
);

// example:

await pusherServer.sendToUser("1", "typing", {
  user: "random username",
});

Features

  • Type-Safe Event Data: Ensure that event data sent and received through Pusher adheres to predefined TypeScript types.
  • Server and Client Integration: Apply type safety both on the server and client sides for a seamless end-to-end development experience.
  • Zod Integration: Leverage the Zod library for runtime type validation, making it easy to define and enforce data schemas.

Roadmap

  • [x] Type-safe event data
  • [x] Server and client integration
  • [x] Zod integration
  • [ ] Support for presence channels
  • [ ] Support for private channels
  • [ ] Add choice between safeParse and parse
  • [ ] Type-safe user data
  • [ ] Retrieve existing private channels and presence channels names on the server side
  • [ ] Add tests

Contributing

Feel free to contribute to Pusher-Zod by opening issues or pull requests on the GitHub repository.

License

Pusher-Zod is licensed under the MIT License.