Jolt implementation
npm install @planningcenter/jolt-clientThis is a Typescript implementation of a Jolt client.
It is suitable for use in client-side browser environments.
If you're new to Jolt, we recommend starting with the Jolt Documentation. It covers the fundamental concepts and usage.
``js
// Configure a new Jolt Client
const client = new JoltClient("wss://example.com/socket", {
fetchAuthTokenFn: async () => "auth-token",
fetchSubscribeTokenFn: async (channel, connectionId) => "subscribe-token",
}, clientConfig);
// Subscribe to a channel.
// Note: The subscription token must have access to this channel, you can't just bind to any channel.
const subscription = client.subscribe("channel-name");
// Bind as my event handlers as you need to the channel.
subscription.bind("person.created", ({ event, data, channel }) => {})
subscription.bind("person.deleted", ({ event, data, channel }) => {})
subscription.bind("person.*", ({ event, data, channel }) => {})
subscription.bind("*", ({ event, data, channel }) => {})
// Unbind event handlers when you are done with them
// The most convenient way is to call the function that bind returned
const unbindSubscription = subscription.bind("person.edited", ({ event, data, channel }) => {})
unbindSubscription()
// Or unbind all and unsubscribe from the channel
subscription.unsubscribe()
// You can also unsubscribe from the client
client.unsubscribe("channel-name");
// And disconnect all-together if needed
client.disconnect();
`
#### JoltClient Constructor Parameters
- wssEndpoint: The WebSocket server endpoint.
- authorizationConfig: Configuration for authorization tokens.
- fetchAuthTokenFn: Function to fetch the authentication token.
- fetchSubscribeTokenFn: Optional function to fetch the subscription token. If you don't define it here, you will need to define it when subscribing to a channel.
- clientConfig: Optional configuration for the client.
- logToConsole: Whether to log messages to the console. Default is false.logLevel
- : The log level. Can be "none", "debug", "info", "warn", or "error". Default is "error" if logToConsole is false, otherwise "info".pingInterval
- : Interval in milliseconds to send ping messages. Default is 240000 (4 minutes).pingTimeout
- : Timeout in milliseconds for ping responses. Default is 2000 (2 seconds).retryTimeout
- : Function to calculate the retry timeout based on the previous timeout and retry count. Default is an exponential backoff starting at 3000ms.
This client is not tied to React in any way. So, the following is just an example of how you _could_ use this library with React hooks.
`js
// Maybe you want some kind of useJoltChannel.js hook
import { useEffect, useState } from "react";
import Jolt from "@planningcenter/jolt-client";
function useJoltChannel(channelName) {
const [joltChannel, setJoltChannel] = useState();
useEffect(() => {
const jolt = new Jolt("wss://your.endpoint.here", {
authToken: "your:auth:token:or:whatever",
fetchSubscribeTokenFn: async (channel, connectionId, { claims }) =>
"your:subscribe:token",
});
setJoltChannel(jolt.subscribe(channelName));
return () => jolt.unsubscribe(channelName);
}, [channelName]);
return joltChannel;
}
// Elsewhere...
function ComponentCommunicatingWithJolt() {
const channel = useJoltChannel("someChannel");
useEffect(() => {
if (!channel) return;
const handleMessage = ({ event, data, channel }) => doSomething(data);
return channel.bind("someEvent", handleMessage);
}, [channel]);
}
`
The Jolt client can be used with Turbo Streams in Rails applications. This works in conjunction with the pco-jolt gem.
- The attachTurboStreamListener function searches the DOM for elements and attaches listeners to them. This is useful for dynamically loaded Turbo Streams. These are best used to be created by jolt_turbo_stream_from from the pco-jolt Rails gem.
If you're using the pco-jolt gem, you can just add this to your application.js file (or as part of a React hook):`js
import { JoltClient, attachTurboStreamListener } from "@planningcenter/jolt-client";
const client = new JoltClient("wss://your.endpoint.here", {
fetchAuthTokenFn: async () => "auth-token",
}); // or reuse the existing client
attachTurboStreamListener(client);
`
`ts
const client = new JoltClient("wss://your.endpoint.here", {
autosubscribe: true
...
})
// and/or
client.subcribe("channelName", { autosubscribe: true })
`
By default, WebSocket subscriptions are established when you call subscribe and remain active until
you explicitly call unsubscribe.
However, if you set autosubscribe: true in your JoltClient configuration or when usingJoltClient#subscribe, subscriptions will automatically unsubscribe when all listeners are removed.
If a listener is later added to a closed subscription, it will automatically resubscribe.
This feature is particularly useful for managing multiple subscriptions across different parts of
your application. When listeners for a specific context are removed, the subscription will
intelligently unsubscribe—either keeping it active if there are other active listeners or closing
it entirely if no listeners remain.
Dev dependencies and scripts are definined in package.json.
Install development dependencies:
`sh`
npm ci
Run jest watch to run specs on changes:
`sh`
npm run watch
Aside from npm run watch, you can run the tests on demand with:
`sh`
npm run test
When you're ready to compile the Javascript module:
`sh`
npm run build
This will also run tests as part of the preBuild phase.
Time for a new release? First check these things:
1. npm run build` succeeds.
1. You've updated the CHANGELOG heading and package.json version.
Then, follow this notion document