Skip to content

Server

The high-level server wrapper that handles service registration, endpoint creation, and health endpoints.

import { AsterServer } from '@aster-rpc/aster';
import { HelloService } from './service.js';
const server = new AsterServer({
services: [new HelloService()],
config: {
logFormat: 'json',
},
});
await server.start();
console.log("Producer ready at:", server.address);
await server.serve(); // blocks until shutdown
Option Type Default Description
services object[] Required Array of @Service-decorated instances
config Partial<AsterConfig> {} Override config values
identity string undefined Path to a .aster-identity TOML file
peer string undefined Peer name to load from the identity file
allowAllConsumers boolean true Open-gate mode (dev). Set false for trusted mode.
interceptors Interceptor[] [] Server-side interceptors
Method Returns Description
start() Promise<void> Start the server (create node, publish contracts, open admission)
serve() Promise<void> Block until the server is shut down (Ctrl+C in scripts)
close() Promise<void> Graceful shutdown
localTransport() LocalTransport In-process transport for testing
Property Type Description
address string aster1... ticket consumers connect to
running boolean Whether the server is running
registry ServiceRegistry The service registry
config AsterConfig Resolved configuration
import { ServiceRegistry, LocalTransport } from '@aster-rpc/aster';
import { HelloService } from './service.js';
const registry = new ServiceRegistry();
registry.register(new HelloService());
const transport = new LocalTransport(registry);
Method Returns Description
register(instance) ServiceInfo Register a @Service-decorated instance
lookup(name, version?) ServiceInfo | undefined Look up by name and optional version
lookupMethod(service, method) [ServiceInfo, MethodInfo] | undefined Look up a specific method
services() IterableIterator<ServiceInfo> All registered services
size number Number of registered services
@Service({ name: "Echo", version: 1 })
class EchoService { ... }
@Rpc({ timeout: 30, idempotent: true })
async echo(req: EchoRequest): Promise<EchoResponse> { ... }

The aster-gen build step reads request/response types from the AST, so you don’t need to pass them in the decorator. Optional keys: timeout, idempotent, requires, serialization. See TypeScript Build Setup.

@ServerStream()
async *watchItems(req: WatchRequest): AsyncGenerator<ItemUpdate> { ... }
@ClientStream()
async uploadBatch(requests: AsyncIterable<Item>): Promise<BatchResult> { ... }
@BidiStream()
async *chat(requests: AsyncIterable<Message>): AsyncGenerator<Message> { ... }
@WireType("myapp/Invoice")
class Invoice {
amount = 0;
currency = "USD";
constructor(init?: Partial<Invoice>) { if (init) Object.assign(this, init); }
}

All 9 interceptors from the Python binding are available:

import {
DeadlineInterceptor,
MetricsInterceptor,
RetryInterceptor,
RateLimitInterceptor,
AuthInterceptor,
CircuitBreakerInterceptor,
CompressionInterceptor,
AuditLogInterceptor,
CapabilityInterceptor,
} from '@aster-rpc/aster';
const metrics = new MetricsInterceptor();
const rateLimit = new RateLimitInterceptor({ globalRps: 1000, perServiceRps: 500 });

See the Python Server Reference for detailed interceptor documentation — the TypeScript API mirrors it exactly.