Skip to Content

Generate Your SDK

So far you’ve built a typed server. This is the part most teams come for: every controller you wrote becomes a typed function in a generated SDK that a frontend can import and call. No fetch, no URL strings, no hand-maintained DTOs in two places.


1. The config file

Nestia reads nestia.config.ts at the project root. If you used the starter it is already there; otherwise:

Terminal
npx nestia init

Open it:

nestia.config.ts
import { INestiaConfig } from "@nestia/sdk"; import { NestFactory } from "@nestjs/core"; import { AppModule } from "./src/AppModule"; const config: INestiaConfig = { input: () => NestFactory.create(AppModule), output: "src/api", }; export default config;

Three things matter:

  • input β€” how Nestia finds your controllers. A function returning your NestApplication is the most reliable form; it picks up every module, prefix, and versioning rule you set on the app.
  • output β€” where the generated SDK lives. We recommend src/api.
  • That’s all you need for the SDK. We will add swagger and e2e keys in later chapters.

2. Generate

Terminal
npx nestia sdk

You should see a tree appear under src/api/:

src/api/
src/api/ β”œβ”€β”€ HttpError.ts β”œβ”€β”€ IConnection.ts β”œβ”€β”€ Primitive.ts β”œβ”€β”€ module.ts └── functional/ └── articles/ └── index.ts # one file per controller

Open src/api/functional/articles/index.ts and you will find one exported function per controller method. The function signature is derived from your TypeScript types:

src/api/functional/articles/index.ts (excerpt)
/** * Create a new article. * * @param input The article payload. * @returns The stored article with `id` and `created_at` populated. * * @controller ArticlesController.create() * @path POST /articles */ export async function create( connection: IConnection, input: create.Input, ): Promise<create.Output> { /* ... */ } export namespace create { export type Input = Primitive<IArticle.ICreate>; export type Output = Primitive<IArticle>; // ... }

The JSDoc came from your controller’s JSDoc. The Input / Output types came from your TypeScript types. Nothing about this file is hand-written.


3. The shape of an SDK call

Every generated function takes an IConnection as the first argument and the rest of the parameters in source order. IConnection is a small config object exported from the SDK that tells it where your server lives and what headers to send β€” no class, no client to instantiate, just a plain object.

import api from "@my-app/api"; // or, when the SDK lives in the same repo: import * as api from "../api"; const connection: api.IConnection = { host: "http://localhost:37001", }; const article = await api.functional.articles.create(connection, { title: "Hello", body: "World", });
  • connection.host points at your server.
  • connection.headers (optional) is merged into every request β€” handy for Authorization.
  • The function returns the typed response. Your IDE autocompletes article.id, article.created_at, etc.

A 4xx / 5xx response throws an HttpError. Mistyped arguments are a TypeScript compile error, not a 400 at runtime.


4. Where to put the generated SDK

Three common shapes:

Single repo: put output: "src/api" inside the NestJS project. Tests inside the repo import the SDK from ../api. Good for solo projects and prototypes.


5. When to regenerate

Re-run npx nestia sdk whenever your controllers, DTOs, or nestia.config.ts change. In a typical workflow you wire it into your build:

package.json
{ "scripts": { "build": "ttsc && npx nestia sdk" } }

If you also want Swagger and e2e, use the combined command (npx nestia all) covered in the next chapters.


6. What you can do now

The generated SDK is a normal TypeScript module. You can:

  • Import it from a Next.js / Vite / React Native client.
  • Use it inside Node scripts and Lambda functions.
  • Bundle it into a published npm package for external partners.
  • Drive it from tests (Chapter 8 will do exactly that).

Next

You have an SDK. Let’s Call Your API from a tiny client and feel what type-safe RPC looks like.

Last updated on