# @push.rocks/smartipc

A library for node inter process communication, providing an easy-to-use API for IPC.

# readme.md for @push.rocks/smartipc

**Rock-solid IPC for Node.js with zero dependencies**

[![npm version](https://img.shields.io/npm/v/@push.rocks/smartipc.svg)](https://www.npmjs.com/package/@push.rocks/smartipc)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./license)

SmartIPC delivers bulletproof Inter-Process Communication for Node.js applications. Built for real-world production use, it handles all the edge cases that make IPC tricky - automatic reconnection, race conditions, heartbeat monitoring, and clean shutdowns. All with **zero external dependencies** and full TypeScript support.

## 🎯 Why SmartIPC?

- **Zero Dependencies** - Pure Node.js implementation using native modules
- **Battle-tested Reliability** - Automatic reconnection, graceful degradation, and timeout handling
- **Type-Safe** - Full TypeScript support with generics for compile-time safety
- **CI/Test Ready** - Built-in helpers and race condition prevention for testing
- **Observable** - Real-time metrics, connection tracking, and health monitoring
- **Multiple Patterns** - Request/Response, Pub/Sub, and Fire-and-Forget messaging
- **Streaming Support** - Efficient, backpressure‑aware streaming for large data and files

## 📦 Installation

```bash
npm install @push.rocks/smartipc
# or
pnpm add @push.rocks/smartipc
# or
yarn add @push.rocks/smartipc
```

## 🚀 Quick Start

```typescript
import { SmartIpc } from '@push.rocks/smartipc';

// Create a server
const server = SmartIpc.createServer({
  id: 'my-service',
  socketPath: '/tmp/my-service.sock',
  autoCleanupSocketFile: true  // Clean up stale sockets automatically
});

// Handle incoming messages
server.onMessage('greet', async (data, clientId) => {
  console.log(`Client ${clientId} says:`, data.message);
  return { response: `Hello ${data.name}!` };
});

// Start the server
await server.start({ readyWhen: 'accepting' });  // Wait until fully ready
console.log('Server is ready to accept connections! ✨');

// Create a client
const client = SmartIpc.createClient({
  id: 'my-service',
  socketPath: '/tmp/my-service.sock',
  connectRetry: {
    enabled: true,
    maxAttempts: 10
  }
});

// Connect with automatic retry
await client.connect();

// Send a request and get a response
const response = await client.request('greet', { 
  name: 'World',
  message: 'Hi there!' 
});
console.log('Server said:', response.response);  // "Hello World!"
```

## 🎮 Core Concepts

### Transport Types

SmartIPC supports multiple transport mechanisms, automatically selecting the best one for your platform:

```typescript
// TCP Socket (cross-platform, network-capable)
const tcpServer = SmartIpc.createServer({
  id: 'tcp-service',
  host: 'localhost',
  port: 9876
});

// Unix Domain Socket (Linux/macOS, fastest local IPC)
const unixServer = SmartIpc.createServer({
  id: 'unix-service',
  socketPath: '/tmp/my-app.sock'
});

// Windows Named Pipe (Windows optimal)
// Automatically used on Windows when socketPath is provided
const windowsServer = SmartIpc.createServer({
  id: 'pipe-service',
  socketPath: '\\\\.\\pipe\\my-app-pipe'
});
```

### Message Patterns

#### 🔥 Fire and Forget
Send messages without waiting for a response:

```typescript
// Server
server.onMessage('log', (data, clientId) => {
  console.log(`[${clientId}] ${data.level}:`, data.message);
  // No return needed
});

// Client
await client.sendMessage('log', { 
  level: 'info',
  message: 'User logged in',
  timestamp: Date.now()
});
```

#### 📞 Request/Response
RPC-style communication with type safety:

```typescript
interface UserRequest {
  userId: string;
  fields?: string[];
}

interface UserResponse {
  id: string;
  name: string;
  email?: string;
  createdAt: number;
}

// Server
server.onMessage<UserRequest, UserResponse>('getUser', async (data) => {
  const user = await db.getUser(data.userId);
  return {
    id: user.id,
    name: user.name,
    email: data.fields?.includes('email') ? user.email : undefined,
    createdAt: user.createdAt
  };
});

// Client - with timeout
const user = await client.request<UserRequest, UserResponse>(
  'getUser',
  { userId: '123', fields: ['email'] },
  { timeout: 5000 }
);
```

#### 📢 Pub/Sub Pattern
Topic-based message broadcasting:

```typescript
// Subscribers
const subscriber1 = SmartIpc.createClient({
  id: 'events-service',
  socketPath: '/tmp/events.sock'
});

await subscriber1.connect();
await subscriber1.subscribe('user.login', (data) => {
  console.log('User logged in:', data);
});

// Publisher
const publisher = SmartIpc.createClient({
  id: 'events-service',
  socketPath: '/tmp/events.sock'
});

await publisher.connect();
await publisher.publish('user.login', { 
  userId: '123',
  ip: '192.168.1.1',
  timestamp: Date.now()
});
```

## 💪 Advanced Features

### 📦 Streaming Large Data & Files

SmartIPC supports efficient, backpressure-aware streaming of large payloads using chunked messages. Streams work both directions and emit a high-level `stream` event for consumption.

Client → Server streaming:

```typescript
// Server side: receive stream
server.on('stream', async (info, readable) => {
  if (info.meta?.type === 'file') {
    console.log('Receiving file', info.meta.basename, 'from', info.clientId);
  }
  // Pipe to disk or process chunks
  await SmartIpc.pipeStreamToFile(readable, '/tmp/incoming.bin');
});

// Client side: send a stream
const readable = fs.createReadStream('/path/to/local.bin');
await client.sendStream(readable, {
  meta: { type: 'file', basename: 'local.bin' },
  chunkSize: 64 * 1024 // optional, defaults to 64k
});
```

Server → Client streaming:

```typescript
client.on('stream', async (info, readable) => {
  console.log('Got stream from server', info.meta);
  await SmartIpc.pipeStreamToFile(readable, '/tmp/from-server.bin');
});

await server.sendStreamToClient(client.getClientId(), fs.createReadStream('/path/server.bin'), {
  meta: { type: 'file', basename: 'server.bin' }
});
```

High-level helpers for files:

```typescript
// Client → Server
await client.sendFile('/path/to/bigfile.iso');

// Server → Client
await server.sendFileToClient(clientId, '/path/to/backup.tar');

// Save an incoming stream to a file (both sides)
server.on('stream', async (info, readable) => {
  await SmartIpc.pipeStreamToFile(readable, '/data/uploaded/' + info.meta?.basename);
});
```

Events & metadata:

- `channel/server/client` emit `stream` with `(info, readable)`
- `info` contains: `streamId`, `meta` (your metadata, e.g., filename/size), `headers`, and `clientId` (if available)

API summary:

- Client: `sendStream(readable, opts)`, `sendFile(filePath, opts)`, `cancelOutgoingStream(id)`, `cancelIncomingStream(id)`
- Server: `sendStreamToClient(clientId, readable, opts)`, `sendFileToClient(clientId, filePath, opts)`, `cancelIncomingStreamFromClient(clientId, id)`, `cancelOutgoingStreamToClient(clientId, id)`
- Utility: `SmartIpc.pipeStreamToFile(readable, filePath)`

Concurrency and cancelation:

```typescript
// Limit concurrent streams per connection
const server = SmartIpc.createServer({
  id: 'svc', socketPath: '/tmp/svc.sock', maxConcurrentStreams: 2
});

// Cancel a stream from the receiver side
server.on('stream', (info, readable) => {
  if (info.meta?.shouldCancel) {
    (server as any).primaryChannel.cancelIncomingStream(info.streamId, { clientId: info.clientId });
  }
});
```

Notes:
- Streaming uses chunked messages under the hood and respects socket backpressure.
- Include `meta` to share context like filename/size; it’s delivered with the `stream` event.
- Configure `maxConcurrentStreams` (default: 32) to guard resources.

### 🏁 Server Readiness Detection

Eliminate race conditions in tests and production:

```typescript
const server = SmartIpc.createServer({
  id: 'my-service',
  socketPath: '/tmp/my-service.sock',
  autoCleanupSocketFile: true
});

// Option 1: Wait for full readiness
await server.start({ readyWhen: 'accepting' });
// Server is now FULLY ready to accept connections

// Option 2: Use ready event
server.on('ready', () => {
  console.log('Server is ready!');
  startClients();
});

await server.start();

// Option 3: Check readiness state
if (server.getIsReady()) {
  console.log('Ready to rock! 🎸');
}
```

### 🔄 Smart Connection Retry

Never lose messages due to temporary connection issues:

```typescript
const client = SmartIpc.createClient({
  id: 'resilient-client',
  socketPath: '/tmp/service.sock',
  connectRetry: {
    enabled: true,
    initialDelay: 100,      // Start with 100ms
    maxDelay: 1500,         // Cap at 1.5 seconds
    maxAttempts: 20,        // Try 20 times
    totalTimeout: 15000     // Give up after 15 seconds total
  },
  registerTimeoutMs: 8000   // Registration handshake timeout
});

// Will retry automatically if server isn't ready yet
await client.connect({ 
  waitForReady: true,       // Wait for server to exist
  waitTimeout: 10000        // Wait up to 10 seconds
});
```

### 🛑 Client-Only Mode (No Auto-Start)

In some setups (CLI + long-running daemon), you want clients to fail fast when no server is available, rather than implicitly becoming the server. Enable client-only mode to prevent the “client becomes server” fallback for Unix domain sockets and Windows named pipes.

```typescript
// Strict client that never auto-starts a server on connect failure
const client = SmartIpc.createClient({
  id: 'my-service',
  socketPath: '/tmp/my-service.sock',
  clientId: 'my-cli',
  clientOnly: true,                 // NEW: disable auto-start fallback
  connectRetry: { enabled: false }  // optional: fail fast
});

try {
  await client.connect();
} catch (err) {
  // With clientOnly: true, errors become descriptive
  // e.g. "Server not available (ENOENT); clientOnly prevents auto-start"
  console.error(err.message);
}
```

- Default: `clientOnly` is `false` to preserve backward compatibility.
- Env override: set `SMARTIPC_CLIENT_ONLY=1` to enforce client-only behavior without code changes.
- Note: `SmartIpc.waitForServer()` internally uses `clientOnly: true` for safe probing.

### 💓 Graceful Heartbeat Monitoring

Keep connections alive without crashing on timeouts:

```typescript
const server = SmartIpc.createServer({
  id: 'monitored-service',
  socketPath: '/tmp/monitored.sock',
  heartbeat: true,
  heartbeatInterval: 3000,
  heartbeatTimeout: 10000,
  heartbeatInitialGracePeriodMs: 5000,    // Grace period for startup
  heartbeatThrowOnTimeout: false           // Emit event instead of throwing
});

server.on('heartbeatTimeout', (clientId) => {
  console.log(`Client ${clientId} heartbeat timeout - will handle gracefully`);
});

// Client configuration
const client = SmartIpc.createClient({
  id: 'monitored-service',
  socketPath: '/tmp/monitored.sock',
  heartbeat: true,
  heartbeatInterval: 3000,
  heartbeatTimeout: 10000,
  heartbeatInitialGracePeriodMs: 5000,
  heartbeatThrowOnTimeout: false
});

client.on('heartbeatTimeout', () => {
  console.log('Heartbeat timeout detected, reconnecting...');
  // Handle reconnection logic
});
```

### 🧹 Automatic Socket Cleanup

Never worry about stale socket files:

```typescript
const server = SmartIpc.createServer({
  id: 'clean-service',
  socketPath: '/tmp/service.sock',
  autoCleanupSocketFile: true,    // Remove stale socket on start
  socketMode: 0o600               // Set socket permissions (Unix only)
});

// Socket file will be cleaned up automatically on start
await server.start();
```

### 📊 Real-time Metrics

Monitor your IPC performance:

```typescript
// Server stats
const serverStats = server.getStats();
console.log({
  isRunning: serverStats.isRunning,
  connectedClients: serverStats.connectedClients,
  totalConnections: serverStats.totalConnections,
  metrics: {
    messagesSent: serverStats.metrics.messagesSent,
    messagesReceived: serverStats.metrics.messagesReceived,
    errors: serverStats.metrics.errors
  }
});

// Client stats
const clientStats = client.getStats();
console.log({
  connected: clientStats.connected,
  reconnectAttempts: clientStats.reconnectAttempts,
  metrics: clientStats.metrics
});

// Get specific client info
const clientInfo = server.getClientInfo('client-123');
console.log({
  connectedAt: new Date(clientInfo.connectedAt),
  lastActivity: new Date(clientInfo.lastActivity),
  metadata: clientInfo.metadata
});
```

### 🎯 Broadcasting

Send messages to multiple clients:

```typescript
// Broadcast to all connected clients
await server.broadcast('announcement', { 
  message: 'Server will restart in 5 minutes',
  severity: 'warning'
});

// Send to specific clients
await server.broadcastTo(
  ['client-1', 'client-2'],
  'private-message',
  { content: 'This is just for you two' }
);

// Send to one client
await server.sendToClient('client-1', 'direct', {
  data: 'Personal message'
});
```

## 🧪 Testing Utilities

SmartIPC includes powerful helpers for testing:

### Wait for Server

```typescript
import { SmartIpc } from '@push.rocks/smartipc';

// Start your server in another process
const serverProcess = spawn('node', ['server.js']);

// Wait for it to be ready
await SmartIpc.waitForServer({
  socketPath: '/tmp/test.sock',
  timeoutMs: 10000
});

// Now safe to connect clients
const client = SmartIpc.createClient({
  id: 'test-client',
  socketPath: '/tmp/test.sock'
});
await client.connect();
```

### Spawn and Connect

```typescript
// Helper that spawns a server and connects a client
const { client, serverProcess } = await SmartIpc.spawnAndConnect({
  serverScript: './server.js',
  socketPath: '/tmp/test.sock',
  clientId: 'test-client',
  connectRetry: {
    enabled: true,
    maxAttempts: 10
  }
});

// Use the client
const response = await client.request('ping', {});

// Cleanup
await client.disconnect();
serverProcess.kill();
```

## 🎭 Event Handling

SmartIPC provides comprehensive event emitters:

```typescript
// Server events
server.on('start', () => console.log('Server started'));
server.on('ready', () => console.log('Server ready for connections'));
server.on('clientConnect', (clientId, metadata) => {
  console.log(`Client ${clientId} connected with metadata:`, metadata);
});
server.on('clientDisconnect', (clientId) => {
  console.log(`Client ${clientId} disconnected`);
});
server.on('error', (error, clientId) => {
  console.error(`Error from ${clientId}:`, error);
});

// Client events  
client.on('connect', () => console.log('Connected to server'));
client.on('disconnect', () => console.log('Disconnected from server'));
client.on('reconnecting', (attempt) => {
  console.log(`Reconnection attempt ${attempt}`);
});
client.on('error', (error) => {
  console.error('Client error:', error);
});
client.on('heartbeatTimeout', (error) => {
  console.warn('Heartbeat timeout:', error);
});
```

## 🛡️ Error Handling

Robust error handling with detailed error information:

```typescript
// Client-side error handling
try {
  const response = await client.request('riskyOperation', data, {
    timeout: 5000
  });
} catch (error) {
  if (error.message.includes('timeout')) {
    console.error('Request timed out');
  } else if (error.message.includes('Failed to register')) {
    console.error('Could not register with server');
  } else {
    console.error('Unknown error:', error);
  }
}

// Server-side error boundaries
server.onMessage('process', async (data, clientId) => {
  try {
    return await riskyProcessing(data);
  } catch (error) {
    console.error(`Processing failed for ${clientId}:`, error);
    throw error;  // Will be sent back to client as error
  }
});
```

## 🏗️ Architecture

SmartIPC uses a clean, layered architecture:

```
┌─────────────────────────────────────────┐
│          Your Application               │
│        (Business logic)                 │
└─────────────────────────────────────────┘
                   ↕
┌─────────────────────────────────────────┐
│         IpcServer / IpcClient           │
│   (High-level API, Message routing)     │
└─────────────────────────────────────────┘
                   ↕
┌─────────────────────────────────────────┐
│            IpcChannel                   │
│  (Connection management, Heartbeat,     │
│   Reconnection, Request/Response)       │
└─────────────────────────────────────────┘
                   ↕
┌─────────────────────────────────────────┐
│          Transport Layer                │
│  (TCP, Unix Socket, Named Pipe)         │
│     (Framing, buffering, I/O)           │
└─────────────────────────────────────────┘
```

## 🎯 Common Use Cases

### Microservices Communication
```typescript
// API Gateway
const gateway = SmartIpc.createServer({
  id: 'api-gateway',
  socketPath: '/tmp/gateway.sock'
});

// User Service
const userService = SmartIpc.createClient({
  id: 'api-gateway',
  socketPath: '/tmp/gateway.sock',
  clientId: 'user-service'
});

// Order Service  
const orderService = SmartIpc.createClient({
  id: 'api-gateway',
  socketPath: '/tmp/gateway.sock',
  clientId: 'order-service'
});
```

### Worker Process Management
```typescript
// Main process
const server = SmartIpc.createServer({
  id: 'main',
  socketPath: '/tmp/workers.sock'
});

server.onMessage('job-complete', (result, workerId) => {
  console.log(`Worker ${workerId} completed job:`, result);
});

// Worker process
const worker = SmartIpc.createClient({
  id: 'main',
  socketPath: '/tmp/workers.sock',
  clientId: `worker-${process.pid}`
});

await worker.sendMessage('job-complete', {
  jobId: '123',
  result: processedData
});
```

### Real-time Event Distribution
```typescript
// Event bus
const eventBus = SmartIpc.createServer({
  id: 'event-bus',
  socketPath: '/tmp/events.sock'
});

// Services subscribe to events
const analyticsService = SmartIpc.createClient({
  id: 'event-bus',
  socketPath: '/tmp/events.sock'
});

await analyticsService.subscribe('user.*', (event) => {
  trackEvent(event);
});
```

## 📈 Performance

SmartIPC is optimized for high throughput and low latency:

| Transport | Messages/sec | Avg Latency | Use Case |
|-----------|-------------|-------------|----------|
| Unix Socket | 150,000+ | < 0.1ms | Local high-performance IPC (Linux/macOS) |
| Named Pipe | 120,000+ | < 0.15ms | Windows local IPC |
| TCP (localhost) | 100,000+ | < 0.2ms | Local network-capable IPC |
| TCP (network) | 50,000+ | < 1ms | Distributed systems |

- **Memory efficient**: Streaming support for large payloads
- **CPU efficient**: Event-driven, non-blocking I/O

## 🔧 Requirements

- Node.js >= 14.x
- TypeScript >= 4.x (for development)
- Unix-like OS (Linux, macOS) or Windows

## License and Legal Information

This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. 

**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

### Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.

### Company Information

Task Venture Capital GmbH  
Registered at District court Bremen HRB 35230 HB, Germany

For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

# changelog.md for @push.rocks/smartipc

# Changelog

## 2025-08-30 - 2.3.0 - feat(streaming)
Add streaming support: chunked stream transfers, file send/receive, stream events and helpers

- Implement chunked streaming protocol in IpcChannel (init / chunk / end / error / cancel messages)
- Add sendStream, cancelOutgoingStream and cancelIncomingStream methods to IpcChannel
- Expose high-level streaming API on client: sendStream, sendFile, cancelOutgoingStream, cancelIncomingStream
- Expose high-level streaming API on server: sendStreamToClient, sendFileToClient, cancelIncomingStreamFromClient, cancelOutgoingStreamToClient
- Emit 'stream' events from channels/servers/clients with (info, readable) where info includes streamId, meta, headers and clientId
- Add maxConcurrentStreams option (default 32) and enforce concurrent stream limits for incoming/outgoing
- Add SmartIpc.pipeStreamToFile helper to persist incoming streams to disk
- Export stream in smartipc.plugins and update README with streaming usage and examples
- Add comprehensive streaming tests (test/test.streaming.ts) covering large payloads, file transfer, cancellation and concurrency limits

## 2025-08-29 - 2.2.2 - fix(ipc)
Propagate per-client disconnects, add proper routing for targeted messages, and remove unused node-ipc deps

- Forward per-client 'clientDisconnected' events from transports up through IpcChannel and IpcServer so higher layers can react and clean up state.
- IpcChannel re-emits 'clientDisconnected' and allows registering handlers for it.
- IpcServer now listens for 'clientDisconnected' to cleanup topic subscriptions, remove clients from the map, and emit 'clientDisconnect'.
- sendToClient injects the target clientId into headers so transports can route messages to the correct socket instead of broadcasting.
- broadcast and broadcastTo delegate to sendToClient to ensure messages are routed to intended recipients and errors are attributed to the correct client.
- Transports now emit 'clientDisconnected' with the clientId when known.
- package.json: removed unused node-ipc and @types/node-ipc dependencies (dependency cleanup).

## 2025-08-29 - 2.2.1 - fix(tests)
Remove redundant manual topic handlers from tests and rely on server built-in pub/sub

- Removed manual server.onMessage('__subscribe__') and server.onMessage('__publish__') handlers from test/test.ts
- Tests now rely on the server's built-in publish/subscribe behavior: clients publish directly and subscribers receive messages
- Test code simplified without changing public API or runtime behavior

## 2025-08-29 - 2.2.0 - feat(ipcclient)
Add clientOnly mode to prevent clients from auto-starting servers and improve registration/reconnect behavior

- Introduce a clientOnly option on transports and clients, and support SMARTIPC_CLIENT_ONLY=1 env override to prevent a client from auto-starting a server when connect() encounters ECONNREFUSED/ENOENT.
- Update UnixSocketTransport/TcpTransport connect behavior: if clientOnly (or env override) is enabled, reject connect with a descriptive error instead of starting a server (preserves backward compatibility when disabled).
- Make SmartIpc.waitForServer use clientOnly probing to avoid accidental server creation during readiness checks.
- Refactor IpcClient registration flow: extract attemptRegistrationInternal, set didRegisterOnce flag, and automatically re-register on reconnects when previously registered.
- Add and update tests to cover clientOnly behavior, SMARTIPC_CLIENT_ONLY env enforcement, temporary socket paths and automatic cleanup, and other reliability improvements.
- Update README with a new 'Client-Only Mode' section documenting the option, env override, and examples.

## 2025-08-28 - 2.1.3 - fix(classes.ipcchannel)
Normalize heartbeatThrowOnTimeout option parsing and allow registering 'heartbeatTimeout' via IpcChannel.on

- Normalize heartbeatThrowOnTimeout to boolean (accepts 'true'/'false' strings and other truthy/falsey values) to be defensive for JS consumers
- Expose 'heartbeatTimeout' as a special channel event so handlers registered via IpcChannel.on('heartbeatTimeout', ...) will be called

## 2025-08-26 - 2.1.2 - fix(core)
Improve heartbeat handling and transport routing; forward heartbeat timeout events; include clientId routing and probe improvements

- IpcChannel: add heartbeatInitialGracePeriod handling — delay heartbeat timeout checks until the grace period elapses and use a minimum check interval (>= 1000ms)
- IpcChannel: add heartbeatGraceTimer and ensure stopHeartbeat clears the grace timer to avoid repeated events
- IpcChannel / Client / Server: forward heartbeatTimeout events instead of only throwing when configured (heartbeatThrowOnTimeout = false) so consumers can handle timeouts via events
- IpcClient: include clientId in registration request headers to enable proper routing on the server/transport side
- UnixSocketTransport: track socket <-> clientId mappings, clean them up on socket close, and update mappings when __register__ or messages containing clientId are received
- UnixSocketTransport: route messages to a specific client when headers.clientId is present (fallback to broadcasting when no target is found), and emit both clientMessage and message for parsed client messages
- ts/index.waitForServer: use SmartIpc.createClient for probing, shorten probe register timeout, and use a slightly longer retry delay between probes for stability

## 2025-08-25 - 2.1.1 - fix(readme)
Update README: expand docs, examples, server readiness, heartbeat, and testing utilities

- Rewrite introduction and overall tone to emphasize zero-dependency, reliability, and TypeScript support
- Replace several Quick Start examples to use socketPath and show autoCleanupSocketFile usage
- Add Server readiness detection docs and SmartIpc.waitForServer example
- Document smart connection retry options (connectRetry) and registerTimeoutMs usage
- Clarify heartbeat configuration and add heartbeatThrowOnTimeout option to emit events instead of throwing
- Add sections for automatic socket cleanup, broadcasting, testing utilities (waitForServer, spawnAndConnect), and metrics
- Various formatting and copy improvements throughout README

## 2025-08-25 - 2.1.0 - feat(core)
Add heartbeat grace/timeout options, client retry/wait-for-ready, server readiness and socket cleanup, transport socket options, helper utilities, and tests

- IpcChannel: add heartbeatInitialGracePeriodMs and heartbeatThrowOnTimeout; emit 'heartbeatTimeout' event when configured instead of throwing and disconnecting immediately.
- IpcClient: add connectRetry configuration, registerTimeoutMs, waitForReady option and robust connect logic with exponential backoff and total timeout handling.
- IpcServer: add start option readyWhen ('accepting'), isReady/getIsReady API, autoCleanupSocketFile and socketMode support for managing stale socket files and permissions.
- Transports: support autoCleanupSocketFile and socketMode (cleanup stale socket files and set socket permissions where applicable).
- SmartIpc: add waitForServer helper to wait until a server is ready and spawnAndConnect helper to spawn a server process and connect a client.
- Tests: add comprehensive tests (test.improvements.ts and test.reliability.ts) covering readiness, socket cleanup, retries, heartbeat behavior, race conditions, multiple clients, and server restart scenarios.

## 2025-08-25 - 2.0.3 - fix(ipc)
Patch release prep: bump patch version and release minor fixes

- No changes detected in the provided diff; repository files currently declare version 2.0.2.
- Recommend a patch bump to 2.0.3 to prepare a new release (no breaking changes identified).

## 2025-08-24 - 2.0.2 - fix(packaging)
Update package metadata: add exports, mark package public; clean up README contributing section

- Add an exports entry in package.json pointing to ./dist_ts/index.js for proper ESM exports resolution
- Mark package as public (private: false) and remove legacy main/typings fields
- Remove the Contributing section and example contributor workflow from README

## 2025-08-24 - 2.0.1 - fix(npm)
Remove .npmrc to avoid committing npm registry configuration

- Deleted .npmrc which contained a hardcoded registry (https://registry.npmjs.org/).
- Prevents accidental leakage of local npm configuration into the repository and avoids affecting CI/publish behavior.

## 2025-08-24 - 2.0.0 - BREAKING CHANGE(core)
Refactor core IPC: replace node-ipc with native transports and add IpcChannel / IpcServer / IpcClient with heartbeat, reconnection, request/response and pub/sub. Update tests and documentation.

- Replaced node-ipc with native Node.js transports (net module) and length-prefixed framing
- Added transport abstraction (IpcTransport) and implementations: UnixSocketTransport, NamedPipeTransport, TcpTransport plus createTransport factory
- Introduced IpcChannel with automatic reconnection (exponential backoff), heartbeat, request/response tracking, pending request timeouts and metrics
- Implemented IpcServer and IpcClient classes with client registration, pub/sub (subscribe/publish), broadcast, targeted messaging, client management and idle timeout handling
- Exported factory API via SmartIpc.createServer / createClient / createChannel and updated ts/index accordingly
- Updated and expanded README with usage, examples, advanced features and migration guidance; added readme.plan.md
- Added and updated comprehensive tests (test/test.ts, test/test.simple.ts) to cover TCP transport, messaging patterns, reconnection and metrics

## 2025-08-23 - 1.0.8 - chore
Metadata and configuration updates; repository/org migration.

- Update package description and general project metadata.
- Update TypeScript configuration (tsconfig).
- Update npmextra.json githost entries (multiple updates).
- Switch to new organization scheme for the repository.
- Miscellaneous minor updates.

## 2019-04-09 - 1.0.1 - 1.0.7 - core
Initial release and a series of patch fixes to core components.

- 1.0.1: initial release.
- 1.0.2 → 1.0.7: a sequence of small core fixes and maintenance updates (repeated "fix(core): update" commits).
## 2025-08-29 - 2.1.4 - feat(transports)
Add client-only mode to prevent unintended server auto-start in Unix/NamedPipe transports; safer probing

- Add `clientOnly?: boolean` to transport options; when true (or `SMARTIPC_CLIENT_ONLY=1`), a client will fail fast on `ECONNREFUSED`/`ENOENT` instead of auto-starting a server.
- Update `SmartIpc.waitForServer()` to probe with `clientOnly: true` to avoid races during readiness checks.
- Extend tests to cover option and env override; update core test to use unique socket path and auto-cleanup.
- Docs: add README section for client-only mode.