@bloonio/chat-client-core
v0.1.0
Published
Framework-agnostic TypeScript core for the bloonio chat widget + SDKs. WebSocket protocol, REST client, signed-token handling, branding config types.
Maintainers
Readme
@bloonio/chat-client-core
Framework-agnostic TypeScript core for the bloonio chat widget and framework SDKs (Preact widget, Angular, future React/Vue). Zero runtime dependencies.
@bloonio/chat-widget (Preact embeddable, phase 9f)
@bloonio/chat-angular (Angular library, phase 9g)
@bloonio/chat-react (future, phase 15) ─── all depend on ──┐
@bloonio/chat-vue (future) │
▼
@bloonio/chat-client-core
(this package)What's in here
| Module | Surface |
|---|---|
| client.ts | ChatClient — REST wrapper for /fetch/widget-config, /create/visitor-session, /identify/visitor |
| ws.ts | WSClient — WebSocket wrapper with typed handlers, ping/pong heartbeat, exponential-backoff reconnect |
| protocol.ts | TS types for every inbound/outbound frame — mirrors bloonio_chat_relay/app/modules/ws_hub/protocol.py |
| config.ts | WidgetBootstrapConfig + request/response shapes for the REST endpoints |
| storage.ts | TokenStorage interface + localStorage-backed default (graceful fallback to in-memory in private mode) |
| errors.ts | Typed error hierarchy (BloonioChatError, …Network, …Server, …Auth, …Protocol) |
Quick start
import { ChatClient, WSClient } from '@bloonio/chat-client-core';
const client = new ChatClient({ baseUrl: 'https://chat-relay.example.com' });
// 1. Bootstrap (no session — just config so we can render the launcher)
const cfg = await client.fetchWidgetConfig({
tenantId: '019e4ae7-...',
widgetPublicKey: 'pk_...',
origin: window.location.origin,
});
// 2. Create a visitor session (returns a signed JWT)
const sess = await client.createVisitorSession({
tenantId: cfg.tenant_id,
widgetPublicKey: 'pk_...',
origin: window.location.origin,
});
// 3. Open the WebSocket
const ws = new WSClient(
{ baseUrl: 'https://chat-relay.example.com', visitorToken: sess.visitor_token },
{
onWelcome: (f) => console.log('welcome', f),
onMessage: (f) => console.log('msg', f),
onTyping: (f) => console.log('typing', f),
onError: (f) => console.error('proto error', f),
},
);
ws.connect();
// 4. Send a message
ws.send({ type: 'msg', client_msg_id: 'c1', content: 'Where is my order?' });Build + test
npm install
npm run build # tsup → dist/index.js (ESM) + index.cjs + index.d.ts
npm test # vitest, no-watch
npm run typecheck # tsc --noEmitDesign notes
- Zero runtime deps. Production bundle is whatever you write in
src/— tsup just transpiles + emits.d.ts. Consumer bundlers tree-shake naturally. - No framework primitives.
WSClientexposes plain callback handlers, not RxJS / signals / hooks. Each framework SDK wraps these into its idiom. - Protocol parity with the relay. Adding a new frame type means editing
both
src/protocol.tshere andbloonio_chat_relay/app/modules/ws_hub/protocol.pyon the Python side — one PR per change, kept lockstep. - Reconnect strategy. Exponential backoff (0.5s → 1s → 2s → 4s → 8s,
capped at 30s). Caps at
maxReconnectAttempts(default Infinity). Manualclose()suppresses reconnect; transport-level failures don't.
Related
bloonio_chat_relay/— the relay this client talks to (Python, FastAPI)bloonio_chat_api/docs/12_PAAS_CONVERSION_PLAN.md— full PaaS plan, this package is part of phase 9e
