Skip to content

Multiple Clients โ€‹

Configure multiple API clients in a single Angular application with independent configurations and interceptors.

Overview โ€‹

ng-openapi supports generating multiple clients for different APIs, each with their own base paths, interceptors, and configurations. This is useful when your application needs to communicate with multiple backend services.

Generating Multiple Clients โ€‹

Create separate configuration files for each API:

typescript
// users-api.config.ts
import { GeneratorConfig } from "ng-openapi";

const config: GeneratorConfig = {
    clientName: "Users",
    input: "./users-swagger.json",
    output: "./src/api/users",
    options: {
        dateType: "Date",
        enumStyle: "enum",
    },
};

export default config;
typescript
// orders-api.config.ts
import { GeneratorConfig } from "ng-openapi";

const config: GeneratorConfig = {
    clientName: "Orders",
    input: "./orders-swagger.json",
    output: "./src/api/orders",
    options: {
        dateType: "Date",
        enumStyle: "enum",
    },
};

export default config;

Generate each client:

bash
ng-openapi -c users-api.config.ts
ng-openapi -c orders-api.config.ts

Provider Configuration โ€‹

Each client generates its own provider function based on the clientName:

typescript
// app.config.ts
import { ApplicationConfig } from "@angular/core";
import { provideHttpClient } from "@angular/common/http";
import { provideUsersClient } from "./api/users/providers";
import { provideOrdersClient } from "./api/orders/providers";

export const appConfig: ApplicationConfig = {
    providers: [
        provideHttpClient(),
        provideUsersClient({
            basePath: "https://users-api.example.com",
        }),
        provideOrdersClient({
            basePath: "https://orders-api.example.com",
        }),
    ],
};

Independent Interceptors โ€‹

Apply different interceptors to each client:

typescript
// auth.interceptor.ts
import { HttpInterceptor, HttpRequest, HttpHandler } from "@angular/common/http";
import { Injectable } from "@angular/core";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler) {
        const authReq = req.clone({
            headers: req.headers.set("Authorization", "Bearer token"),
        });
        return next.handle(authReq);
    }
}
typescript
// logging.interceptor.ts
import { HttpInterceptor, HttpRequest, HttpHandler } from "@angular/common/http";
import { Injectable } from "@angular/core";

@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler) {
        console.log("Request:", req.url);
        return next.handle(req);
    }
}

Configure interceptors per client:

typescript
export const appConfig: ApplicationConfig = {
    providers: [
        provideHttpClient(),
        provideUsersClient({
            basePath: "https://users-api.example.com",
            interceptors: [AuthInterceptor], // Only for users API
        }),
        provideOrdersClient({
            basePath: "https://orders-api.example.com",
            interceptors: [AuthInterceptor, LoggingInterceptor], // Both interceptors
        }),
    ],
};

Using Multiple Clients โ€‹

Import and use services from different clients:

typescript
import { Component, inject } from "@angular/core";
import { toSignal } from "@angular/core/rxjs-interop";
import { UsersService } from "./api/users/services";
import { OrdersService } from "./api/orders/services";

@Component({
    selector: "app-dashboard",
    template: `
        <div>
            <h2>Users: {{ users()?.length ?? 0 }}</h2>
            <h2>Orders: {{ orders()?.length ?? 0 }}</h2>
        </div>
    `,
})
export class DashboardComponent {
    private readonly usersService = inject(UsersService);
    private readonly ordersService = inject(OrdersService);

    readonly users = toSignal(this.usersService.getUsers());
    readonly orders = toSignal(this.ordersService.getOrders());
}

Client Isolation โ€‹

Each client operates independently:

  • Separate Base Paths - Different API endpoints
  • Independent Interceptors - Apply different authentication, logging, or transformation logic
  • Isolated Configuration - Different date handling, headers, or response types
  • No Cross-Client Interference - Changes to one client don't affect others

Generated Structure โ€‹

With multiple clients, your project structure looks like:

src/
โ”œโ”€โ”€ api/
โ”‚   โ”œโ”€โ”€ users/
โ”‚   โ”‚   โ”œโ”€โ”€ models/
โ”‚   โ”‚   โ”œโ”€โ”€ services/
โ”‚   โ”‚   โ”œโ”€โ”€ tokens/
โ”‚   โ”‚   โ”œโ”€โ”€ utils/
โ”‚   โ”‚   โ”œโ”€โ”€ providers.ts
โ”‚   โ”‚   โ””โ”€โ”€ index.ts
โ”‚   โ””โ”€โ”€ orders/
โ”‚       โ”œโ”€โ”€ models/
โ”‚       โ”œโ”€โ”€ services/
โ”‚       โ”œโ”€โ”€ tokens/
โ”‚       โ”œโ”€โ”€ utils/
โ”‚       โ”œโ”€โ”€ providers.ts
โ”‚       โ””โ”€โ”€ index.ts
โ””โ”€โ”€ app/
    โ””โ”€โ”€ app.config.ts

Package.json Scripts โ€‹

Organize generation scripts for multiple clients:

json
{
    "scripts": {
        "generate:users": "ng-openapi -c users-api.config.ts",
        "generate:orders": "ng-openapi -c orders-api.config.ts",
        "generate:all": "npm run generate:users && npm run generate:orders"
    }
}

Best Practices โ€‹

Naming Convention โ€‹

Use descriptive client names that reflect the API purpose:

typescript
clientName: "Users"; // generates provideUsersClient
clientName: "Orders"; // generates provideOrdersClient
clientName: "Payments"; // generates providePaymentsClient

Directory Organization โ€‹

Keep clients in separate directories:

bash
ng-openapi -c users-api.config.ts    # outputs to ./src/api/users
ng-openapi -c orders-api.config.ts   # outputs to ./src/api/orders

Environment Configuration โ€‹

Use environment-specific configurations:

typescript
import { environment } from "../environments/environment";

export const appConfig: ApplicationConfig = {
    providers: [
        provideUsersClient({
            basePath: environment.usersApiUrl,
        }),
        provideOrdersClient({
            basePath: environment.ordersApiUrl,
        }),
    ],
};

Resources โ€‹

Released under the MIT License.
This site is powered by Netlify
About ยท Impressum