Middlewares

fetchMetadata

Fetch route metadata from the server instead of bundling it in the client.

Fetch route metadata from the server instead of bundling it in the client.

Route metadata is what the client needs to call a route: its param and return types, its options, and its validation and JSON round trip functions. By default, the mion build plugin bundles it into your client code.

Use this middleware when:

  • You don't want the routes metadata in the client bundle, for example to keep the bundle small for a large API.
  • Your client is built in a separate project from your server, or without the mion build plugin.

When you deploy a server that changes a route, the client fetches it again, with no client rebuild.

A client that fetches metadata builds the validation and JSON round trip functions at runtime, so a strict Content Security Policy blocks it. A client built without the mion build plugin cannot send batches.

Getting Route Metadata

A fetched client gets the server's own compiled functions, so they always match it.

ModeHow the client gets itWhat you set up
Bundled (default)The build ships it with the client, for every route the client calls.Nothing.
FetchedThe mionFetchMetadata middleware sends it on a route's first call, and the client saves it.The middleware and the client setup.

Adding the Middleware

Import mionFetchMetadata from @mionjs/router/middlewares and add it to your routes. Only an API whose clients fetch metadata needs it.

server.routes.ts
import {createMionRouter, Routes} from '@mionjs/router';
import {mionFetchMetadata} from '@mionjs/router/middlewares';

const mion = createMionRouter();

const routes = {
  // at the root, before any route or group, or the router refuses it
  mionFetchMetadata,
  sayHello: mion.route((ctx, name: string): string => `Hello ${name}`),
} satisfies Routes;

const myApi = mion.initRoutes(routes);

export type MyApi = typeof myApi;
It runs only when a request asks for metadata, so other calls cost nothing.

What the Middleware Answers

Given a list of route ids, it returns the metadata of each route and of every middleware that runs with it.

It describesIt never describes
Every routeYour handler code
Middleware that takes params or headers, or returns dataRaw middleware, and middleware with no params and no return data
The compiled validation and JSON round trip functions of thosemion's internal routes

Why Metadata Is Public

Any client can ask for any route's metadata, without logging in. A client with bundled metadata has the same metadata in its JavaScript. Treat it like a public API schema: it shows your types, never your data.

Route metadata is not access control. Protect your routes with your own middleware.

Listing Every Method

A client written without mion can POST this body to any route path to list every public route and middleware, and the ids of your batches, so it can call a batch by id. The route at that path does not run.

{"mionFetchMetadata": [[], "all"]}

Method List Limit

When the API has more routes and middleware than the getAllRemoteMethodsMaxNumber router option, you get no full list: the answer has only the ids you sent, no batch ids, and truncated: true.

import {createMionRouter} from '@mionjs/router';

// list up to 200 methods when a client asks for all of them (100 by default)
export const mion = createMionRouter({getAllRemoteMethodsMaxNumber: 200});
Copyright © 2026