Bun Http Server

Bun http wrapper around the mion router. It takes care of handling the http requests and passing them down to the router.

This is using bun's native http server to take advantage of bun's performance. Check the benchmarks section for results.

Init a Bun Server

init Bun
import {BunHttpOptions, setBunHttpOpts, startBunServer} from '@mionkit/bun';
import './myApi.routes';

// set options specific for bun
const bunOptions: Partial<BunHttpOptions> = {port: 8080};
setBunHttpOpts(bunOptions);

// init bun server
startBunServer();
myApi.routes.ts
import {RpcError} from '@mionkit/core';
import {Routes, RouterOptions, initRouter, registerRoutes} from '@mionkit/router';
import {clientRoutes} from '@mionkit/common';

export type User = {id: string; name: string; surname: string};
export type Order = {id: string; date: Date; userId: string; totalUSD: number};

export const routes = {
    auth: {
        headerName: 'authorization',
        hook: (ctx, token: string): void => {
            if (!token) throw new RpcError({statusCode: 401, message: 'Not Authorized', name: ' Not Authorized'});
        },
    },
    users: {
        getById: (ctx, id: string): User => ({id, name: 'John', surname: 'Smith'}),
        delete: (ctx, id: string): string => id,
        create: (ctx, newUser: Omit<User, 'id'>): User => ({id: 'USER-123', ...newUser}),
    },
    orders: {
        getById: (ctx, id: string): Order => ({id, date: new Date(), userId: 'USER-123', totalUSD: 120}),
        delete: (ctx, id: string): string => id,
        create: (ctx, newOrder: Omit<Order, 'id'>): Order => ({id: 'ORDER-123', ...newOrder}),
    },
    utils: {
        sum: (ctx, a: number, b: number): number => a + b,
        sayHello: (ctx, user: User): string => `Hello ${user.name} ${user.surname}`,
    },
    log: {
        forceRunOnError: true,
        hook: (ctx): void => {
            const now = Date.now();
            console.log(now, ctx.path, ctx.response.statusCode);
            if (ctx.request.internalErrors.length) console.error(now, ctx.path, ctx.request.internalErrors);
        },
    },
} satisfies Routes;

// set options and init router
export const routerOptions: Partial<RouterOptions> = {prefix: 'api/v1'};
initRouter(routerOptions);

// register routes and exporting the type of the Api (used by the client)
export const myApi = registerRoutes(routes);
export type MyApi = typeof myApi;

// register routes required by client
// these routes serve metadata required for validation and serialization on the client
registerRoutes(clientRoutes);
Quick Tip:
It is a good idea to split the routes definition and server initialization code so mion can be easily configured to run on multiple environments!

Run Types Loader

mion requires extending typescript compiler to emit the runtime type metadata. This can be done either following the quick start guide and compiling typescript before running your application with bun. Or either using the included run types loader so bun can emit the runtime type metadata on the fly.

To use bun's loader and emit runtime type metadata on the fly, you need to create a bun-preload.ts file in the root of your project as follows:

import {plugin} from 'bun';
import {runTypesLoader} from '@mionkit/bun/loader/runtypes-loader';
import {join} from 'path';

const tsConfig = join(__dirname, './tsconfig.json');

plugin(runTypesLoader({tsConfig}));
Please note at the moment SourceMaps are not working correctly when using the bun Run Types Loader. The issue has been reported into bun's repo here

Type Reference

RouterOptions

Basic options to configure mion router. These options are independent of the environment mion is being used (server or serverless).

export interface RouterOptions<Req = any, SharedData = any> extends CoreOptions {
    /** prefix for all routes, i.e: api/v1.
     * path separator is added between the prefix and the route */
    prefix: string;
    /** suffix for all routes, i.e: .json.
     * Not path separators is added between the route and the suffix */
    suffix: string;
    /** Transform the path before finding a route */
    pathTransform?: (request: Req, path: string) => string;
    /** factory function to initialize shared call context data */
    sharedDataFactory?: SharedDataFactory<SharedData>;
    /** enable automatic parameter validation, defaults to true */
    enableValidation: boolean;
    /** Enables serialization/deserialization */
    enableSerialization: boolean;
    /** Reflection and Deepkit Serialization-Validation options */
    reflectionOptions: ReflectionOptions;
    /** Custom JSON parser, defaults to Native js JSON */
    bodyParser: JsonParser;
    /** Used to return public data structure when adding routes */
    getPublicRoutesData: boolean;
    /** automatically generate and uuid */
    autoGenerateErrorId: boolean;
}

BunHttpOptions

export interface BunHttpOptions {
    port: number;
    /** Bun's native Server Options */
    options: Omit<Serve, 'fetch' | 'error'>;
    /** Set of default response header to add to every response*/
    defaultResponseHeaders: Record<string, string>;
    /**
     * 256KB by default, same as lambda payload
     * @link https://docs.aws.amazon.com/lambda/latest/operatorguide/payload.html
     * */
    maxBodySize: number; // default 256KB
}