foundations/net/examples/README.md
This directory contains comprehensive examples demonstrating various aspects of the Huly Virtual Network.
All examples have been updated to demonstrate the new typed proxies using the cast<T>() method. This provides:
See PROXY_MIGRATION.md for detailed migration guide.
// Define your service interface
interface MyService {
getData: (id: string) => Promise<{ data: any }>
updateData: (id: string, data: any) => Promise<boolean>
}
// On client side - use cast() for typed proxy
const containerRef = await client.get('my-service', {})
const service = containerRef.cast<MyService>('MyService')
// Call methods with full type safety
const result = await service.getData('123')
await service.updateData('123', { updated: true })
All examples in this directory use the await using keyword for automatic client disposal. This ensures proper cleanup when the example completes or if an error occurs. For production services that need to run indefinitely, you should use manual lifecycle management instead. See docs/AUTO_DISPOSAL_GUIDE.md for detailed guidance.
Before running any example, make sure you have:
Built the project:
node common/scripts/install-run-rush.js build
Either start a standalone network server:
cd pods/network-pod && rushx dev
Or let the example start its own network server (most examples do this).
Run an example:
cd examples
rushx run:basic
File: 01-basic-container-request-response.ts
Learn the fundamentals of creating containers with typed proxies. This example shows:
createProxyHandlercast<T>() method for typed proxiesKey concepts:
// Define interface
interface DataProcessorService {
store: (key: string, value: any) => Promise<{ success: boolean }>
retrieve: (key: string) => Promise<{ success: boolean; value: any }>
}
// Use typed proxy
const processor = containerRef.cast<DataProcessorService>('DataProcessorService')
await processor.store('key', value)
Use case: Simple data storage service, key-value stores, stateful services
File: 02-event-broadcasting.ts
Demonstrates real-time event broadcasting to multiple connected clients with typed proxies. Features:
Key concepts:
// Define interface
interface ChatRoomService {
sendMessage: (username: string, text: string) => Promise<{ success: boolean }>
getHistory: () => Promise<{ messages: ChatMessage[] }>
}
// Use typed proxy
const chat = connection.cast<ChatRoomService>('ChatRoomService')
await chat.sendMessage('Alice', 'Hello!')
const history = await chat.getHistory()
Use case: Chat systems, real-time notifications, collaborative editing, live dashboards
File: 03-multi-tenant.ts
Shows how to build multi-tenant applications with isolated workspaces. Includes:
Use case: SaaS applications, workspace management, multi-tenant platforms
File: 04-complete-production-setup.ts
A comprehensive production-ready example with:
Use case: Production deployments, enterprise systems, mission-critical services
File: 05-error-handling-retry.ts
Advanced error handling patterns including:
Use case: Unreliable networks, external service integration, fault-tolerant systems
File: custom-timeout-example.ts
Shows how to configure different timeouts for various environments:
Use case: Environment-specific configuration, debugging, performance tuning
File: ha-stateless-container-example.ts
Demonstrates automatic failover with stateless containers:
Use case: Leader election, active-passive HA, single-instance services with failover
Start with these examples to learn the basics:
01-basic-container-request-response.tscustom-timeout-example.tsBuild real applications with these patterns:
02-event-broadcasting.ts - Real-time features03-multi-tenant.ts - SaaS applicationsProduction-ready patterns:
04-complete-production-setup.ts - Full production setup05-error-handling-retry.ts - Robust error handlingha-stateless-container-example.ts - High availabilityMake sure you have installed dependencies:
rush install
cd examples
rushx run:basic # Run basic container request-response example
All available examples:
rushx run:basic - Basic container request-responserushx run:events - Event broadcastingrushx run:multi-tenant - Multi-tenant setuprushx run:production - Complete production setuprushx run:retry - Error handling and retryrushx run:timeout - Custom timeout configurationrushx run:ha - High-availability stateless containersMost examples connect to localhost:3737 by default. To use a different host:
const client = createNetworkClient('your-host:3737')
Run with longer timeouts for debugging:
cd examples
NODE_ENV=development rushx run:basic
import type { Container, ContainerUuid, ClientUuid } from '@hcengineering/network-core'
class MyContainer implements Container {
constructor(readonly uuid: ContainerUuid) {}
async request(operation: string, data?: any, clientId?: ClientUuid): Promise<any> {
switch (operation) {
case 'myOperation':
return { success: true, result: 'data' }
default:
return { success: false, error: 'Unknown operation' }
}
}
async ping(): Promise<void> {}
async terminate(): Promise<void> {}
connect(clientId: ClientUuid, broadcast: (data: any) => Promise<void>): void {}
disconnect(clientId: ClientUuid): void {}
}
import { createNetworkClient } from '@hcengineering/network-client'
const client = createNetworkClient('localhost:3737')
await client.waitConnection(5000)
const containerRef = await client.get('my-service' as any, {})
const result = await containerRef.request('myOperation', { data: 'value' })
await containerRef.close()
await client.close()
import { createNetworkClient } from '@hcengineering/network-client'
const client = createNetworkClient('localhost:3737')
await client.waitConnection(5000)
await client.serveAgent('localhost:3738', {
'my-service': async (options) => {
const uuid = options.uuid ?? generateUuid()
const container = new MyContainer(uuid)
return {
uuid,
container,
endpoint: `my-service://host/${uuid}` as any
}
}
})
// Agent server is already started and registered to network
createNetworkClient('host:port', 3600)The examples use dynamic container kinds (strings) which may show TypeScript errors. This is expected and doesn't affect functionality. In production, define proper types:
type MyContainerKind = 'my-service' as ContainerKind
To contribute a new example:
XX-descriptive-name.tsExample template structure:
Need help? Open an issue on GitHub or check the main documentation.