API Types
mion api-types builds a package that holds only your API's types. A client installs it instead of your whole server, and builds against the same ids.
Publishing a Types-Only Package
Run it from your server project. Its name is your server's plus -types, and its version is your server's. Change them with --name and --version.
mion api-types --tsconfig tsconfig.json --out api-types
cd api-types && npm publish
| In the package | What it is for |
|---|---|
.d.ts files | The exported API and every type it reaches. Private and raw middlewares, server-only code, unused global declarations, and their imports are left out. |
_outside/ | The types your API uses from other libraries, one file per library. |
mion-pure-fns/ | Pure functions and overrides your clients can use, so they compute the same ids. |
.mion/vendor/ | Pure functions from other libraries that your clients need. |
.mion/api/manifest.json | Lets mion api-check compare a client build with this server build. |
mion-api.json | The marker a client checks. |
package.json | No JavaScript entry. Peer dependencies on the mion packages and on your tsconfig libraries. |
mion api-types built it (rpc-client-types-not-built-by-mion). Build the client with the same mion version as the package (rpc-client-types-other-mion-version).Dependencies the Client Installs
A client installs the types package, the mion packages, and the libraries your tsconfig types and lib load, such as @types/node. Nothing else: a type your API takes from any other library ships inside the package. The package entry loads the same tsconfig libraries, so the client gets your server's ids whatever its own tsconfig lists.
export type Address = {city: string; street: string};
export declare enum Role { Admin = 'admin', User = 'user' }
Page<T> in your own generic type) cannot be copied. It stays an import, its library stays a peer dependency, and mion api-types prints a warning naming it.Classes and Enums From Other Libraries
A class or enum from another library is copied as a type only, with its name and members, so its ids do not change. A method's type parameters are not copied: map<T>(fn: (v: number) => T): T[] shows as map(fn: (v: number) => unknown): unknown[]. To get class instances back from the API, install that library in your client and register its class as usual:
import {registerClassSerializer} from '@mionjs/run-types/runtime';
import {Money} from 'money-lib';
registerClassSerializer(Money, {deserialize: (data) => new Money(data.amount)});
Installing a Copied Library in the Client
If your client installs a library the package copied, its types and the copies are separate declarations. Plain objects mix fine, but a class with private fields, a unique symbol or an enum from one does not fit the other: TypeScript reports "is not assignable". Ids and runtime are not affected.
Building a Client From Published API Types
Build your API package with mion compile and declaration: true, and its .d.ts carries the server's build version. A client calling initClient<typeof api>() on that type checks its ids against the version at build time, and fails with rpc-client-server-version-mismatch if they differ (another tsconfig or library version).
export declare const api: PublicApi<{...}> & ApiBuildVersion<"k3Jd92xQaP1z">;
tsc carry no version, so the client builds with the warning rpc-client-no-server-version and a mismatch only shows at runtime. They also lose the type of every private class field, so a route type holding such a class fails the client build with marker-untyped-private-member.Types-Only Package Compared With OpenAPI
A types-only package does for TypeScript clients what an OpenAPI spec does for other stacks. A client that fetches its routes from the server (client: {routes: 'fetch'}) needs no package.
| Types-only package | OpenAPI spec | |
|---|---|---|
| Who can read it | TypeScript clients built with mion | Any language or tool |
| Validation | The client compiles the server's validators from the same types | Each tool builds its own from the schema, so they can differ |
| Drift check | The build fails on a mismatch (rpc-client-server-version-mismatch); the version is also checked at runtime | None built in |
| Version | A hash of the route ids, set by the build | Written by hand |