Server
Router Overview
Core concepts and terminology used in mion APIs.
Features
- RPC-style routing: Direct method calls, no URL parsing or regex matching
- Automatic validation: All parameters are validated before execution using TypeScript types
- Automatic serialization: Complex types (Date, Map, Set, BigInt) serialized automatically
- MiddleFns (middleware): Execute code before/after routes for auth, logging, etc.
- Type-safe: Full TypeScript support with end-to-end type safety
- Lightweight & fast: Simple in-memory map for route lookup
- Nested routes: Organize routes in a hierarchical structure
Quick Example
import {Routes, route} from '@mionjs/router';
import {memoryStoreService as db} from './full-example.app.ts';
export const routes = {
sayHello: route((ctx, name1: string, name2: string): string => {
return `Hello ${name1} and ${name2}.`;
}),
getSomeData: route(async (ctx, id: string): Data | RpcError<'data-not-found'> => {
const data = await db.getData(id);
return data || new RpcError({publicMessage: 'Data not found', type: 'data-not-found'});
}),
} satisfies Routes;
Why return errors instead of throwing?
Returned errors are part of the function signature, giving the client full type information about possible error types and their data. The client can then handle each error type with autocompletion and type checking.
⚠️ Thrown errors are not strongly typed and should be treated as unexpected errors (not part of the Business logic).
Returned errors are part of the function signature, giving the client full type information about possible error types and their data. The client can then handle each error type with autocompletion and type checking.
⚠️ Thrown errors are not strongly typed and should be treated as unexpected errors (not part of the Business logic).
Jargon
MiddleFns
Auxiliary or (middleware) functions that get executed before or after a route. MiddleFns can send/receive data but cannot be called directly.
Execution Chain
Ordered list of all the methods to be executed when calling a route. Each Execution Chain can contain multiple MiddleFns but a single Route method.
Powered by run-types
mion uses @mionjs/run-types for automatic validation and serialization. When TypeScript is compiled, type metadata is extracted and used at runtime — no schemas to define or maintain.
What happens automatically:
- Validation: All route/middleFn parameters are validated before execution
- JSON Serialization: Complex types (Date, Map, Set, BigInt) are serialized correctly
- Type Errors: Detailed error messages when validation fails
- Zero Configuration: Works out of the box with your TypeScript types
import {Routes, route} from '@mionjs/router';
import {memoryStoreService} from './full-example.app.ts';
// Your TypeScript types ARE the validation schema
interface User {
id: string;
email: string;
age: number;
birthDate: Date;
tags: Set<string>;
}
type NewUser = Omit<User, 'id'>;
// mion automatically:
// 1. Restores Date and Set from JSON
// 2. Validates user parameter
const routes = {
createUser: route((ctx, user: NewUser): User => {
// user is already validated and types are restored
console.log(user.birthDate instanceof Date); // true
console.log(user.tags instanceof Set); // true
return memoryStoreService.createUser(user);
}),
} satisfies Routes;
RPC vs REST
Some advantages of an RPC architecture:
- Type Safety
- Fewer abstractions
- Better client-server integration
For more detailed insights into different API types and their pros and cons, check out Nate Barbettini's presentation (API Throw-down: RPC vs REST vs GraphQL)