https://github.com/cbschuld/valkey-pubsub
A lightweight, TypeScript-native Pub/Sub implementation designed for use with Mercurius GraphQL, built on top of Valkey (Redis-compatible).
https://github.com/cbschuld/valkey-pubsub
Last synced: 3 months ago
JSON representation
A lightweight, TypeScript-native Pub/Sub implementation designed for use with Mercurius GraphQL, built on top of Valkey (Redis-compatible).
- Host: GitHub
- URL: https://github.com/cbschuld/valkey-pubsub
- Owner: cbschuld
- License: mit
- Created: 2025-03-22T19:56:10.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2025-03-22T20:27:04.000Z (3 months ago)
- Last Synced: 2025-03-22T20:29:27.530Z (3 months ago)
- Language: TypeScript
- Size: 0 Bytes
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# valkey-pubsub
A lightweight, TypeScript-native Pub/Sub implementation designed for use with [Mercurius GraphQL](https://github.com/mercurius-js/mercurius), built on top of Valkey (Redis-compatible).
Supports broadcasting messages to multiple listeners and enables easy event-driven design for GraphQL subscriptions or internal messaging systems.
---
## Features
- ๐ **Broadcast-style delivery**: All listeners receive each message
- โก **Fast and simple API**: Push, subscribe, destroy
- โ **Compatible with Mercurius** PubSub interface
- ๐งช **Tested with Jest**
- ๐งฑ **Type-safe and modular** โ written in pure TypeScript---
## Installation
```bash
pnpm add valkey-pubsub
```## Usage
### Create the PubSub instance
```typescript
import ValkeyPubSub, { PubSubGenericQueue } from "valkey-pubsub";const pubsub = await ValkeyPubSub.create({
addresses: [{ host: "localhost", port: 6379 }],
clusterMode: false,
});
```### Subscribe to a topic
```typescript
const queue = new PubSubGenericQueue();await pubsub.subscribe("my-topic", queue);
queue.onItem((message) => {
console.log("Received:", message);
});
```### Publish a message
```typescript
await pubsub.publish({
topic: "my-topic",
payload: { hello: "world" },
});
```## Usage with Mercurius
The original/driving force for the design was the [subscription models for Mercurius](https://mercurius.dev/#/docs/subscriptions)
```typescript
const pubsub = await ValkeyPubSub.create();fastify.decorate("pubsub", pubsub);
fastify.register(mercurius, {
schema,
resolvers: await resolvers,
loaders: await loaders,
context: async (request: FastifyRequest) => {
return {
request,
db: server.db,
valkey: server.valkey,
pubsub: server.pubsub,
logger: server.log,
} as ServerDecorators;
},
subscription: {
context: async (_server, request) => {
return {
request,
db: server.db,
valkey: server.valkey,
pubsub: server.pubsub,
logger: server.log,
} as ServerDecorators;
},
pubsub: server.pubsub,
},
graphiql: false, // โน๏ธ cannot use in place with helmet
allowBatchedQueries: true,
path: "/graphql", // ๐ Restricts GraphQL to this endpoint
prefix: "/",
});
```## API
### ValkeyPubSub
#### `ValkeyPubSub.create(config): Promise`
Creates a PubSub instance.
Config options:
- addresses: Array of { host, port } objects (defaults to Valkey on localhost:6379)
- protocol: 'RESP2' or 'RESP3' (default: 'RESP3')
- clusterMode: true or false (default: false)#### `pubsub.subscribe(topic, queue)`
- Subscribes a queue to a topic. Every published message will be pushed to the queue and delivered to all its listeners.
#### `pubsub.publish({ topic, payload }, callback?)`
- Publishes a message to the specified topic. Payload will be stringified before being sent.
#### `pubsub.cleanup()`
- Cleans up all open connections and subscriptions.
### PubSubGenericQueue
#### `PubSubGenericQueue`
A generic in-memory delivery queue that stores items and allows multiple listeners.
Methods:
- `push(value: T)`: Pushes a value onto the queue
- `onItem(callback: (value: T) => void)`: Registers a callback for new items
- `isEmpty()`: Returns true if the queue is empty
- `size()`: Returns the current number of pending items
- `destroy()`: Destroys the queue and runs any registered close callbacks## License
MIT ยฉ Chris Schuld
## Contact
- **Email** - twitter handle @ gmail.com
- **X** - @cbschuld## Contributing
Yes, thank you! Please update the docs and tests and add your name to the package.json file.