@devgrid/netron
Version:
A powerful TypeScript library for building distributed systems with event bus, streaming capabilities, and remote object invocation. Features WebSocket-based bidirectional communication between Node.js and browser environments, service discovery, and type
270 lines (216 loc) • 7.07 kB
Markdown
# @devgrid/netron
A powerful TypeScript library for building distributed systems with event bus, streams, and remote object invocation capabilities. Built with WebSocket for real-time bidirectional communication between Node.js and browser environments.
## Features
- 🔄 Bidirectional WebSocket communication
- 📦 Remote object invocation (RPC)
- 🚀 Event bus with parallel and serial execution
- 💫 Streaming support
- 🛡️ TypeScript decorators for service definitions
- 🔍 Automatic service discovery
- ⚡ MessagePack serialization
- 🔒 Type-safe service interfaces
- 🔄 Automatic reconnection handling
- 📡 Service versioning support
## Installation
```bash
npm install @devgrid/netron
# or
yarn add @devgrid/netron
```
## Basic Usage
### Creating a Server
```typescript
import { Netron, Service, Public } from '@devgrid/netron';
@Service('calculator@1.0.0')
class Calculator {
@Public()
add(a: number, b: number): number {
return a + b;
}
@Public()
multiply(a: number, b: number): number {
return a * b;
}
@Public({ readonly: true })
version: string = '1.0.0';
}
const server = await Netron.create({
listenHost: 'localhost',
listenPort: 8080,
taskTimeout: 5000,
connectTimeout: 5000,
requestTimeout: 5000,
streamTimeout: 5000,
allowServiceEvents: true,
maxReconnectAttempts: 5
});
// Expose the calculator service
await server.peer.exposeService(new Calculator());
```
### Connecting from Client
```typescript
import { Netron } from '@devgrid/netron';
const client = await Netron.create();
const remotePeer = await client.connect('ws://localhost:8080');
// Query the calculator interface
const calculator = await remotePeer.queryInterface<ICalculator>('calculator@1.0.0');
// or latest version
const latestCalculator = await peer.queryInterface<ICalculator>('calculator');
// Use remote methods
const sum = await calculator.add(5, 3); // 8
const product = await calculator.multiply(4, 2); // 8
const version = await calculator.version; // '1.0.0'
```
## Advanced Features
### Event Bus
```typescript
// Server side
@Service('notifications')
class NotificationService {
@Public()
async broadcast(message: string) {
await this.netron.emitParallel('notification', { message });
}
}
// Client side
remotePeer.subscribe('notification', (data) => {
console.log('New notification:', data.message);
});
// Different emission patterns
await netron.emitParallel('event'); // Execute handlers in parallel
await netron.emitSerial('event'); // Execute handlers sequentially
await netron.emitReduce('event'); // Reduce pattern (left to right)
await netron.emitReduceRight('event'); // Reduce pattern (right to left)
```
### Streaming Support
```typescript
@Service('fileService')
class FileService {
@Public()
async streamFile(filename: string) {
const stream = createReadStream(filename);
return new ReadableStream(stream);
}
@Public()
async uploadFile(filename: string) {
const stream = createWriteStream(filename);
return new WritableStream(stream);
}
}
// Client usage
const fileService = await remotePeer.queryInterface('fileService');
const readStream = await fileService.streamFile('large.file');
for await (const chunk of readStream) {
console.log('Received chunk:', chunk);
}
```
### Task Management
```typescript
// Define a task
netron.addTask(async function pingTask(peer) {
return { status: 'ok', timestamp: Date.now() };
});
// Execute task on remote peer
const result = await remotePeer.runTask('pingTask');
```
### Service Decorators
```typescript
@Service('users')
class UserService {
@Public()
async getUser(id: number): Promise<User> {
return this.database.findUser(id);
}
@Public({ readonly: true })
currentUser: User;
// Private methods/properties are not exposed
private async validateUser(user: User) {
// ...
}
}
```
## Configuration Options
```typescript
interface NetronOptions {
id?: string; // Unique identifier for the Netron instance
listenHost?: string; // Host to listen on (server only)
listenPort?: number; // Port to listen on (server only)
taskTimeout?: number; // Timeout for task execution (default: 5000ms)
taskOverwriteStrategy?: 'replace' | 'skip' | 'throw'; // How to handle duplicate tasks
connectTimeout?: number; // Connection timeout (default: 5000ms)
requestTimeout?: number; // Request timeout (default: 5000ms)
streamTimeout?: number; // Stream timeout (default: 5000ms)
allowServiceEvents?: boolean; // Enable service events
maxReconnectAttempts?: number; // Maximum reconnection attempts (default: unlimited)
}
```
## API Reference
### Netron Class
```typescript
class Netron {
static create(options?: NetronOptions): Promise<Netron>;
connect(address: string): Promise<RemotePeer>;
disconnect(peerId: string): void;
addTask(fn: Task): string;
getServiceNames(): string[];
emitParallel(event: string, ...args: any[]): Promise<void>;
emitSerial(event: string, ...args: any[]): Promise<void>;
emitReduce(event: string, ...args: any[]): Promise<any>;
emitReduceRight(event: string, ...args: any[]): Promise<any>;
}
```
### Service Decorator Options
```typescript
interface ServiceMetadata {
name: string;
version: string;
properties: Record<string, PropertyInfo>;
methods: Record<string, MethodInfo>;
}
interface PropertyInfo {
type: string;
readonly: boolean;
}
interface MethodInfo {
type: string;
arguments: ArgumentInfo[];
}
interface ArgumentInfo {
index: number;
type: string;
}
```
### RemotePeer Methods
```typescript
class RemotePeer {
queryInterface<T>(qualifiedName: string): Promise<T>;
queryInterfaceByDefId<T>(defId: string, def?: Definition): T;
subscribe(eventName: string, handler: EventSubscriber): Promise<void>;
unsubscribe(eventName: string, handler: EventSubscriber): Promise<void>;
runTask(name: string, ...args: any[]): Promise<any>;
disconnect(): void;
getServiceNames(): string[];
}
```
## Performance Considerations
- Uses MessagePack for efficient serialization
- Supports parallel execution of event handlers
- Automatic cleanup of unused services
- Memory-efficient stream handling
- Connection pooling for multiple peers
- Automatic reconnection with exponential backoff
- Efficient binary protocol for WebSocket communication
## Browser Compatibility
- Modern browsers (Chrome, Firefox, Safari, Edge)
- WebSocket support required
- ES2018+ features used
- Some features may require polyfills in older browsers
## License
MIT
## Credits
Built with:
- [ws](https://github.com/websockets/ws) for WebSocket support
- [@devgrid/messagepack](https://github.com/devgrid/messagepack) for serialization
- [@devgrid/async-emitter](https://github.com/devgrid/async-emitter) for event handling
- [@devgrid/smartbuffer](https://github.com/devgrid/smartbuffer) for efficient binary operations
- [@devgrid/common](https://github.com/devgrid/common) for utility functions