Skip to main content

Overview

The @apisr/api-aggregator package provides utilities for aggregating and orchestrating multiple API endpoints into a cohesive configuration. It includes type-safe endpoint definitions, schema validation, and HTTP client integration using ky.

Installation

npm install @apisr/api-aggregator

Exports

The package exports the following functions and types:
  • aggregate(config: Config) - Main aggregation function
  • endpoint() - Helper for defining type-safe endpoints
  • Type exports: Config, Endpoint, Methods, ResponseStatus, ProbeFactory

Core Concepts

Endpoint Definition

Endpoints are the building blocks of your API configuration. Each endpoint defines:
  • Path: The URL path (supports params like :id)
  • Method: HTTP method (GET, POST, PUT, DELETE, PATCH, OPTIONS)
  • Schemas: Request/response validation schemas
  • Probes: Test data for different response scenarios

Configuration

The Config interface defines the overall API setup:
interface Config {
  baseUrl: string;
  endpoints: Endpoint[];
  format?: "json"; // default: "json"
  headers?: Record<string, string>;
  outDir?: string; // default: "./.openapi"
}

Usage

Defining Endpoints

Use the endpoint() helper to create type-safe endpoint definitions:
import { endpoint } from '@apisr/api-aggregator';
import { z } from '@apisr/zod';

const getUserEndpoint = endpoint({
  path: '/users/:id',
  method: 'GET',
  summary: 'Get user by ID',
  operationId: 'getUser',
  
  // Define schemas for different parts of the request
  paramsSchema: z.object({
    id: z.string(),
  }),
  
  querySchema: z.object({
    include: z.array(z.string()).optional(),
  }),
  
  headersSchema: z.object({
    authorization: z.string(),
  }),
});

Creating API Configuration

import { aggregate } from '@apisr/api-aggregator';

const config = {
  baseUrl: 'https://api.example.com',
  headers: {
    'Content-Type': 'application/json',
  },
  endpoints: [
    getUserEndpoint,
    // ... more endpoints
  ],
  outDir: './generated/openapi',
};

const api = aggregate(config);

Using Probes for Testing

Probes allow you to define test data for different response scenarios:
const createUserEndpoint = endpoint({
  path: '/users',
  method: 'POST',
  bodySchema: z.object({
    name: z.string(),
    email: z.string().email(),
  }),
  
  probe: {
    200: {
      body: {
        name: 'John Doe',
        email: '[email protected]',
      },
    },
    400: {
      body: {
        name: '',  // Invalid: empty name
        email: 'invalid-email',
      },
    },
  },
});

Advanced: Factory Functions

For dynamic test data, use probe factories:
const endpoint = endpoint({
  path: '/users',
  method: 'POST',
  bodySchema: z.object({
    name: z.string(),
    email: z.string().email(),
  }),
  
  probe: {
    200: {
      body: ({ faker }) => ({
        name: faker.person.fullName(),
        email: faker.internet.email(),
      }),
    },
  },
});

Type Utilities

Automatic Path Parameter Extraction

The package automatically extracts typed path parameters from endpoint paths:
// Path: "/users/:userId/posts/:postId"
// Automatically infers: { userId: string, postId: string }

const endpoint = endpoint({
  path: '/users/:userId/posts/:postId',
  method: 'GET',
  // paramsSchema must match the extracted params
});

HTTP Methods

Supported HTTP methods:

GET

Retrieve resources

POST

Create resources

PUT

Replace resources

PATCH

Update resources

DELETE

Remove resources

OPTIONS

Get supported methods

Response Status Codes

Currently supports defining probes for:
  • 200 - Success
  • 400 - Bad Request
  • Custom status codes (as strings or numbers)
The probe system allows you to define test scenarios for any HTTP status code, making it easy to test error handling and edge cases.

@apisr/zod

Extended Zod validation with request source mapping

@apisr/schema

Core schema types and utilities

Build docs developers (and LLMs) love