@23rdpro/xapi
v1.0.2
Published
Open-source TypeScript SDK for working with the xAPI standard.
Readme
xAPI — Type-Safe API Client Generator
Generate strongly-typed REST and GraphQL API clients from OpenAPI and GraphQL schemas.
📋 Project Overview
xAPI is a TypeScript SDK for generating type-safe API clients from OpenAPI and GraphQL schemas. It uses a plugin-based architecture that produces strongly-typed clients for:
- REST APIs →
fetch,axios,RTK Query,TanStack Query - GraphQL APIs → Operations-based clients with subscription support
📖 Quick Start
Installation
npm install @23rdpro/xapi
# or
pnpm add @23rdpro/xapiBasic Usage (CLI)
Generate a fetch client from an OpenAPI spec:
xapi generate ./openapi.yaml fetch --zod --out src/generatedCreate a config file:
xapi init
xapi generateUsage Examples
Programmatic Examples
See examples.js for comprehensive examples demonstrating:
- ✅ Generating fetch, axios, RTK, and TanStack clients
- ✅ Working with GraphQL schemas and subscriptions
- ✅ Using Zod validators for runtime validation
- ✅ Programmatic API for integration
- ✅ Custom naming prefixes
Run programmatic examples:
node examples.jsThis generates sample clients from the included Petstore fixtures.
CLI Examples
See cli-examples.js for real-world CLI command examples demonstrating:
- ✅ Installation via npm/pnpm
- ✅ Generating clients for different HTTP libraries
- ✅ Configuration file setup
- ✅ Common workflows and patterns
- ✅ CI/CD integration
- ✅ Using generated clients in applications
Run CLI examples:
node cli-examples.jsThis will execute actual xapi generate commands and show you the workflows.
🏗️ Architecture
Core Flow: Plugin System
CLI / Script
↓
Plugin Registry
↓
Schema Detection
↓
Plugin.run()
├─ REST Plugin (YAML/JSON)
└─ GraphQL Plugin (.graphql)Key Files
| File | Purpose |
|------|---------|
| src/core/pluginSystem.ts | Registers plugins, matches schema type by extension |
| src/plugins/{rest,graphql,generate}.ts | Plugin execution logic |
| src/cli.ts | Command parsing (generate, init, doctor) |
Pipeline for Each Schema Type
REST / OpenAPI Path
- Load →
loaders/openapi.ts— Fetch from file or URL - Parse →
parsers/openapi.tsusing@apidevtools/swagger-parser - Normalize →
normalizers/openapi.ts→ produces uniformEndpoint[] - Generate →
generators/{typescript,client}.ts
GraphQL Path
- Load →
loaders/graphql.ts— Support.graphqlSDL or.jsonintrospection - Parse →
parsers/graphql.tsbuilds GraphQL schema - Normalize →
normalizers/graphql.ts→GraphQLEndpoint[] - Generate → Same generators as REST (polymorphic)
HTTP Client Variants
The generator switches logic based on the CLI/config:
// Supported clients
type HttpLibrary = "fetch" | "axios" | "rtk" | "tanstack";fetch(default) — Native browser/Node APIaxios— Popular HTTP clientrtk— Redux Toolkit Querytanstack— React Query
See: src/generators/client.ts
📦 Critical Data Types
REST Endpoint
type Endpoint = {
id: string;
name: string;
method: HttpMethod; // "get" | "post" | "put" | "patch" | "delete" ...
path: string; // e.g., "/pets/{id}"
params: Param[];
requestBody?: Body;
responses: Response[];
};GraphQL Endpoint
type GraphQLEndpoint = {
operationType: "query" | "mutation" | "subscription";
operationName: string;
requestSchema?: any;
responseSchema?: any;
graphql: { kind, field };
};⚙️ Configuration & Entry Points
Optional Config File: xapi.config.json
{
"schema": "./openapi.yaml",
"outDir": "src/generated",
"baseUrl": "https://api.example.com",
"httpLibrary": "fetch",
"zod": true
}CLI Commands
| Command | Description |
|---------|-------------|
| xapi generate [schema] [client] | Main codegen (supports --zod, --base-url, --out) |
| xapi init | Create config file interactively |
| xapi doctor [schema] | Validate schema and configuration |
Development Scripts
pnpm xapi:generate # Run code generation
pnpm dev:cli # Test CLI locally with tsx
pnpm test # Run tests (Vitest)
pnpm lint # ESLint check
pnpm build # Build for distribution🧪 Testing Strategy
Framework & Setup
- Test Runner →
Vitest - Path Resolution →
vite-tsconfig-paths(usestsconfig.jsonaliases)
Test Layout
tests/
├── generators/
│ ├── client.test.ts ← REST & GraphQL client generation
│ └── typescript.test.ts ← Type & Zod schema generation
├── parsers/
│ └── openapi.test.ts ← Schema dereferencing
├── normalizers/
│ └── openapi.test.ts ← Endpoint normalization
├── loaders/
│ └── openapi.test.ts ← File/URL loading
├── fixtures/
│ ├── petstore.yaml ← Sample OpenAPI spec
│ ├── petstore.json ← Sample OpenAPI (JSON)
│ └── petstore.graphql ← Sample GraphQL schema
└── utils/
└── file.test.ts ← Utility functionsImportant Test Files
client.test.ts— Verifies fetch, axios, RTK, TanStack variant outputtypescript.test.ts— Type & Zod schema generationopenapi.test.ts— Schema dereferencing & validationopenapi.normalizer.test.ts— Endpoint mapping correctness
🎯 Common Patterns
1. Options Threading
Options flow through the pipeline via a single ClientGenOptions interface:
interface ClientGenOptions {
outputPath?: string;
httpLibrary?: "fetch" | "axios" | "rtk" | "tanstack";
baseUrl?: string;
zod?: boolean;
wsUrl?: string; // GraphQL subscriptions
prefix?: string; // Type name prefix
}2. Naming Conventions
- Functions →
camelCase(e.g.,getPet,updateUser) - Types →
PascalCase+ suffix (e.g.,GetPetParams,GetPetResponse) - Zod schemas →
${TypeName}Schemawith inferred type:${TypeName}Parsed
3. Schema Handling
- Use
stableStringify()for schema deduplication via content hashing - Use
jsonSchemaToTS()for complex JSON schemas - Fall back to
simpleSchemaToTS()for simple types
4. Error Handling
// Missing dependency
throw new MissingDependencyError("axios", "@reduxjs/toolkit");
// CLI feedback
console.log(chalk.green("✅ Success"));
// Async operations with spinner
await withSpinner("Generating types...", async () => {
// work here
});🔧 Development Workflow
Run tests first to establish baseline
pnpm testUpdate generator logic (handle both REST and GraphQL paths if needed)
- Edit
src/generators/orsrc/plugins/
- Edit
Add test fixtures if testing new schema patterns
- Place in
tests/fixtures/
- Place in
Ensure type safety — use import aliases, not relative paths
Build & test CLI manually
pnpm build pnpm dev:cli -- ./tests/fixtures/petstore.yaml fetch
📍 Import Path Aliases
Always use import aliases, configured in tsconfig.json:
✅ Correct:
import { normalize } from "normalizers/openapi";
import { Endpoint } from "types/endpoint";
import { withSpinner } from "utils/spinner";❌ Avoid:
import { normalize } from "../normalizers/openapi";
import { Endpoint } from "../../types/endpoint";📦 Key Dependencies
| Package | Purpose |
|---------|---------|
| @apidevtools/swagger-parser | OpenAPI validation & dereferencing |
| graphql | GraphQL schema parsing & introspection |
| zod | Runtime validation schemas (optional) |
| commander | CLI argument parsing |
| chalk | Terminal colors |
| ora | CLI spinners |
| vitest | Test runner |
Last Updated: November 26, 2025
Maintained by: xAPI Team
