UNPKG

@hivellm/synap

Version:

Official TypeScript/JavaScript SDK for Synap - High-Performance In-Memory Key-Value Store & Message Broker

806 lines (792 loc) 21.6 kB
import { Observable } from 'rxjs'; /** * Synap client configuration options */ interface SynapClientOptions { /** Synap server URL (default: http://localhost:15500) */ url?: string; /** Request timeout in milliseconds (default: 30000) */ timeout?: number; /** Enable request/response logging (default: false) */ debug?: boolean; /** Authentication options */ auth?: AuthOptions; /** Retry configuration */ retry?: RetryOptions; } /** * Authentication options */ interface AuthOptions { /** Authentication type */ type: 'basic' | 'api_key'; /** Username (for Basic Auth) */ username?: string; /** Password (for Basic Auth) */ password?: string; /** API Key (for Bearer Token auth) */ apiKey?: string; } /** * Retry configuration */ interface RetryOptions { /** Maximum number of retry attempts (default: 3) */ maxRetries?: number; /** Initial retry delay in milliseconds (default: 1000) */ retryDelay?: number; /** Exponential backoff multiplier (default: 2) */ backoffMultiplier?: number; } /** * Key-Value SET options */ interface SetOptions { /** Time-to-live in seconds */ ttl?: number; } /** * Key-Value statistics */ interface KVStats { total_keys: number; total_memory_bytes: number; operations: { gets: number; sets: number; dels: number; hits: number; misses: number; }; hit_rate: number; } /** * SCAN result */ interface ScanResult { keys: string[]; count: number; } /** * Queue configuration */ interface QueueConfig { /** Maximum queue depth */ max_depth?: number; /** ACK deadline in seconds */ ack_deadline_secs?: number; /** Default max retries */ default_max_retries?: number; /** Default priority (0-9) */ default_priority?: number; } /** * Queue message */ interface QueueMessage { /** Unique message identifier */ id: string; /** Message payload (base64 or raw bytes) */ payload: Uint8Array; /** Priority (0-9, where 9 is highest) */ priority: number; /** Number of retry attempts */ retry_count: number; /** Maximum retries allowed */ max_retries: number; /** Custom headers */ headers?: Record<string, string>; } /** * Publish message options */ interface PublishOptions { /** Message priority (0-9, default: 5) */ priority?: number; /** Maximum retry attempts (default: 3) */ max_retries?: number; /** Custom message headers */ headers?: Record<string, string>; } /** * Queue statistics */ interface QueueStats { depth: number; consumers: number; published: number; consumed: number; acked: number; nacked: number; dead_lettered: number; } /** * Consumer options for reactive queue consumption */ interface QueueConsumerOptions { /** Queue name to consume from */ queueName: string; /** Consumer identifier */ consumerId: string; /** Polling interval in milliseconds (default: 1000) */ pollingInterval?: number; /** Maximum concurrent messages to process (default: 1) */ concurrency?: number; /** Auto-acknowledge messages on success (default: true) */ autoAck?: boolean; /** Auto-nack messages on error (default: true) */ autoNack?: boolean; /** Requeue on nack (default: true) */ requeueOnNack?: boolean; } /** * Processed message with metadata */ interface ProcessedMessage<T = any> { /** Original queue message */ message: QueueMessage; /** Decoded payload */ data: T; /** Acknowledge the message */ ack: () => Promise<void>; /** Negative acknowledge the message */ nack: (requeue?: boolean) => Promise<void>; } /** * Event Stream event */ interface StreamEvent { /** Event offset in stream */ offset: number; /** Event name/type */ event: string; /** Event data */ data: any; /** Event timestamp */ timestamp?: string; } /** * Stream publish options */ interface StreamPublishOptions { /** Custom metadata */ metadata?: Record<string, string>; } /** * Stream consumer options for reactive consumption */ interface StreamConsumerOptions { /** Room name to consume from */ roomName: string; /** Subscriber identifier */ subscriberId: string; /** Start offset (default: 0) */ fromOffset?: number; /** Polling interval in milliseconds (default: 1000) */ pollingInterval?: number; } /** * Stream room statistics */ interface StreamStats { /** Maximum offset in stream */ max_offset: number; /** Number of subscribers */ subscribers: number; /** Total events published */ total_events: number; /** Total events consumed */ total_consumed: number; /** Room name */ room: string; /** Created timestamp */ created_at: number; /** Last activity timestamp */ last_activity: number; } /** * Processed stream event with metadata */ interface ProcessedStreamEvent<T = any> { /** Event offset */ offset: number; /** Event name */ event: string; /** Decoded event data */ data: T; /** Event timestamp */ timestamp?: string; } /** * Pub/Sub message */ interface PubSubMessage<T = any> { /** Topic the message was published to */ topic: string; /** Message data */ data: T; /** Message timestamp */ timestamp?: string; /** Message ID */ id?: string; } /** * Pub/Sub publish options */ interface PubSubPublishOptions { /** Message priority */ priority?: number; /** Custom headers */ headers?: Record<string, string>; } /** * Pub/Sub subscriber options for reactive consumption */ interface PubSubSubscriberOptions { /** Topics to subscribe to (supports wildcards: user.*, *.created) */ topics: string[]; /** Subscriber identifier */ subscriberId?: string; /** Auto-reconnect on disconnect (default: true) */ autoReconnect?: boolean; /** Reconnect interval in ms (default: 1000) */ reconnectInterval?: number; } /** * Processed pub/sub message with metadata */ interface ProcessedPubSubMessage<T = any> { /** Topic */ topic: string; /** Decoded message data */ data: T; /** Message timestamp */ timestamp?: string; /** Message ID */ id?: string; } /** * Synap error class */ declare class SynapError extends Error { code?: string | undefined; statusCode?: number | undefined; requestId?: string | undefined; constructor(message: string, code?: string | undefined, statusCode?: number | undefined, requestId?: string | undefined); } /** * Network error (connection failed) */ declare class NetworkError extends SynapError { originalError?: Error | undefined; constructor(message: string, originalError?: Error | undefined); } /** * Timeout error (request took too long) */ declare class TimeoutError extends SynapError { timeoutMs: number; constructor(message: string, timeoutMs: number); } /** * Server error (server returned error response) */ declare class ServerError extends SynapError { constructor(message: string, statusCode?: number, requestId?: string); } /** * JSON-serializable value */ type JSONValue = string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue; }; /** * Synap TypeScript SDK - Base Client * * Core HTTP client for StreamableHTTP protocol communication. */ /** * Base HTTP client for Synap server communication */ declare class SynapClient { private readonly baseUrl; private readonly timeout; private readonly debug; private readonly auth?; constructor(options?: SynapClientOptions); /** * Send a command to the Synap server using StreamableHTTP protocol */ sendCommand<T = any>(command: string, payload?: Record<string, any>): Promise<T>; /** * Ping the server to check connectivity */ ping(): Promise<boolean>; /** * Get server health status */ health(): Promise<{ status: string; service: string; version: string; }>; /** * Close the client (cleanup) */ close(): void; } /** * Synap TypeScript SDK - Key-Value Store Module * * Provides key-value operations using the StreamableHTTP protocol. */ /** * Key-Value Store client */ declare class KVStore { private client; constructor(client: SynapClient); /** * Set a key-value pair */ set(key: string, value: JSONValue, options?: SetOptions): Promise<boolean>; /** * Get a value by key */ get<T = JSONValue>(key: string): Promise<T | null>; /** * Delete a key */ del(key: string): Promise<boolean>; /** * Check if a key exists */ exists(key: string): Promise<boolean>; /** * Increment a numeric value */ incr(key: string, amount?: number): Promise<number>; /** * Decrement a numeric value */ decr(key: string, amount?: number): Promise<number>; /** * Set multiple key-value pairs atomically */ mset(entries: Record<string, JSONValue>): Promise<boolean>; /** * Get multiple values by keys */ mget<T = JSONValue>(keys: string[]): Promise<Record<string, T | null>>; /** * Delete multiple keys */ mdel(keys: string[]): Promise<number>; /** * Scan keys with optional prefix */ scan(prefix?: string, limit?: number): Promise<ScanResult>; /** * List all keys matching a pattern */ keys(pattern?: string): Promise<string[]>; /** * Get database size (number of keys) */ dbsize(): Promise<number>; /** * Set expiration time for a key */ expire(key: string, seconds: number): Promise<boolean>; /** * Get TTL for a key */ ttl(key: string): Promise<number | null>; /** * Remove expiration from a key */ persist(key: string): Promise<boolean>; /** * Flush current database */ flushdb(): Promise<number>; /** * Flush all databases */ flushall(): Promise<number>; /** * Get store statistics */ stats(): Promise<KVStats>; } /** * Synap TypeScript SDK - Queue System Module * * Message queue operations with ACK/NACK support. * Includes reactive consumer patterns using RxJS. */ /** * Queue System client with reactive support */ declare class QueueManager { private client; private stopSignals; constructor(client: SynapClient); /** * Create a new queue */ createQueue(name: string, config?: QueueConfig): Promise<boolean>; /** * Publish a message to a queue */ publish(queueName: string, payload: Uint8Array | string, options?: PublishOptions): Promise<string>; /** * Consume a message from a queue */ consume(queueName: string, consumerId: string): Promise<QueueMessage | null>; /** * Acknowledge message processing (ACK) */ ack(queueName: string, messageId: string): Promise<boolean>; /** * Negative acknowledge (NACK) - requeue or send to DLQ */ nack(queueName: string, messageId: string, requeue?: boolean): Promise<boolean>; /** * Get queue statistics */ stats(queueName: string): Promise<QueueStats>; /** * List all queues */ listQueues(): Promise<string[]>; /** * Purge all messages from a queue */ purge(queueName: string): Promise<number>; /** * Delete a queue */ deleteQueue(queueName: string): Promise<boolean>; /** * Helper: Publish a string message */ publishString(queueName: string, message: string, options?: PublishOptions): Promise<string>; /** * Helper: Publish a JSON object */ publishJSON(queueName: string, data: any, options?: PublishOptions): Promise<string>; /** * Helper: Consume and decode as string */ consumeString(queueName: string, consumerId: string): Promise<{ message: QueueMessage | null; text: string | null; }>; /** * Helper: Consume and decode as JSON */ consumeJSON<T = any>(queueName: string, consumerId: string): Promise<{ message: QueueMessage | null; data: T | null; }>; /** * Create a reactive message consumer as an Observable * * @example * ```typescript * synap.queue.observeMessages({ * queueName: 'tasks', * consumerId: 'worker-1', * pollingInterval: 500, * concurrency: 5 * }).subscribe({ * next: async (msg) => { * await processMessage(msg.data); * await msg.ack(); * }, * error: (err) => console.error('Error:', err) * }); * ``` */ observeMessages<T = any>(options: QueueConsumerOptions): Observable<ProcessedMessage<T>>; /** * Create a reactive message consumer with automatic ACK/NACK handling * * @example * ```typescript * synap.queue.observeMessagesAuto({ * queueName: 'tasks', * consumerId: 'worker-1', * }).subscribe({ * next: async (msg) => { * // Process message - will auto-ACK on success * await processMessage(msg.data); * }, * error: (err) => console.error('Error:', err) * }); * ``` */ observeMessagesAuto<T = any>(options: QueueConsumerOptions): Observable<ProcessedMessage<T>>; /** * Create a reactive consumer that processes messages with a handler function * * @example * ```typescript * const subscription = synap.queue.processMessages({ * queueName: 'emails', * consumerId: 'email-worker', * concurrency: 10 * }, async (data) => { * await sendEmail(data); * }).subscribe({ * next: (result) => console.log('Processed:', result), * error: (err) => console.error('Error:', err) * }); * ``` */ processMessages<T = any>(options: QueueConsumerOptions, handler: (data: T, message: QueueMessage) => Promise<void>): Observable<{ messageId: string; success: boolean; error?: Error; }>; /** * Stop a reactive consumer * * @param queueName - Queue name * @param consumerId - Consumer ID */ stopConsumer(queueName: string, consumerId: string): void; /** * Stop all reactive consumers */ stopAllConsumers(): void; /** * Create an observable that emits queue statistics at regular intervals * * @param queueName - Queue name * @param interval - Polling interval in milliseconds (default: 5000) * * @example * ```typescript * synap.queue.observeStats('tasks', 1000).subscribe({ * next: (stats) => console.log('Queue depth:', stats.depth), * }); * ``` */ observeStats(queueName: string, interval?: number): Observable<QueueStats>; } /** * Synap TypeScript SDK - Event Stream Module * * Event stream operations with reactive consumption patterns. */ /** * Event Stream Manager with reactive support */ declare class StreamManager { private client; private stopSignals; constructor(client: SynapClient); /** * Create a new stream room */ createRoom(roomName: string): Promise<boolean>; /** * Publish an event to a stream room */ publish(roomName: string, eventName: string, data: any, options?: StreamPublishOptions): Promise<number>; /** * Consume events from a stream room (one-time fetch) */ consume(roomName: string, subscriberId: string, fromOffset?: number): Promise<StreamEvent[]>; /** * Parse event data - handle both byte arrays and objects */ private parseEventData; /** * Get stream room statistics */ stats(roomName: string): Promise<StreamStats>; /** * List all stream rooms */ listRooms(): Promise<string[]>; /** * Delete a stream room */ deleteRoom(roomName: string): Promise<boolean>; /** * Create a reactive event consumer as an Observable * * @example * ```typescript * synap.stream.observeEvents({ * roomName: 'chat-room', * subscriberId: 'user-123', * fromOffset: 0, * pollingInterval: 500 * }).subscribe({ * next: (event) => { * console.log('Event:', event.event, event.data); * } * }); * ``` */ observeEvents<T = any>(options: StreamConsumerOptions): Observable<ProcessedStreamEvent<T>>; /** * Create a reactive consumer that filters by event name * * @example * ```typescript * synap.stream.observeEvent({ * roomName: 'notifications', * subscriberId: 'user-1', * eventName: 'user.created' * }).subscribe({ * next: (event) => console.log('User created:', event.data) * }); * ``` */ observeEvent<T = any>(options: StreamConsumerOptions & { eventName: string; }): Observable<ProcessedStreamEvent<T>>; /** * Stop a reactive consumer * * @param roomName - Room name * @param subscriberId - Subscriber ID */ stopConsumer(roomName: string, subscriberId: string): void; /** * Stop all reactive consumers */ stopAllConsumers(): void; /** * Create an observable that emits stream statistics at regular intervals * * @param roomName - Room name * @param interval - Polling interval in milliseconds (default: 5000) * * @example * ```typescript * synap.stream.observeStats('chat-room', 3000).subscribe({ * next: (stats) => console.log('Events:', stats.max_offset), * }); * ``` */ observeStats(roomName: string, interval?: number): Observable<StreamStats>; /** * Helper: Publish a typed event */ publishEvent<T>(roomName: string, eventName: string, data: T, options?: StreamPublishOptions): Promise<number>; } /** * Synap TypeScript SDK - Pub/Sub Module * * Pub/Sub operations with reactive subscription patterns. */ /** * Pub/Sub Manager with reactive support */ declare class PubSubManager { private client; private subscriptions; constructor(client: SynapClient); /** * Publish a message to a topic */ publish(topic: string, data: any, options?: PubSubPublishOptions): Promise<boolean>; /** * Helper: Publish a typed message */ publishMessage<T>(topic: string, data: T, options?: PubSubPublishOptions): Promise<boolean>; /** * Create a reactive pub/sub subscriber as an Observable * * Note: This method creates a simulated reactive subscription using polling. * For real-time WebSocket-based subscriptions, consider using the WebSocket API directly. * * @example * ```typescript * synap.pubsub.subscribe({ * topics: ['user.created', 'user.updated'], * subscriberId: 'subscriber-1' * }).subscribe({ * next: (message) => { * console.log('Topic:', message.topic); * console.log('Data:', message.data); * } * }); * ``` */ subscribe<T = any>(options: PubSubSubscriberOptions): Observable<ProcessedPubSubMessage<T>>; /** * Subscribe to a single topic with reactive pattern * * @example * ```typescript * synap.pubsub.subscribeTopic('user.created').subscribe({ * next: (message) => console.log('User created:', message.data) * }); * ``` */ subscribeTopic<T = any>(topic: string, subscriberId?: string): Observable<ProcessedPubSubMessage<T>>; /** * Stop a reactive subscription * * @param subscriberId - Subscriber ID * @param topics - Topics that were subscribed to */ unsubscribe(subscriberId: string, topics: string[]): void; /** * Stop all reactive subscriptions */ unsubscribeAll(): void; /** * Get statistics for a topic (if supported by server) */ stats(topic: string): Promise<any>; /** * List all active topics */ listTopics(): Promise<string[]>; } /** * Main Synap client class * * Provides access to all Synap subsystems (KV, Queue, Stream, PubSub) */ declare class Synap { private client; /** Key-Value store operations */ readonly kv: KVStore; /** Queue system operations */ readonly queue: QueueManager; /** Event Stream operations */ readonly stream: StreamManager; /** Pub/Sub operations */ readonly pubsub: PubSubManager; constructor(options?: SynapClientOptions); /** * Ping the server */ ping(): Promise<boolean>; /** * Get server health */ health(): Promise<{ status: string; service: string; version: string; }>; /** * Close the client */ close(): void; /** * Get the underlying HTTP client (for advanced usage) */ getClient(): SynapClient; } export { type AuthOptions, type JSONValue, type KVStats, KVStore, NetworkError, type ProcessedPubSubMessage, type ProcessedStreamEvent, PubSubManager, type PubSubMessage, type PubSubPublishOptions, type PubSubSubscriberOptions, type PublishOptions, type QueueConfig, QueueManager, type QueueMessage, type QueueStats, type RetryOptions, type ScanResult, ServerError, type SetOptions, type StreamConsumerOptions, type StreamEvent, StreamManager, type StreamPublishOptions, type StreamStats, Synap, SynapClient, type SynapClientOptions, SynapError, TimeoutError, Synap as default };