Typescript Full Stack APIsAt The Speed Of Light ⚡

mion is the definitive TypeScript Framework for Full Stack APIs.
It offers The best Developer Experience for building Single Page Apps.

Mion Features

RPC Like

RPC architecture for simpler and easier to consume APIs. Just use remote methods as any other local async method.
mion is focused on offering the best developer experience.


Fully validation adn serialization of params and results out of the box.

mion-router.ts
// packages/examples/src/_homepage/home-server.tsimport {function initMionRouter<R extends Routes>(routes: R, opts?: Partial<RouterOptions>): Promise<PublicApi<R>>initMionRouter, function route<H extends Handler>(handler: H, opts?: RouteOptions): RouteDef<H>route, Routes} from '@mionkit/router';import {function startNodeServer(options?: Partial<NodeHttpOptions>): Promise<Server | Server>startNodeServer} from '@mionkit/node';
Automatic Validation and Serialization from Typescript types
interface User { User.id: numberid: number; User.name: stringname: string; User.age: numberage: number; User.createdAt: DatecreatedAt: Date; User.tags: Set<string>tags: Set<string>;}interface Order { Order.id: stringid: string; Order.userId: numberuserId: number; Order.amount: numberamount: number }
Object based router with rpc methods that receive Fully Validated params
const
const routes: {    getUser: RouteDef<(ctx: any, id: number) => User | null>;    getOrder: RouteDef<(ctx: any, id: string) => Order | null>;    sayHello: RouteDef<(ctx: any, name: string) => string>;}
routes
= {
getUser: RouteDef<(ctx: any, id: number) => User | null>getUser: route<(ctx: any, id: number) => User | null>(handler: (ctx: any, id: number) => User | null, opts?: RouteOptions): RouteDef<(ctx: any, id: number) => User | null>route((ctx: anyctx, id: numberid: number): User | null => { const const tags: Set<string>tags = new
var Set: SetConstructornew <string>(iterable?: Iterable<string>) => Set<string> (+1 overload)
Set
(['tag1', 'tag2'])
const const user: Useruser: User = {User.id: numberid: 1234, User.name: stringname: 'John',User.age: numberage: 30, User.createdAt: DatecreatedAt: new
var Date: DateConstructornew () => Date (+4 overloads)
Date
(), User.tags: Set<string>tags};
if (id: numberid === 1234) return const user: Useruser; return null; }), getOrder: RouteDef<(ctx: any, id: string) => Order | null>getOrder: route<(ctx: any, id: string) => Order | null>(handler: (ctx: any, id: string) => Order | null, opts?: RouteOptions): RouteDef<(ctx: any, id: string) => Order | null>route((ctx: anyctx, id: stringid: string): Order | null => { const const order: Orderorder: Order = {Order.id: stringid: 'ORDER-123', Order.userId: numberuserId: 1234, Order.amount: numberamount: 100}; if (id: stringid === 'ORDER-123') return const order: Orderorder; return null; }), sayHello: RouteDef<(ctx: any, name: string) => string>sayHello: route<(ctx: any, name: string) => string>(handler: (ctx: any, name: string) => string, opts?: RouteOptions): RouteDef<(ctx: any, name: string) => string>route((ctx: anyctx, name: stringname: string): string => `Hello ${name: stringname}`),} satisfies Routes;export const
const myApi: {    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}
myApi
= await
initMionRouter<{    getUser: RouteDef<(ctx: any, id: number) => User | null>;    getOrder: RouteDef<(ctx: any, id: string) => Order | null>;    sayHello: RouteDef<(ctx: any, name: string) => string>;}>(routes: {    getUser: RouteDef<(ctx: any, id: number) => User | null>;    getOrder: RouteDef<(ctx: any, id: string) => Order | null>;    sayHello: RouteDef<(ctx: any, name: string) => string>;}, opts?: Partial<RouterOptions>): Promise<{    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<...>;    sayHello: PublicRoute<...>;}>
initMionRouter
(
const routes: {    getUser: RouteDef<(ctx: any, id: number) => User | null>;    getOrder: RouteDef<(ctx: any, id: string) => Order | null>;    sayHello: RouteDef<(ctx: any, name: string) => string>;}
routes
);
export type
type MyApi = {    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}
MyApi
= typeof
const myApi: {    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}
myApi
;
function startNodeServer(options?: Partial<NodeHttpOptions>): Promise<Server | Server>startNodeServer({port?: numberport: 3000});

Fully Typed Client

Fully typed client that seamlessly bridges frontend and backend with static type checking, autocompletion, automatic validation and serialization.


Lightweight and framework-agnostic — use it with React, Vue, Svelte, or any frontend framework.

mion-client.ts
// packages/examples/src/_homepage/home-client.tsimport {
function initClient<RM extends RemoteApi>(options: InitOptions): {    client: MionClient;    routes: ClientRoutes<RM>;    middleFns: ClientMiddleFns<RM>;}
initClient
} from '@mionkit/client';
import type {
type MyApi = {    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}
MyApi
} from './home-server.ts';
const {
const routes: {    getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>;    getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>;    sayHello: (name: string) => RSubRequest<(name: string) => Promise<string>>;}
routes
} =
initClient<{    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}>(options: InitOptions): {    client: MionClient;    routes: {        getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>;        getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>;        sayHello: (name: string) => RSubRequest<...>;    };    middleFns: {};}
initClient
<
type MyApi = {    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}
MyApi
>({
baseURL: stringbaseURL: 'http://localhost:3000',});
Autocomplete: shows available routes
const [const user: Useruser, const error: ValidationErrorerror] = await
const routes: {    getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>;    getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>;    sayHello: (name: string) => RSubRequest<(name: string) => Promise<string>>;}
routes
.
  • getOrder
  • getUser
  • sayHello
getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>getUser(1234).RSubRequest<(id: number) => Promise<User>>.call: () => Promise<Result<User, ValidationError, Record<string, unknown>, Record<string, ValidationError | RpcError<string, unknown>>>>
Calls a remote route and returns a Result 4-tuple with full typing preserved
call
();
if (const user: Useruser) { const user: Useruser.
User.createdAt: Date
createdAt
;
Native Classes are automatically restored to their original types
const user: Useruser.
User.tags: Set<string>
tags
;
}// Type error: id must be a number
const routes: {    getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>;    getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>;    sayHello: (name: string) => RSubRequest<(name: string) => Promise<string>>;}
routes
.getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>getUser('1234').RSubRequest<(id: number) => Promise<User>>.call: () => Promise<Result<User, ValidationError, Record<string, unknown>, Record<string, ValidationError | RpcError<string, unknown>>>>
Calls a remote route and returns a Result 4-tuple with full typing preserved
call
();
Argument of type 'string' is not assignable to parameter of type 'number'.

Routes Flows

Execute multiple routes in a single HTTP request. Batch API calls together, and Orchestrate router logic from the client.


GraphQL-like data composition with the simplicity of RPC — resolve relationships in a single request using mapFrom.
mion-routesFlow.ts
// packages/examples/src/_homepage/home-mapFrom.tsimport {
function initClient<RM extends RemoteApi>(options: InitOptions): {    client: MionClient;    routes: ClientRoutes<RM>;    middleFns: ClientMiddleFns<RM>;}
initClient
, function routesFlow<Routes extends RSubRequest<any>[], MiddleFns extends Record<string, HSubRequest<any>> = Record<string, never>>(routeSubRequests: [...Routes], middleFns?: MiddleFns): Promise<WorkflowResult<Routes, MiddleFns>>
Creates and executes a routesFlow request with multiple routes
routesFlow
, function mapFrom<FromSR extends SubRequest<any>, MappedInput>(source: FromSR, mapper: (value: FromSR["resolvedValue"]) => MappedInput, bodyHash?: string): MapFromServerFnRef<(value: FromSR["resolvedValue"]) => MappedInput>
Maps the output of one route SubRequest to the input of another within a routesFlow. The mapper function must be pure (same rules as pureServerFn). The bodyHash is injected at build time by the mion vite plugin.
mapFrom
} from '@mionkit/client';
import type {
type MyApi = {    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}
MyApi
} from './home-server.ts';
const {
const routes: {    getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>;    getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>;    sayHello: (name: string) => RSubRequest<(name: string) => Promise<string>>;}
routes
} =
initClient<{    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}>(options: InitOptions): {    client: MionClient;    routes: {        getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>;        getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>;        sayHello: (name: string) => RSubRequest<...>;    };    middleFns: {};}
initClient
<
type MyApi = {    getUser: PublicRoute<(id: number) => Promise<User>>;    getOrder: PublicRoute<(id: string) => Promise<Order>>;    sayHello: PublicRoute<(name: string) => Promise<string>>;}
MyApi
>({baseURL: stringbaseURL: 'http://localhost:3000'});
const const orderReq: RSubRequest<(id: string) => Promise<Order>>orderReq =
const routes: {    getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>;    getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>;    sayHello: (name: string) => RSubRequest<(name: string) => Promise<string>>;}
routes
.getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>getOrder('ORDER-123');
mapFrom order.userId → getUser input, (mapping function runs server-side)
const const userIdMapping: numberuserIdMapping = mapFrom<RSubRequest<(id: string) => Promise<Order>>, number>(source: RSubRequest<(id: string) => Promise<Order>>, mapper: (value: Order) => number, bodyHash?: string): MapFromServerFnRef<(value: Order) => number>
Maps the output of one route SubRequest to the input of another within a routesFlow. The mapper function must be pure (same rules as pureServerFn). The bodyHash is injected at build time by the mion vite plugin.
mapFrom
(const orderReq: RSubRequest<(id: string) => Promise<Order>>orderReq, (order: Orderorder) => order: Orderorder!.Order.userId: numberuserId).MapFromServerFnRef<(value: Order) => number>.type(): number
Returns this reference cast as ReturnType<F>, allowing it to be passed as a parameter to subrequests
type
();
const const userReq: RSubRequest<(id: number) => Promise<User>>userReq =
const routes: {    getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>;    getOrder: (id: string) => RSubRequest<(id: string) => Promise<Order>>;    sayHello: (name: string) => RSubRequest<(name: string) => Promise<string>>;}
routes
.getUser: (id: number) => RSubRequest<(id: number) => Promise<User>>getUser(const userIdMapping: numberuserIdMapping);
const [[const order: Orderorder, const user: Useruser]] = await routesFlow<[RSubRequest<(id: string) => Promise<Order>>, RSubRequest<(id: number) => Promise<User>>], Record<string, never>>(routeSubRequests: [RSubRequest<(id: string) => Promise<Order>>, RSubRequest<(id: number) => Promise<User>>], middleFns?: Record<string, never>): Promise<WorkflowResult<[RSubRequest<(id: string) => Promise<Order>>, RSubRequest<(id: number) => Promise<User>>], Record<...>>>
Creates and executes a routesFlow request with multiple routes
routesFlow
([const orderReq: RSubRequest<(id: string) => Promise<Order>>orderReq, const userReq: RSubRequest<(id: number) => Promise<User>>userReq]);
if (const order: Orderorder && const user: Useruser) { console.log(`Order ${const order: Orderorder.Order.id: stringid} placed by ${const user: Useruser.User.name: stringname}`);}

RunTypes ©

mion use RunTypes behinds the scene to generate JIT-compiled validation and serialization functions directly from TypeScript types. RunTypes supports advanced type formats and can be used as a standalone library.


No schemas libraries needed — Typescript is the single source of truth.

mion-run-types.ts
// packages/examples/src/_homepage/home-run-types.tsimport {function createIsTypeFn<T>(opts?: RunTypeOptions, type?: ReceiveType<T>): Promise<IsTypeFn>
Returns a function that checks if the given value is of the specified type.
createIsTypeFn
, function createStringifyJsonFn<T>(opts?: RunTypeOptions, type?: ReceiveType<T>): Promise<JsonStringifyFn>
Returns a function that stringifies a javascript value to a json string. Stringifies special types like dates, bigints, maps, set, etc... Is equivalent to calling prepareForJson and then json.stringify but more efficient.
createStringifyJsonFn
, function createMockTypeFn<T>(type?: ReceiveType<T>): Promise<(opts?: Partial<RunTypeOptions>) => T>
Returns a function that mocks a value of the specified type.
createMockTypeFn
, function createToBinaryFn<T>(opts?: RunTypeOptions, type?: ReceiveType<T>): Promise<ToBinaryFn>
Returns a function that serializes any type value to a binary format.
createToBinaryFn
} from '@mionkit/run-types';
interface User { User.id: stringid: string; User.name: stringname: string; User.createdAt: DatecreatedAt: Date; User.tags: Set<string>tags: Set<string>;}
Create JIT-compiled functions directly from TypeScript types
const const isUser: IsTypeFnisUser = await createIsTypeFn<User>(opts?: RunTypeOptions, type?: ReceiveType<User>): Promise<IsTypeFn>
Returns a function that checks if the given value is of the specified type.
createIsTypeFn
<User>();
const const stringify: JsonStringifyFnstringify = await createStringifyJsonFn<User>(opts?: RunTypeOptions, type?: ReceiveType<User>): Promise<JsonStringifyFn>
Returns a function that stringifies a javascript value to a json string. Stringifies special types like dates, bigints, maps, set, etc... Is equivalent to calling prepareForJson and then json.stringify but more efficient.
createStringifyJsonFn
<User>();
const const toBinary: ToBinaryFntoBinary = await createToBinaryFn<User>(opts?: RunTypeOptions, type?: ReceiveType<User>): Promise<ToBinaryFn>
Returns a function that serializes any type value to a binary format.
createToBinaryFn
<User>();
const const mockUser: (opts?: Partial<RunTypeOptions>) => UsermockUser = await createMockTypeFn<User>(type?: ReceiveType<User>): Promise<(opts?: Partial<RunTypeOptions>) => User>
Returns a function that mocks a value of the specified type.
createMockTypeFn
<User>();
Generate mock data - respects type structure
const
const user: User
user
= const mockUser: (opts?: Partial<RunTypeOptions>) => UsermockUser();
Validate data at runtime
const isUser: (value: any) => booleanisUser(const user: Useruser);
Serialize complex types (Date, Set, unions) to JSON
const
const json: string
json
= const stringify: (value: any) => JSONStringstringify(const user: Useruser);

Drizzle ORM

Auto-generate Drizzle ORM table schemas directly from types using reflection.
Simply extends your types with SQL/Drizzle specific configuration.

Keep DB and Validation/Serialization logic separated.

mion-drizzle.ts
// packages/examples/src/_homepage/home-drizzle.tsimport {
function mapPGTable<T>(config?: DrizzleMapperConfig, type?: ReceiveType<T>): {    build<TN extends string, TConfig extends PgTableConfig<T>>(tableName: TN, tableConfig?: TConfig): PgTableWithColumns<{        name: TN;        schema: undefined;        columns: BuildColumns<TN, MergedPgColumns<...>, "pg">;        dialect: "pg";    }>;}
Creates a PostgreSQL table schema from a TypeScript type. Auto-generates drizzle column definitions based on the type's properties. Use .build(tableName, config?) to create the table with optional column overrides.
@example```typescript interface User { id: StrUUIDv7; email: StrEmail; name: string; age: number; createdAt: Date; } // Without overrides - auto-generates all columns const users = mapPGTable<User>().build('users'); // With overrides - customize specific columns const users = mapPGTable<User>().build('users', { id: uuid('id').primaryKey(), }); // With custom lengthBuffer for varchar columns const users = mapPGTable<User>({lengthBuffer: 2.0}).build('users'); ```
mapPGTable
} from '@mionkit/drizzle';
import {function uuid(): PgUUIDBuilderInitial<""> (+1 overload)uuid, function text(): PgTextBuilderInitial<"", [string, ...string[]]> (+2 overloads)text, function timestamp(): PgTimestampBuilderInitial<""> (+2 overloads)timestamp} from 'drizzle-orm/pg-core';// Note: Must use regular import (not `import type`) for reflection to workimport {
type StrUUIDv7 = string & {    brand: "uuid";}
UUID v7 format, always branded with 'uuid'.
StrUUIDv7
,
type StrEmail<EP extends FormatParams_Email = DEFAULT_EMAIL_PARAMS<RegExp, EMAIL_SAMPLES>> = string & {    brand: "email";}
Email format, always branded with 'email'.
StrEmail
} from '@mionkit/type-formats/FormatsString';
Define Models using type-formats for validation and serialization functionality
interface User {
User.id: string & {    brand: "uuid";}
id
:
type StrUUIDv7 = string & {    brand: "uuid";}
UUID v7 format, always branded with 'uuid'.
StrUUIDv7
;
User.email: string & {    brand: "email";}
email
:
type StrEmail<EP extends FormatParams_Email = DEFAULT_EMAIL_PARAMS<RegExp, EMAIL_SAMPLES>> = string & {    brand: "email";}
Email format, always branded with 'email'.
StrEmail
;
User.name: stringname: string; User.bio?: stringbio?: string; User.age: numberage: number; User.createdAt: DatecreatedAt: Date;}
Auto-generate Drizzle table cond configure keys, indexes, etc..
const
const users: PgTableWithColumns<{    name: "users";    schema: undefined;    columns: {        id: PgColumn<{            name: "id";            tableName: "users";            dataType: "string";            columnType: "PgUUID";            data: string;            driverParam: string;            notNull: true;            hasDefault: false;            isPrimaryKey: true;            isAutoincrement: false;            hasRuntimeDefault: false;            enumValues: undefined;            baseColumn: never;            identity: undefined;            generated: undefined;        }, {}, {}>;        email: PgColumn<{            name: "email";            tableName: "users";            dataType: "string";            columnType: "PgText";            data: string;            driverParam: string;            notNull: true;            hasDefault: false;            isPrimaryKey: false;            isAutoincrement: false;            hasRuntimeDefault: false;            enumValues: [...];            baseColumn: never;            identity: undefined;            generated: undefined;        }, {}, {}>;        name: PgColumn<...>;        bio?: PgColumn<...>;        age: PgColumn<...>;        createdAt: PgColumn<...>;    };    dialect: "pg";}>
users
=
mapPGTable<User>(config?: DrizzleMapperConfig, type?: ReceiveType<User>): {    build<TN, TConfig>(tableName: TN, tableConfig?: TConfig): PgTableWithColumns<{        name: TN;        schema: undefined;        columns: {            id: PgColumn<{                name: (Omit<("id" extends keyof TConfig ? TConfig[keyof TConfig & "id"] extends PgColumnBuilderBase<ColumnBuilderBaseConfig<ColumnDataType, string>, object> ? TConfig[keyof TConfig & "id"] : PgColumnType<...> : PgUUIDBuilderInitial<...>)["_"], "name"> & {                    ...;                })["name"];                ... 13 more ...;                generated: Omit<...> & {                    ...;                } extends {                    ...;                } ? unknown extends G ? undefined : G extends undefined ? undefined : G : undefined;            }, {}, { [K in keyof Omit<...>]: Omit<...>[K]; }>;            ... 4 more ...;            createdAt: PgColumn<...>;        };        dialect: "pg";    }>;}
Creates a PostgreSQL table schema from a TypeScript type. Auto-generates drizzle column definitions based on the type's properties. Use .build(tableName, config?) to create the table with optional column overrides.
@example```typescript interface User { id: StrUUIDv7; email: StrEmail; name: string; age: number; createdAt: Date; } // Without overrides - auto-generates all columns const users = mapPGTable<User>().build('users'); // With overrides - customize specific columns const users = mapPGTable<User>().build('users', { id: uuid('id').primaryKey(), }); // With custom lengthBuffer for varchar columns const users = mapPGTable<User>({lengthBuffer: 2.0}).build('users'); ```
mapPGTable
<User>().
build<"users", {    id: IsPrimaryKey<NotNull<PgUUIDBuilderInitial<"id">>>;    email: NotNull<PgTextBuilderInitial<"email", [string, ...string[]]>>;}>(tableName: "users", tableConfig?: {    id: IsPrimaryKey<NotNull<PgUUIDBuilderInitial<"id">>>;    email: NotNull<PgTextBuilderInitial<"email", [string, ...string[]]>>;}): PgTableWithColumns<{    name: "users";    schema: undefined;    columns: {        id: PgColumn<{            name: "id";            tableName: "users";            dataType: "string";            ... 11 more ...;            generated: undefined;        }, {}, {}>;        ... 4 more ...;        createdAt: PgColumn<...>;    };    dialect: "pg";}>
build
('users', {
id: IsPrimaryKey<NotNull<PgUUIDBuilderInitial<"id">>>id: uuid<"id">(name: "id"): PgUUIDBuilderInitial<"id"> (+1 overload)uuid('id').ColumnBuilder<{ name: "id"; dataType: "string"; columnType: "PgUUID"; data: string; driverParam: string; enumValues: undefined; }, object, object & { dialect: "pg"; }, ColumnBuilderExtraConfig>.primaryKey(): IsPrimaryKey<NotNull<PgUUIDBuilderInitial<"id">>>
Adds a `primary key` clause to the column definition. This implicitly makes the column `not null`. In SQLite, `integer primary key` implicitly makes the column auto-incrementing.
primaryKey
(),
email: NotNull<PgTextBuilderInitial<"email", [string, ...string[]]>>email: text<"email", string, readonly [string, ...string[]]>(name: "email", config?: PgTextConfig<[string, ...string[]] | readonly [string, ...string[]]>): PgTextBuilderInitial<"email", [string, ...string[]]> (+2 overloads)text('email').ColumnBuilder<{ name: "email"; dataType: "string"; columnType: "PgText"; data: string; enumValues: [string, ...string[]]; driverParam: string; }, { enumValues: [string, ...string[]]; }, object & { dialect: "pg"; }, ColumnBuilderExtraConfig>.notNull(): NotNull<PgTextBuilderInitial<"email", [string, ...string[]]>>
Adds a `not null` clause to the column definition. Affects the `select` model of the table - columns *without* `not null` will be nullable on select.
notNull
().
PgColumnBuilder<{ name: "email"; dataType: "string"; columnType: "PgText"; data: string; enumValues: [string, ...string[]]; driverParam: string; }, { enumValues: [string, ...string[]]; }, object, ColumnBuilderExtraConfig>.unique(name?: string, config?: {    nulls: "distinct" | "not distinct";}): NotNull<PgTextBuilderInitial<"email", [string, ...string[]]>>
unique
(),
});
The table schema is fully typed - columns match your interface
const users: PgTableWithColumns<{    name: "users";    schema: undefined;    columns: {        id: PgColumn<{            name: "id";            tableName: "users";            dataType: "string";            columnType: "PgUUID";            data: string;            driverParam: string;            notNull: true;            hasDefault: false;            isPrimaryKey: true;            isAutoincrement: false;            hasRuntimeDefault: false;            enumValues: undefined;            baseColumn: never;            identity: undefined;            generated: undefined;        }, {}, {}>;        email: PgColumn<{            name: "email";            tableName: "users";            dataType: "string";            columnType: "PgText";            data: string;            driverParam: string;            notNull: true;            hasDefault: false;            isPrimaryKey: false;            isAutoincrement: false;            hasRuntimeDefault: false;            enumValues: [...];            baseColumn: never;            identity: undefined;            generated: undefined;        }, {}, {}>;        name: PgColumn<...>;        bio?: PgColumn<...>;        age: PgColumn<...>;        createdAt: PgColumn<...>;    };    dialect: "pg";}>
users
.
id: PgColumn<{    name: "id";    tableName: "users";    dataType: "string";    columnType: "PgUUID";    data: string;    driverParam: string;    notNull: true;    hasDefault: false;    isPrimaryKey: true;    isAutoincrement: false;    hasRuntimeDefault: false;    enumValues: undefined;    baseColumn: never;    identity: undefined;    generated: undefined;}, {}, {}>
id
;

Binary Serialization 🚀

Our binary protocol is designed to support al Typescript features: unions, optional props, rest params, circular types and any type you can think about!

Achieve smaller payloads and faster data transfer with automatic binary serialization for Dates, BigInts, Maps, Sets, and complex nested types.

Write Once Run Everywhere

Run mion APIs in Node.js, Bun or Serverless platforms like Aws Lambda and Google cloud functions.

Solid Performance

  • RPC-style routing - No URL parsing or regex matching, just direct in-memory Map lookup
  • JIT-compiled validation/serialization - RunTypes generates optimized functions at startup
  • Fast cold starts - Load routes in demand, no need to load all routes and jit functions at startup
  • Lightweight architecture - Simple request/response handling
  •