Pingerchips LogoPingerchips
SDK Reference

Client SDK

The browser pub/sub client — pingerchips-js.

pingerchips-js (v3.0.0) is the browser/Node client. It wraps Phoenix Channels in a small pub/sub API and also ships the Chat and Spaces clients.

3.0.0 has no client-facing API changes — it's bumped to match the server SDK. The client forwards whatever token your authEndpoint returns, so the move to capability tokens is transparent. Upgrade pingerchips-js and pingerchips-js-server together.


Install

npm install pingerchips-js

ESM only ("type": "module" or .mjs). Node ≥ 18.


Initialise

import Pingerchips from 'pingerchips-js';

const client = new Pingerchips('YOUR_APP_KEY', options);

The socket connects immediately on construction.

Constructor options

OptionTypeDescription
endpointstringWebSocket URL. Default wss://queue.pingerchips.com/socket (prod), ws://localhost:4000/socket (dev).
authEndpointstringYour server route that signs private/presence joins.
authInfoobjectSent to authEndpoint in the auth_info field.
authHeadersobjectExtra headers on the auth request.
paramsobjectExtra params merged into the socket connect.
serializer / messageFormat"msgpack"Switch to MessagePack binary frames.
transportclassOverride the WebSocket transport.
reconnectAfterMs / rejoinAfterMsnumber | fnPhoenix backoff.

There is no cluster or host option, and the client never takes the App Secret.


Subscribe

// public
const lobby = await client.subscribe('lobby');

// private — needs authEndpoint (or an explicit `auth` token)
const inbox = await client.subscribe('private-user-123');

// presence — needs authEndpoint + user data on the server side
const room = await client.subscribe('presence-lobby');

// server-side filter (ExSift) — only matching messages reach this subscriber
const alerts = await client.subscribe('sensor-data', {
  filter: { 'data.level': { $eq: 'critical' } },
});

// delta compression — server sends diffs, client reconstructs
const prices = await client.subscribe('live-prices', { delta: 'fossil' });

// resume from a serial after a reload
const orders = await client.subscribe('orders', {
  after_serial: Number(localStorage.getItem('ordersSerial')) || undefined,
});

subscribe(name, options?) returns Promise<ChannelWrapper>. Re-subscribing to the same channel returns the existing wrapper.

options keyMeaning
filterExSift query — $eq $ne $gt $gte $lt $lte $in $nin over data.* / metadata.* paths
delta"fossil" | "xdelta3" | true — enable delta compression
after_serialReplay messages after this serial on join
authA pre-minted auth token, bypassing authEndpoint

ChannelWrapper

MethodDescription
bind(event, cb)thisListen for an event.
unbind(event, cb?)thisRemove one or all listeners for an event.
trigger(event, data)thisClient-side publish. Needs Enable Client Messages on the app; rate-limited. Add msg_serial: "<uuid>" to data for idempotent retries.
onRecoveryFailed(cb)thiscb({ reason: "position_expired" | "no_buffer", channel, afterSerial }) — the server couldn't replay after reconnect; re-fetch state from your own API.
leave()Unsubscribe.

The wrapper transparently handles message, message:delta, pingerchips:delta_compression_enabled and pingerchips:recovery_failed — you just bind('message', …) (or your event name).


Client methods

MethodDescription
connect() / disconnect()Manual socket control.
getLastSerial(channelName)number | nullLast serial seen — checkpoint it for cross-reload resume.
getSocketId()stringServer socket id. Throws if not connected.
getSocketIdAsync(timeoutMs?)Promise<string>Await a socket id.
getHttpEndpoint()stringHTTP base derived from the WS endpoint.
unsubscribe(channelName)Leave a channel by name.
authenticate(channelName)Manually fetch a capability token via authEndpoint.

registerPushToken() / unregisterPushToken() throw — push registration moved server-side. Use the server SDK's registerPushToken.

class Pingerchips has no connection-state event emitter (pc.on('connected') etc). It reconnects and re-joins automatically, passing after_serial so the server replays missed messages.


Example

import Pingerchips from 'pingerchips-js';

const client = new Pingerchips('YOUR_APP_KEY', {
  authEndpoint: '/pingerchips/auth',
  authInfo: { token: sessionToken },
});

const alerts = await client.subscribe('sensor-data', {
  filter: { 'data.severity': { $gte: 2 } },
});
alerts.bind('message', (data) => console.log('Alert:', data));

const room = await client.subscribe('presence-lobby');
room.bind('user-joined', ({ user_info }) => addToOnlineList(user_info));
room.bind('user-left', ({ user_info }) => removeFromOnlineList(user_info));
room.trigger('chat-message', { text: 'Hello!' });

@pingerchips/ai (Vercel AI SDK)

For AI chat UIs, @pingerchips/ai gives you a useChat()-compatible transport with resumable token streams:

npm install @pingerchips/ai
'use client';
import { useChat } from '@ai-sdk/react';
import { createChatTransport, createClientSession } from '@pingerchips/ai/vercel';

const session = createClientSession({
  appKey: 'YOUR_APP_KEY',
  channelName: threadId,
  clientId: 'user-42',
  authEndpoint: '/pingerchips/auth',
});

export function Chat() {
  const { messages, sendMessage } = useChat({
    transport: createChatTransport(session),
  });
  // …
}

It also exports createAgentSession for the server side and a React ClientSessionProvider / useClientSession. See the chat quickstart.


Python

The pingerchips Python package is agent-only — it has no pub/sub client, no subscribe, no presence. For pub/sub from Python, call the HTTP trigger API. For chat agents, see the Agent SDK.


Next steps

On this page