Evo
schema-validated RPC between client, server and UI runtimes.
type-safe, schema-based RPC system for distributed TypeScript applications. enables validated communication across client, server, and UI contexts.
features
-
built for distributed runtime environments
supports communication across client, server, and UI layers with a consistent, contract-driven interface.
-
contract-driven design
define RPC methods with
Zodschemas and auto-generate fully-typed APIs with runtime validation. -
cross-environment communication
handles bi-directional calls between
Client ⇄ Server,Client ⇄ UI, andUI ⇄ Client. -
retry and timeout handling
built-in support for configurable retry strategies, delay enforcement, and timeout safeguards.
-
runtime environment safety
prevents incorrect usage by validating the execution context before sending or handling RPC calls.
-
response routing and cleanup
uses UUIDs to track and clean up response listeners automatically for better memory and safety control.
usage
// 1. Define a contract using Zod for type-safe args and return values
import { z } from 'zod';
import { Contract } from '@smaiill/evo';
const userContract = new Contract({
getUser: {
args: z.object({ id: z.number() }),
returns: z.object({ name: z.string(), email: z.string() }),
},
}).build();// 2. Define a server-side RPC listener (RS = server, RC = client)
userContract.createListener('rs', 'rc', {
getUser: async ({ id }) => {
// Simulate user data fetching
return { name: 'Alice', email: 'alice@example.com' };
},
});// 3. Define a client-side API (RC = client, RS = server)
const api = userContract.createApi('rc', 'rs');
// Make a request to the server from the client
const user = await api.getUser({ id: 1 });
// Output: { name: string; email: string }// 4. Add retry options to make the method more resilient
const contractWithRetry = new Contract({
getUser: {
args: z.object({ id: z.number() }),
returns: z.object({ name: z.string() }),
retryOptions: {
max: 3, // Max 3 attempts
delay: 1000, // Wait 1 second between retries
forceDelay: false,
},
},
}).build();// 5. Global timeout for all API calls in the contract (in ms)
const contractWithTimeout = new Contract(
{
getUser: {
args: z.object({ id: z.number() }),
returns: z.object({ name: z.string() }),
},
},
{
timeout: 5000, // 5 seconds max timeout for RPC calls
}
).build(); stack
TypeScript, Zod