Skip to main content

Getting Started

This guide will walk you through installing Apinni, configuring your project, and generating your first type-safe API definitions.

info

New to Apinni? This guide assumes you have a TypeScript project set up. If you're starting from scratch, create a new TypeScript project first.

System Requirements

  • Node.js 18.x or later
  • TypeScript 4.5 or later
  • Package Manager: npm, Yarn, or pnpm

Installation

Install Apinni as a development dependency in your project:

npm install @apinni/client-ts --save-dev

TypeScript Configuration

Apinni requires TypeScript decorators to be enabled. Update your tsconfig.json:

tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"outDir": "./dist",
"rootDir": "./src"
}
}
warning

Without experimentalDecorators and emitDecoratorMetadata, Apinni cannot process your decorators.

Quick Start

Let's create your first API controller and generate types.

Step 1: Create a Configuration File

Create an apinni.config.ts file in your project root:

apinni.config.ts
import type { ApinniConfig } from '@apinni/client-ts';

export default {
outputPath: './types',
plugins: [],
} satisfies ApinniConfig;

Step 2: Create Your First Controller

Create a controller file with Apinni decorators:

src/controllers/user.controller.ts
import { ApinniController, ApinniEndpoint } from '@apinni/client-ts';

interface User {
id: string;
name: string;
email: string;
}

@ApinniController({ path: '/api/users' })
export class UserController {
@ApinniEndpoint({ path: '/:id', method: 'GET' })
async getUserById(): Promise<User> {
// Your implementation here
return {
id: '123',
name: 'Alice',
email: 'alice@example.com'
};
}

@ApinniEndpoint({ path: '/', method: 'POST' })
async createUser(): Promise<User> {
// Your implementation here
return {
id: '456',
name: 'Bob',
email: 'bob@example.com'
};
}
}

Step 3: Add Scripts to package.json

Add Apinni commands to your package.json:

package.json
{
"scripts": {
"types:generate": "apinni generate",
"types:watch": "apinni watch"
}
}

Step 4: Generate Types

Run the generation command:

npm run types:generate

Apinni will generate a type definition file in the ./types directory:

types/api-types.d.ts
// Auto-generated by Apinni

export interface GetApiUsersByIdResponse {
id: string;
name: string;
email: string;
}

export interface PostApiUsersResponse {
id: string;
name: string;
email: string;
}

export type Api = {
'/api/users/:id': {
GET: {
query: never;
request: never;
responses: {
200: GetApiUsersByIdResponse;
};
};
};
'/api/users': {
POST: {
query: never;
request: never;
responses: {
200: PostApiUsersResponse;
};
};
};
};

// Utility types for type-safe API consumption
export type ApiPaths = '/api/users/:id' | '/api/users';
export type ApiAvailableMethods<T extends ApiPaths> = // ...
// ... more utility types
success

Success! You've generated your first type-safe API definitions. These types can now be imported and used in your frontend or API clients.

Using Generated Types

Now you can use these types in your client code:

src/client/api.ts
import type { ApiResponsesByStatus, ApiPaths } from '../types/api-types';

// Type-safe API client
async function getUser(id: string) {
type UserResponse = ApiResponsesByStatus<'/api/users/:id', 'GET', '200'>;

const response = await fetch(`/api/users/${id}`);
const data: UserResponse = await response.json();

return data; // Fully typed: { id: string; name: string; email: string }
}

Development Workflow

For the best development experience, run Apinni in watch mode:

npm run types:watch

This will automatically regenerate types whenever you modify your controllers.

tip

Run types:watch alongside your development server for instant type updates as you code.

Configuration Options

Customize Apinni's behavior in your config file:

apinni.config.ts
import type { ApinniConfig } from '@apinni/client-ts';

export default {
// Output directory for generated types
outputPath: './types',

// Glob patterns for files to include
includePatterns: ['src/**/*.controller.ts'],

// Glob patterns for files to exclude
excludePatterns: ['**/*.spec.ts', '**/*.test.ts'],

// Plugins to extend functionality
plugins: [],
} satisfies ApinniConfig;
OptionTypeDescription
outputPathstringDirectory where type files will be generated (default: ./types)
includePatternsstring[]Glob patterns for files to process
excludePatternsstring[]Glob patterns for files to ignore
pluginsPluginTypes[]Array of plugins to extend Apinni's functionality

Troubleshooting

Types Not Generated

Problem: Running apinni generate doesn't create any files.

Solutions:

  • Verify experimentalDecorators and emitDecoratorMetadata are enabled in tsconfig.json
  • Check that your controllers use @ApinniController decorator
  • Ensure your files match the includePatterns in your config
  • Look for compilation errors in your TypeScript code

Decorator Errors

Problem: Errors about decorators not being found.

Solutions:

  • Verify Apinni is installed: npm list @apinni/client-ts
  • Check imports: import { ApinniController } from '@apinni/client-ts'
  • Avoid named imports with aliases (use the exact decorator names)
  • Ensure reflect-metadata is imported if using runtime decorators

Types Generated in Wrong Directory

Problem: Generated files appear in an unexpected location.

Solutions:

  • Check the outputPath in your apinni.config.ts
  • Use absolute paths or paths relative to your project root
  • Verify you're running the command from your project root
info

For more detailed troubleshooting, see the CLI documentation or join our community.

Next Steps

Now that you have Apinni set up, explore more features:

Learn the Core Concepts

Integrate with Your Stack

Extend Functionality