gin-websocket-client
v1.2.0
Published
TypeScript/JavaScript client for gin-websocket with fetch interface and event subscriptions
Readme
gin-websocket-client
TypeScript/JavaScript client for gin-websocket with a fetch-compatible API and elegant event subscriptions using pica-route.
Features
- fetch-compatible API - Drop-in replacement for
window.fetch()over WebSocket - Event subscriptions - Subscribe to server push events with pica-route patterns
- Pattern matching - Use
:paramsand*wildcards in subscription patterns - Auto-reconnect - Configurable automatic reconnection
- TypeScript - Full TypeScript support with type definitions
Installation
npm install gin-websocket-clientQuick Start
import { WsClient } from 'gin-websocket-client';
// Create client
const client = new WsClient('ws://localhost:8080/ws');
// Make requests using fetch API
const response = await client.fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Alice' })
});
const data = await response.json();
// Subscribe to server push events
client.subscribe('/events/user/created', (event) => {
console.log('New user:', new TextDecoder().decode(event.data));
});
// Pattern matching with params
client.subscribe('/notifications/:type', (event, params) => {
console.log(`Notification type: ${params.type}`);
});
// Wildcard subscriptions
client.subscribe('/events/*', (event) => {
console.log('Event:', event.route);
});API
WsClient
Constructor
const client = new WsClient(url: string, options?: WsClientOptions)Options:
interface WsClientOptions {
reconnect?: boolean; // Enable auto-reconnect (default: true)
reconnectInterval?: number; // Reconnect delay in ms (default: 1000)
maxReconnectAttempts?: number; // Max reconnect attempts (default: 5)
}Example:
const client = new WsClient('ws://localhost:8080/ws', {
reconnect: true,
reconnectInterval: 2000,
maxReconnectAttempts: 10
});Methods
fetch
client.fetch(url: string, init?: RequestInit): Promise<Response>Send an HTTP request over WebSocket. Returns a standard Response object.
Example:
// GET request
const response = await client.fetch('/api/users');
const users = await response.json();
// POST request
const response = await client.fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Bob' })
});
// With all fetch options
const response = await client.fetch('/api/data', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token'
},
body: JSON.stringify({ value: 42 })
});subscribe
client.subscribe(pattern: string, handler: (event: PushEvent, params: Record<string, string>) => void): voidSubscribe to server push events using pica-route patterns.
Pattern Syntax:
/exact/path- Exact match/users/:id- Match with parameter/events/*- Wildcard (matches anything under/events/)/users/:id/posts/:postId- Multiple parameters
Example:
// Exact match
client.subscribe('/notifications/alert', (event) => {
console.log('Alert:', new TextDecoder().decode(event.data));
});
// With parameters
client.subscribe('/users/:userId/update', (event, params) => {
console.log(`User ${params.userId} updated`);
});
// Wildcard
client.subscribe('/events/*', (event) => {
console.log('Event:', event.route);
});
// Complex patterns
client.subscribe('/rooms/:roomId/messages/:msgId', (event, params) => {
console.log(`Room: ${params.roomId}, Message: ${params.msgId}`);
});PushEvent:
interface PushEvent {
route: string; // The event route
data: Uint8Array; // The event payload
}unsubscribe
client.unsubscribe(pattern: string): voidRemove a subscription pattern.
Example:
client.unsubscribe('/notifications/alert');close
client.close(): voidClose the WebSocket connection and disable auto-reconnect.
Example:
client.close();Properties
connected
const isConnected: boolean = client.connectedCheck if the WebSocket is currently connected.
Example:
if (client.connected) {
console.log('Connected to server');
}Usage Examples
React Example
import { useEffect, useState } from 'react';
import { WsClient } from 'gin-websocket-client';
function App() {
const [client] = useState(() => new WsClient('ws://localhost:8080/ws'));
const [users, setUsers] = useState([]);
useEffect(() => {
// Subscribe to user events
client.subscribe('/events/user/*', (event) => {
fetchUsers();
});
fetchUsers();
return () => client.close();
}, []);
const fetchUsers = async () => {
const response = await client.fetch('/api/users');
const data = await response.json();
setUsers(data.users);
};
const createUser = async (name: string) => {
await client.fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name })
});
};
return (
<div>
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
<button onClick={() => createUser('New User')}>Add User</button>
</div>
);
}Vue Example
import { ref, onMounted, onUnmounted } from 'vue';
import { WsClient } from 'gin-websocket-client';
export default {
setup() {
const client = new WsClient('ws://localhost:8080/ws');
const messages = ref([]);
onMounted(() => {
client.subscribe('/messages/:roomId', (event, params) => {
const msg = JSON.parse(new TextDecoder().decode(event.data));
messages.value.push(msg);
});
});
onUnmounted(() => {
client.close();
});
const sendMessage = async (text: string) => {
await client.fetch('/api/messages', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text })
});
};
return { messages, sendMessage };
}
};Vanilla JavaScript Example
import { WsClient } from 'gin-websocket-client';
const client = new WsClient('ws://localhost:8080/ws');
// Handle notifications
client.subscribe('/notifications/:type', (event, params) => {
const notification = new TextDecoder().decode(event.data);
showNotification(params.type, notification);
});
// Load data
async function loadUsers() {
const response = await client.fetch('/api/users');
const data = await response.json();
displayUsers(data.users);
}
// Create user
document.getElementById('createBtn').addEventListener('click', async () => {
const name = document.getElementById('nameInput').value;
const response = await client.fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name })
});
if (response.ok) {
console.log('User created!');
}
});
loadUsers();Protocol
This client implements the gin-websocket binary protocol:
- Version: 0x01
- Message Types:
- 0x01: HTTP Request
- 0x02: HTTP Response
- 0x03: Server Push
All messages use big-endian byte order with length-prefixed strings.
License
MIT License
