@devgrid/netron
Version:
Event bus, streams and remote object invocation.
277 lines (213 loc) • 6.21 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
- 🌐 Cross-platform (Node.js and Browser)
- 🔄 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
- 🎯 Task management system
## 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')
class Calculator {
@Public()
add(a: number, b: number): number {
return a + b;
}
@Public()
multiply(a: number, b: number): number {
return a * b;
}
}
const server = await Netron.create({
listenHost: 'localhost',
listenPort: 8080
});
// 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('calculator');
// Use remote methods
const sum = await calculator.add(5, 3); // 8
const product = await calculator.multiply(4, 2); // 8
```
## 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) {
// ...
}
}
```
## Browser Support
The library works seamlessly in modern browsers thanks to WebSocket support:
### Using with Bundlers
```typescript
// webpack/rollup/esbuild
import { Netron } from '@devgrid/netron';
const client = await Netron.create();
const peer = await client.connect('ws://server.com:8080');
```
### Browser-Specific Setup
```html
<!-- Include required dependencies -->
<script src="https://unpkg.com/reflect-metadata/Reflect.js"></script>
<script src="path/to/netron.min.js"></script>
<script>
const client = await Netron.create();
// Connect to server
const peer = await client.connect('ws://server.com:8080');
// Use services
const service = await peer.queryInterface('myService');
const result = await service.doSomething();
</script>
```
### Bundler Configuration
#### Webpack
```javascript
module.exports = {
resolve: {
fallback: {
"ws": false, // Browser will use native WebSocket
"buffer": require.resolve("buffer/")
}
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer']
})
]
};
```
## API Reference
### Netron Class
```typescript
class Netron {
static create(options?: NetronOptions): Promise<Netron>;
connect(address: string, abilities?: Abilities): Promise<RemotePeer>;
disconnect(peerId: string): void;
addTask(fn: Task): void;
getServiceNames(): string[];
}
```
### Service Decorator Options
```typescript
interface ServiceMetadata {
name: string;
properties: Record<string, PropertyInfo>;
methods: Record<string, MethodInfo>;
}
interface PropertyInfo {
type: string;
readonly: boolean;
}
interface MethodInfo {
type: string;
arguments: ArgumentInfo[];
}
```
### RemotePeer Methods
```typescript
class RemotePeer {
queryInterface<T>(serviceName: string): Promise<T>;
subscribe(eventName: string, handler: EventSubscriber): Promise<void>;
unsubscribe(eventName: string, handler: EventSubscriber): Promise<void>;
runTask(name: string, ...args: any[]): Promise<any>;
}
```
## 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
## 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