High-performance, SOLID-structured RESP client for Redis and other RESP-compatible servers
npm install @vcms-io/solidis

High-performance, SOLID-structured RESP client for Redis and other RESP-compatible servers
Overview •
Benchmarks •
Features •
Installation •
Usage •
Configuration •
Advanced
Extensions •
Errors •
Contributing •
License

Solidis is a modern RESP client built with SOLID principles, zero dependencies, and enterprise-grade performance in mind. It supports both RESP2 and RESP3 protocols and is optimized for modern JavaScript/TypeScript applications.
The library is designed for minimal bundle size with maximum type safety and performance:
- Pure ESM/CJS - Support for both module systems
- Tree-shakable - Import only what you need
- Type-safe - Extensive TypeScript definitions for all commands
- Dependency-free - Absolutely zero runtime dependencies
| Benchmark | Solidis | IoRedis | Speed Boost 🚀 |
|:--------------------------------------------------------------------|:------------:|:------------:|:-------------------:|
| Hash
HSET + HGET + HGETALL | 248.82ms | 446.03ms | 79% FASTER 🔥🔥|
| Set Operations
SADD + SISMEMBER + SREM | 257.35ms | 444.08ms | 73% FASTER 🔥🔥|
| Expire
SET + EXPIRE + TTL | 198.11ms | 339.78ms | 72% FASTER 🔥🔥|
| Non-Transaction
SET with EXPIRE + GET | 259.69ms | 394.34ms | 52% FASTER 🔥 |
| List
LPUSH + RPUSH + LRANGE | 219.76ms | 345.48ms | 57% FASTER 🔥 |
| Counter
INCR + DECR | 174.04ms | 258.71ms | 49% FASTER 🔥 |
| List operations
LPUSH + RPUSH + LPOP + RPOP + LLEN| 396.67ms | 587.16ms | 48% FASTER 🔥 |
| Transaction + Non-Transaction
SET + GET | 435.46ms | 574.26ms | 32% FASTER ⚡️ |
| Multi-key
MSET + MGET | 393.87ms | 437.45ms | 11% FASTER ⚡️ |
| Transaction
SET with EXPIRE + GET | 286.75ms | 328.00ms | 14% FASTER ⚡️ |
| Set
SADD + SISMEMBER + SMEMBERS | 260.66ms | 275.27ms | 6% FASTER ⚡️ |
| Hash operations
HMSET + HMGET + HDEL | 360.69ms | 377.32ms | 5% FASTER ⚡️ |
| Info/Config
INFO + CONFIG GET | 371.48ms | 353.02ms | 5% slower |
Up to 79% faster than IoRedis! 🚀
Solidis delivers blazing-fast performance with ZERO dependencies
- Lightweight
- Zero dependencies
- Minimum bundle size < 30KB
- Full bundle size (with all commands) < 105KB
- High Performance
- Efficient pipeline & batch processing
- Minimal memory footprint (custom optimized parser)
- Zero-copy buffer operations
- Intelligent buffer management
- Protocol Support
- RESP2 & RESP3 protocols support
- Automatic protocol negotiation
- Binary-safe operations
- Full multi-byte character support
- Advanced Features
- Transaction support (MULTI/EXEC)
- Pipeline operations
- Pub/Sub functionality
- Automatic reconnection
- Command timeout handling
- Type Safety
- Robust TypeScript support
- Comprehensive type definitions
- Command-specific type guards
- Runtime reply type checking
- Extensibility
- Easy to extend client with internal & external commands
- Customizable transaction handling
- Plugin architecture support
- Runtime: Node.js 14 or higher
- Development: Node.js 22 LTS recommended for optimal stability
``bashUsing npm
npm install @vcms-io/solidis
💻 Usage
$3
Solidis offers two client implementations:
#### 1. Basic Client (SolidisClient)
The basic client contains minimal functionality to reduce bundle size. You need to extend it with specific commands:
`typescript
import { SolidisClient } from '@vcms-io/solidis';
import { get } from '@vcms-io/solidis/command/get';
import { set } from '@vcms-io/solidis/command/set';
import { multi } from '@vcms-io/solidis/command/multi';import type { SolidisClientExtensions } from '@vcms-io/solidis';
// Define extensions with type safety
const extensions = {
get,
set,
multi
} satisfies SolidisClientExtensions;
// Initialize client with extensions
const client = new SolidisClient({
host: '127.0.0.1',
port: 6379
}).extend(extensions);
// Use commands
await client.set('key', 'value');
const value = await client.get('key');
`#### 2. Featured Client (SolidisFeaturedClient)
A convenience client with all RESP commands pre-loaded:
`typescript
import { SolidisFeaturedClient } from '@vcms-io/solidis/featured';// All RESP commands are pre-loaded
const client = new SolidisFeaturedClient({
host: '127.0.0.1',
port: 6379
});
// Use any RESP command directly
await client.set('key', 'value');
await client.hset('hash', 'field', 'value');
await client.lpush('list', 'item-1', 'item-2');
`$3
`typescript
// Create client (with lazy connect)
const client = new SolidisClient({
uri: 'redis://127.0.0.1:6379',
lazyConnect: true
}).extend({ get, set });// Explicitly connect when needed
await client.connect();
// Handle connection events
client.on('connect', () => console.log('Connected to server'));
client.on('ready', () => console.log('Client is ready for commands'));
client.on('error', (err) => console.error('Error occurred:', err));
client.on('end', () => console.log('Connection closed'));
// Close connection when done
client.quit();
`$3
`typescript
// Set a key
await client.set('key', 'value');// Get a key
const value = await client.get('key');
console.log(value); // 'value'
// Delete a key
await client.del('key');
`$3
`typescript
// Start a transaction
const transaction = client.multi();// Queue commands (no await needed)
transaction.set('key', 'value');
transaction.incr('counter');
transaction.get('key');
// Execute transaction
const results = await transaction.exec();
console.log(results); // [[ 'OK' ], [ 1 ], [ ]]
// Or discard a transaction if needed
const transaction = client.multi();
transaction.set('key', 'value');
transaction.discard(); // Cancel transaction
`$3
`typescript
// Create commands for a pipeline
const commands = [
['set', 'pipeline', 'value'],
['incr', 'counter'],
['get', 'pipeline']
];// Send commands as a pipeline
const results = await client.send(commands);
console.log(results); // [[ 'OK' ], [ 1 ], [ ]]
`$3
`typescript
// Subscribe to channels
client.on('message', (channel, message) => {
console.log(Received ${message} from ${channel});
});await client.subscribe('news');
// Publish from another client
await client.publish('news', 'Hello world!');
`⚙️ Configuration
Solidis provides extensive configuration options:
`typescript
const client = new SolidisClient({
// Connection
uri: 'redis://localhost:6379',
host: '127.0.0.1',
port: 6379,
useTLS: false,
lazyConnect: false, // Authentication
authentication: {
username: 'user',
password: 'password'
},
database: 0,
// Protocol & Recovery
clientName: 'solidis',
protocol: 'RESP2', // 'RESP2' or 'RESP3'
autoReconnect: true,
enableReadyCheck: true,
maxConnectionRetries: 20,
connectionRetryDelay: 100,
autoRecovery: {
database: true, // Auto-select DB after reconnect
subscribe: true, // Auto-resubscribe to channels
ssubscribe: true, // Auto-resubscribe to shard channels
psubscribe: true, // Auto-resubscribe to patterns
},
// Timeouts (milliseconds)
commandTimeout: 5000,
connectionTimeout: 2000,
socketWriteTimeout: 1000,
readyCheckInterval: 100,
// Performance Tuning
maxCommandsPerPipeline: 300,
maxProcessRepliesPerChunk: 4 * 1024, // 4KB
maxSocketWriteSizePerOnce: 64 * 1024, // 64KB
rejectOnPartialPipelineError: false,
// Parser Configuration
parser: {
buffer: {
initial: 4 1024 1024, // 4MB
shiftThreshold: 2 1024 1024, // 2MB
},
},
// Event Listeners
maxEventListenersForClient: 10 * 1024,
maxEventListenersForSocket: 10 * 1024,
// Debug Options
debug: false,
debugMaxEntries: 10 * 1024,
});
`🚀 Advanced Features
$3
`typescript
import { SolidisClient } from '@vcms-io/solidis';
import { get, set } from '@vcms-io/solidis/command';import type { SolidisClientExtensions } from '@vcms-io/solidis';
// Define extensions with custom commands
const extensions = {
get,
set,
// Custom command implementation
fill: async function(this: typeof client, keys: string[], value: string) {
return await Promise.all(keys.map((key) => this.set(key, value)));
},
} satisfies SolidisClientExtensions;
const client = new SolidisClient({
host: '127.0.0.1',
port: 6379
}).extend(extensions);
// Use custom command
await client.fill(['key1', 'key2', 'key3'], 'value');
`$3
When you need to use a command that's not yet implemented:
`typescript
// Using raw commands with send()
const result = await client.send([['command', 'some', 'options']]);
`$3
Enable detailed debug logging:
`typescript
// Enable debug mode
const client = new SolidisClient({
debug: true
});// Listen for debug events
client.on('debug', (entry) => {
console.log(
[${entry.type}] ${entry.message}, entry.data);
});// Alternative: environment variable
// DEBUG=solidis node app.js
`🧩 Extensions
The
@vcms-io/solidis-extensions package provides additional functionality and utilities for Solidis clients. It includes pre-built extensions to enhance your Redis operations.$3
`bash
Using npm
npm install @vcms-io/solidis-extensionsUsing yarn
yarn add @vcms-io/solidis-extensionsUsing pnpm
pnpm add @vcms-io/solidis-extensions
`$3
- SpinLock - A lightweight mutex implemented as a Solidis command extension
- RedLock - Fault-tolerant distributed mutex based on the Redlock algorithm
Check the extensions documentation for detailed usage examples.
⚠️ Error Handling
Solidis provides detailed error classes for different failure modes:
`typescript
import {
SolidisClientError,
SolidisConnectionError,
SolidisParserError,
SolidisPubSubError,
SolidisRequesterError,
unwrapSolidisError,
} from '@vcms-io/solidis';try {
await client.set('key', 'value');
} catch (error) {
// Get the root cause with stack trace
console.error(unwrapSolidisError(error));
// Handle specific error types
if (error instanceof SolidisConnectionError) {
console.error('Connection error:', error.message);
} else if (error instanceof SolidisParserError) {
console.error('Parser error:', error.message);
} else if (error instanceof SolidisClientError) {
console.error('Client error:', error.message);
}
}
`🏗️ Structure
`
┌─────────────────────────────────────────────────┐
│ SolidisClient │
│ │
│ Creates & coordinates all components │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Debug Memory │ │
│ └───────┬───────────────────┬────────┘ │
│ ▼ ▼ │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ Connection │─►│ Requester │─┐ │
│ └────────────────┘ └────────────────┘ │ │
│ ┌────────────────┐ │ │
│ │ Parser │◄┤ │
│ └────────────────┘ │ │
│ ┌────────────────┐ │ │
│ │ PubSub │◄┘ │
│ └────────────────┘ │
│ │
└─────────────────────────────────────────────────┘
┌──────────────┴─────────────┐
▼ ▼
┌─────────────────┐ ┌───────────────────────┐
│ SolidisClient │ │ SolidisFeaturedClient │
│ (needs extend) │ │ (all commands) │
└─────────────────┘ └───────────────────────┘
`The Solidis structure follows a clear component separation:
- SolidisClient: Core entry point that creates and coordinates all components
- Debug Memory: Created in the client and injected into other components
- Connection: Manages TCP/TLS socket connections, reconnection and recovery
- Requester: Handles command pipelining & request states
- Parser: Processes RESP2/RESP3 protocol with optimized buffer handling
- PubSub: Maintains subscription state and is used by Requester for pub/sub events
🔔 Event System
Solidis emits the following events:
`typescript
// Connection events
client.on('connect', () => console.log('Connected to server'));
client.on('ready', () => console.log('Client is ready'));
client.on('end', () => console.log('Connection closed'));
client.on('error', (err) => console.error('Error:', err));// Pub/Sub events
client.on('message', (channel, message) => console.log(
${channel}: ${message}));
client.on('pmessage', (pattern, channel, message) => console.log(${pattern} ${channel}: ${message}));
client.on('subscribe', (channel, count) => console.log(Subscribed to ${channel}));
client.on('unsubscribe', (channel, count) => console.log(Unsubscribed from ${channel}));// Debug events
client.on('debug', (entry) => console.log(
[${entry.type}] ${entry.message}));
`🤝 Contributing
Solidis is an open-source project and we welcome contributions from the community. Here's how you can contribute:
$3
`bash
Clone the repository
git clone https://github.com/vcms-io/solidis.git
cd solidisInstall dependencies
npm installBuild the project
npm run buildRun tests
npm test
`$3
1. Fork the Repository: Start by forking the repository and then clone your fork.
2. Create a Branch: Create a branch for your feature or bugfix:
`bash
git checkout -b feature/your-feature-name
`3. Follow Code Style:
- Use TypeScript strict mode
- Follow existing patterns and naming conventions
4. Submit Pull Request: Push your changes to your fork and submit a pull request.
- Provide a clear description of the changes
- Reference any related issues
- Add appropriate documentation
$3
- TypeScript: Use strict typing and avoid
any types and as` cast where possibleSolidis follows semantic versioning (SemVer):
- Patch (0.0.x): Bug fixes and minor changes that don't affect the API
- Minor (0.x.0): New features added in a backward compatible manner
- Major (x.0.0): Breaking changes to the public API
Licensed under the MIT. See LICENSE for more information.