npm package: @hpkv/websocket-client
Description: HPKV WebSocket client for Node.js
Author: HPKV Team
Latest version: 1.4.1

# HPKV WebSocket Client for Node.js

[![npm version](https://img.shields.io/npm/v/@hpkv/websocket-client.svg)](https://www.npmjs.com/package/@hpkv/websocket-client)
[![npm downloads](https://img.shields.io/npm/dm/@hpkv/websocket-client.svg)](https://www.npmjs.com/package/@hpkv/websocket-client)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./License)

This is the official Node.js client for the HPKV WebSocket API, providing high-performance access to HPKV's real-time key-value store capabilities.

For more details, refer to the [SDK Documentation Page](https://hpkv.io/docs/sdk-guides)

## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Subscription Client](#subscription-client)
- [Error Handling](#error-handling)
- [Request Throttling](#request-throttling)
  - [Key Throttling Features](#key-throttling-features)
  - [Configuring Throttling](#configuring-throttling)
  - [Monitoring Throttling Metrics](#monitoring-throttling-metrics)
- [Connection Management](#connection-management)
  - [Connection Features](#connection-features)
  - [Connection Lifecycle Events](#connection-lifecycle-events)
  - [Connection Configuration](#connection-configuration)
  - [Monitoring Connection State](#monitoring-connection-state)
- [Reference](#reference)
  - [Core Classes](#core-classes)
  - [Key Types and Interfaces](#key-types-and-interfaces)
- [Response Types](#response-types)
- [License](#license)

## Features

- WebSocket-based communication for low-latency operations
- Automatic reconnection with exponential backoff
- Support for key monitoring (pub-sub) for real-time updates
- Request throttling
- Support for atomic operations
- Range queries for efficient data retrieval
- Robust error handling and type safety

## Installation

```bash
npm install @hpkv/websocket-client
```

## Quick Start

```javascript
import { HPKVClientFactory } from '@hpkv/websocket-client';

// Create an API client for server-side operations
const apiClient = HPKVClientFactory.createApiClient(
  'your-api-key',
  'your-api-base-url',
);

// Connect to the HPKV service
await apiClient.connect();

// Store a value
await apiClient.set('user:123', { name: 'John', age: 30 });

// Retrieve a value
const response = await apiClient.get('user:123');
console.log(response.value); // '{"name":"John","age":30}'

// Update a value (JSON patch)
await apiClient.set('user:123', { city: 'New York' }, true);

// Delete a value
await apiClient.delete('user:123');

// Range query
const users = await apiClient.range('user:', 'user:~');
console.log(users.records); // Array of user records

// Atomic increment
const counter = await apiClient.atomicIncrement('visits:page1', 1);
console.log(counter.newValue); // Current counter value

// Close connection when done
await apiClient.disconnect();
```

## Subscription Client

For real-time updates on key changes:

```javascript
import { HPKVClientFactory } from '@hpkv/websocket-client';

// First generate a token to be used for connection to websocket with subscription to provided changes.
const tokenManager = new WebsocketTokenManager(HPKV_API_KEY, HPKV_API_BASE_URL);

// Subscribe to keys matching patterns (prefixes, suffixes, or regex)
const token = await tokenManager.generateToken({
        subscribePatterns: ['product:headphone:*', 'user:session:*'], // subscribe to changes matching these patterns
        accessPattern: `^(product|user):*$`, // to allow CRUD operations on product and user keys
      });

// Create a subscription client for real-time updates
const subscriptionClient = HPKVClientFactory.createSubscriptionClient(
  token,
  HPKV_API_BASE_URL,
);

// Connect to the service
await subscriptionClient.connect();

// Subscribe to changes in the subscribed keys/patterns
const subscriptionId = subscriptionClient.subscribe((notification) => {
  console.log(`Key ${notification.key} changed to ${notification.value}`);
  
  // Value is null if the key was deleted
  if (notification.value === null) {
    console.log(`Key ${notification.key} was deleted`);
  }
});

// This get operation will succeed as the key starts with 'product:'
await subscriptionClient.get('product:phone:modelA')

// This get operation will fail as the key does not start with 'product:'
await subscriptionClient.get('order:1') 

// Later, unsubscribe when no longer needed
subscriptionClient.unsubscribe(subscriptionId);

// Disconnect when done
await subscriptionClient.disconnect();
```

## Error Handling

All operations can throw exceptions for network issues, timeouts, or server errors:

```javascript
try {
  const result = await apiClient.get('nonexistent-key');
  console.log(result.value);
} catch (error) {
  if (error.code === 404) {
    console.error('Key not found');
  } else {
    console.error('Operation failed:', error.message);
  }
}
```

## Request Throttling

The HPKV WebSocket client includes a request throttling system to help manage request rates and prevent overwhelming the server.

### Key Throttling Features

- **Rate Limiting**: Enforces a maximum number of requests per second.
- **Exponential Backoff**: Handles 429 (Too Many Requests) responses with intelligent retry logic, reducing the request rate when signaled by the server.
- **Queue Management**: Queues requests when the rate limit is exceeded, processing them as slots become available according to the limit.
- **Configurable Limits**: Customize throttling behavior to match your application needs.

### Configuring Throttling

```javascript
const apiClient = HPKVClientFactory.createApiClient('your-api-key', 'your-api-base-url', {
  throttling: {
    enabled: true,       // Enable/disable throttling (default: true)
    rateLimit: 10        // Default rate limit in requests per second
  }
});

// Later, update throttling configuration
apiClient.updateThrottlingConfig({
  enabled: true,
  rateLimit: 20          // Increase rate limit to 20 requests per second
});
```

### Monitoring Throttling Metrics

```javascript
// Get detailed throttling metrics
const status = apiClient.getThrottlingStatus();
console.log(`Current allowed rate: ${status.metrics.currentRate} req/sec`);
console.log(`Queue length: ${status.metrics.queueLength}`);
```

The throttling system queues requests if they exceed the `currentRate`. When the server returns a 429 response, the client significantly reduces the `currentRate` and applies exponential backoff, gradually increasing the rate back towards the configured `rateLimit` once the backoff period expires.

## Connection Management

The HPKV WebSocket client implements robust connection management with automatic reconnection capabilities:

### Connection Features

- **Automatic Reconnection**: Handles network disruptions with exponential backoff
- **Connection Events**: Subscribe to connection lifecycle events
- **Connection Statistics**: Monitor connection health and performance
- **Configurable Retry Logic**: Customize reconnection behavior

### Connection Lifecycle Events

```javascript
// Subscribe to connection events
apiClient.on('connected', () => {
  console.log('Connected to HPKV service');
});

apiClient.on('disconnected', (details) => {
  console.log(`Disconnected: ${details.reason}`);
});

apiClient.on('reconnecting', (attempt) => {
  console.log(`Reconnection attempt ${attempt.attempt}/${attempt.maxAttempts}`);
});

apiClient.on('reconnectFailed', (error) => {
  console.error('Failed to reconnect after multiple attempts:', error.message);
});

apiClient.on('error', (error) => {
  console.error('Connection error:', error.message);
});
```

### Connection Configuration

```javascript
const apiClient = HPKVClientFactory.createApiClient('your-api-key', 'your-api-base-url', {
  // Reconnection settings
  maxReconnectAttempts: 5,                 // Maximum reconnection attempts
  initialDelayBetweenReconnects: 1000,     // Initial delay in ms
  maxDelayBetweenReconnects: 30000,        // Maximum delay in ms
});
```

### Monitoring Connection State

```javascript
// Get current connection statistics
const stats = apiClient.getConnectionStats();
console.log(`Connected: ${stats.isConnected}`);
console.log(`State: ${stats.connectionState}`);
console.log(`Reconnect attempts: ${stats.reconnectAttempts}`);
console.log(`Pending messages: ${stats.messagesPending}`);

// Log throttling info if enabled
if (stats.throttling) {
  console.log(`Throttling Rate: ${stats.throttling.currentRate} req/sec`);
  console.log(`Throttling Queue: ${stats.throttling.queueLength}`);
}
```

## Reference

### Core Classes

#### `HPKVClientFactory`

Factory class for creating API and subscription clients.

| Method | Description |
| ------ | ----------- |
| `createApiClient(apiKey, baseUrl, config?)` | Creates a client for server-side operations using an API key |
| `createSubscriptionClient(token, baseUrl, config?)` | Creates a client for subscription-based operations using a token |

#### `BaseWebSocketClient`

Abstract base class for WebSocket communication with the HPKV service.

| Method | Description |
| ------ | ----------- |
| `connect()` | Establishes a WebSocket connection |
| `disconnect(cancelPendingRequests?)` | Closes the WebSocket connection |
| `get(key, timeoutMs?)` | Retrieves a value from the store |
| `set(key, value, partialUpdate?, timeoutMs?)` | Stores or updates a value |
| `delete(key, timeoutMs?)` | Deletes a value |
| `range(key, endKey, options?, timeoutMs?)` | Performs a range query |
| `atomicIncrement(key, value, timeoutMs?)` | Performs an atomic increment operation |
| `on(event, listener)` | Registers an event listener |
| `off(event, listener)` | Removes an event listener |
| `getConnectionState()` | Returns the current connection state |
| `getConnectionStats()` | Returns statistics about the connection |
| `getThrottlingStatus()` | Returns throttling configuration and metrics (current rate, queue length) |
| `updateThrottlingConfig(config)` | Updates the throttling configuration |

#### `HPKVApiClient`

Client for performing CRUD operations with API key authentication.

- Extends `BaseWebSocketClient` with API key authentication
- Used for server-side operations with full read/write access

#### `HPKVSubscriptionClient`

Client for subscribing to real-time updates using token authentication.

| Method | Description |
| ------ | ----------- |
| `subscribe(callback)` | Subscribes to changes with the provided callback |
| `unsubscribe(callbackId)` | Unsubscribes a callback |

#### `WebsocketTokenManager`

Utility for generating authentication tokens for WebSocket connections.

| Method | Description |
| ------ | ----------- |
| `generateToken(config)` | Generates an authentication token for subscription access |

### Key Types and Interfaces

This section details key exported types and interfaces you'll work with when using the SDK.

#### `ConnectionConfig`

Configuration options for the WebSocket connection.

| Property | Type | Description |
| -------- | ---- | ----------- |
| `maxReconnectAttempts` | `number` | Maximum number of reconnection attempts |
| `initialDelayBetweenReconnects` | `number` | Initial delay between reconnection attempts (ms) |
| `maxDelayBetweenReconnects` | `number` | Maximum delay between reconnection attempts (ms) |
| `connectionTimeout` | `number` | Timeout for connection attempts (ms) |
| `throttling` | `ThrottlingConfig` | Configuration for request throttling |

#### `ThrottlingConfig`

Configuration for the throttling mechanism.

| Property | Type | Description |
| -------- | ---- | ----------- |
| `enabled` | `boolean` | Whether throttling is enabled |
| `rateLimit` | `number` | Maximum requests per second |

#### `HPKVTokenConfig`

Configuration for generating authentication tokens.

| Property | Type | Description |
| -------- | ---- | ----------- |
| `subscribePatterns` | `string[]` | Key patterns the token can subscribe to (supports wildcards, prefixes, suffixes, or regex) |
| `accessPattern` | `string` | Optional regex pattern for key access control |

#### `ConnectionState`

Enum representing the connection state.

| Value | Description |
| ----- | ----------- |
| `DISCONNECTED` | Not connected |
| `CONNECTING` | Connection in progress |
| `CONNECTED` | Successfully connected |
| `DISCONNECTING` | Disconnection in progress |

#### `ConnectionStats`

Interface representing connection statistics.

| Property | Type | Description |
| -------- | ---- | ----------- |
| `isConnected` | `boolean` | Whether the client is currently connected |
| `reconnectAttempts` | `number` | Number of reconnect attempts since the last successful connection |
| `messagesPending` | `number` | Number of messages awaiting a response |
| `connectionState` | `string` (`ConnectionState` enum) | Current state of the connection |
| `throttling` | `object \| null` | Throttling metrics if enabled (contains `currentRate`, `queueLength`) |

#### `HPKVResponse`

Union type for all possible response types from the HPKV service. Most responses may include an optional `messageId` (number, linking back to the request) and `code` (number, often an HTTP-like status code).

- **`HPKVGetResponse`**: Response for GET operations.
  ```typescript
  interface HPKVGetResponse {
    key: string;
    value: string | number;
    code?: number;
    messageId?: number;
  }
  ```

- **`HPKVSetResponse`**: Response for SET operations.
  ```typescript
  interface HPKVSetResponse {
    success: boolean;
    message?: string;
    code?: number;
    messageId?: number;
  }
  ```

- **`HPKVPatchResponse`**: Response for PATCH operations (partial updates). Typically similar to `HPKVSetResponse`.
  ```typescript
  interface HPKVPatchResponse {
    success: boolean;
    message?: string;
    code?: number;
    messageId?: number;
  }
  ```

- **`HPKVDeleteResponse`**: Response for DELETE operations.
  ```typescript
  interface HPKVDeleteResponse {
    success: boolean;
    message?: string;
    code?: number;
    messageId?: number;
  }
  ```

- **`HPKVRangeResponse`**: Response for RANGE operations.
  ```typescript
  interface HPKVRangeRecord {
    key: string;
    value: string | number;
  }
  interface HPKVRangeResponse {
    records: HPKVRangeRecord[];
    code?: number;
    messageId?: number;
  }
  ```

- **`HPKVAtomicResponse`**: Response for ATOMIC operations (e.g., increment).
  ```typescript
  interface HPKVAtomicResponse {
    newValue: number;
    success: boolean;
    code?: number;
    messageId?: number;
  }
  ```

- **`HPKVNotificationResponse`**: Data structure for key notifications in pub-sub subscriptions.
  ```typescript
  interface HPKVNotificationResponse {
    key: string;
    value: string | number | null; // Value is null if the key was deleted
  }
  ```

- **`HPKVErrorResponse`**: Structure of the error payload from the server, often wrapped by client-side exceptions.
  ```typescript
  interface HPKVErrorResponse {
    error: string;
  }
  ```