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 '@mionkit/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).

    Jargon

    Routes

    Methods that can be called remotely and have a URL assigned.

    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.

    Call Context

    The context passed to every route or middleFn method, contains data like request, response, and context data. It is always the first parameter of any route or middleFn handler.

    RunTypes

    mion uses @mionkit/run-types for automatic validation and serialization. When TypeScript gets compiled, extra bytecode is generated containing type metadata that can later be accessed at runtime and used for validation, serialization, and many other extra functionality.

    Powered by run-types

    mion uses @mionkit/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 '@mionkit/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)