Skip to content

Automatically Generate Type-Safe API Functions for Your RESTful APIs AxiosFlow is a powerful TypeScript library that simplifies API consumption by automatically generating type-safe API functions for your RESTful APIs. It eliminates boilerplate code, ensures compile-time type safety, and works seamlessly with Express.js and Axios.

License

Notifications You must be signed in to change notification settings

Noble-TS/AxiosFlow

Repository files navigation

AxiosFlow

Weekly Downloads Version License GitHub Issues GitHub Stars Build Status

Automatically Generate Type-Safe API Functions for Your RESTful APIs

AxiosFlow is a powerful TypeScript library that simplifies API consumption by automatically generating type-safe API functions for your RESTful APIs. It eliminates boilerplate code, ensures compile-time type safety, and works seamlessly with Express.js and Axios.


Why AxiosFlow?

Building type-safe APIs can be time-consuming and error-prone. AxiosFlow solves this by:

  • Automating API Function Generation: No more writing repetitive API call functions.
  • Ensuring Compile-Time Type Safety: Catch errors before runtime with TypeScript.
  • Reducing Boilerplate Code: Focus on building features, not writing API glue code.
  • Seamless Integration: Works with your existing Express.js backend and Axios client.

Key Features

Comprehensive Type Safety

  • Robust Error Prevention: Ensures type-safe API calls.
  • Compile-Time Validation: Catches type mismatches before runtime.
  • Enhanced Code Quality: Reduces potential errors in API interactions.

Intelligent Type Generation

  • Automatic Function Creation: Generates fully typed API client functions.
  • Eliminates Manual Type Definitions: Dramatically reduces boilerplate code.
  • Compile-Time Type Safety: Guarantees type consistency across API interactions.

End-to-End Type Inference

  • Backend to Frontend Type Mapping: Seamless type propagation.
  • Catches Potential Type Mismatches: Ensures consistency during development.

Core Capabilities

  • Automatic API Function Generation: Generates type-safe API functions with minimal configuration.
  • Dynamic URL Parameter Support: Easily handle dynamic routes like /users/:id.
  • Minimal Configuration Required: Works out of the box with Express.js and Axios.

How AxiosFlow Compares to Other Tools

Feature/Tool AxiosFlow tRPC OpenAPI (Swagger) GraphQL Code Generator Zodios Manual Typing
Type Safety Compile-time Compile-time Runtime Compile-time Runtime (Zod) Manual
Ease of Use Easy (Express.js + Axios) Moderate (tRPC setup) Moderate (YAML/JSON) Moderate (GraphQL) Moderate (Zod schemas) Manual
Flexibility High (framework-agnostic) Low (tRPC-specific) High (RESTful APIs) Low (GraphQL-only) High (Zod integration) High
Boilerplate Code Minimal Minimal Moderate Minimal Moderate High

AxiosFlow is the simplest and most flexible solution for adding type safety to RESTful APIs without requiring a new framework or maintaining a separate schema.


Quick Start

Examples

Check out the examples folder for complete implementation samples:

  • Client: A React/TypeScript frontend using AxiosFlow.
  • Server: An Express.js backend with AxiosFlow integration.

CodeSandbox

Check out the live examples on CodeSandbox to see AxiosFlow in action:

Client and Server Example

Backend setup

Installation

Install core dependencies

npm install express@4.21.2  cors dotenv axiosflow-api

Install TypeScript and types

npm install -D typescript @types/express @types/cors ts-node

Step-by-Step Setup

1. Create Controller (userController.ts)

import { Request, Response } from 'express';

// Interfaces for type safety
export class UserRequest {
  name: string | undefined;
}

export class User {
  id: number | undefined;
  name: string | undefined;
}

export class UserController {
  private users: User[] = [
    { id: 1, name: 'John Doe' },
    { id: 2, name: 'Jane Doe' },
  ];

  getUsers(req: Request, res: Response): Response {
    return res.status(200).json({
      status: 'success',
      data: this.users,
    });
  }

  getUserById(req: Request, res: Response): Response {
    const userId = parseInt(req.params.id);
    const user = this.users.find((u) => u.id === userId);
    
    if (!user) {
      return res.status(404).json({
        status: 'error',
        message: 'User not found',
      });
    }
    
    return res.status(200).json({
      status: 'success',
      data: user,
    });
  }

  createUser(req: Request, res: Response): Response {
    const { name } = req.body as UserRequest;
    
    if (!name) {
      return res.status(400).json({
        status: 'error',
        message: 'Name is required',
      });
    }
    
    const newUser = { 
      id: this.users.length + 1, 
      name 
    };
    
    this.users.push(newUser);
    return res.status(201).json({
      status: 'success',
      data: newUser,
    });
  }
} 

2. Create User Routes (userRoutes.ts)

import { registerRoute, typeRef } from 'axiosflow-api';
import { UserController, UserRequest, User } from '../controllers/userController';

// Create an instance of the controller
const userController = new UserController();

// Define routes and register them dynamically
export function registerUserRoutes() {
  registerRoute(
    userController, 
    'GET', 
    '/users', 
    null, 
    typeRef<User>('User', { id: 'number', name: 'string' }), 
    [], 
    'getUsers'
  );
  
  registerRoute(
    userController, 
    'GET', 
    '/users/:id', 
    null, 
    typeRef<User>('User', { id: 'number', name: 'string' }), 
    [], 
    'getUserById'
  );
  
  registerRoute(
    userController, 
    'POST', 
    '/users', 
    typeRef<UserRequest>('UserRequest', { name: 'string' }), 
    typeRef<User>('User', { id: 'number', name: 'string' }), 
    [], 
    'createUser'
  );
}

// Export the controller instance for use in the router
export const controllerInstances = {
  UserController: userController,
};

3. Create Router (router.ts)

import { Router } from 'express';
import { createRoutes } from 'axiosflow-api';
import { registerUserRoutes, controllerInstances } from './userRoutes';

const router = Router();

// Register user routes
registerUserRoutes();

// Dynamically create routes based on registered metadata
createRoutes(router, controllerInstances);

export default router;

4. Create Server (server.ts)

import express from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import router from './routes/router';
import { exportRoutesForSchema } from 'axiosflow-api';

dotenv.config();

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(cors());
app.use(express.json());

// Routes
app.use('/api', router);

// Route to export API schema
app.get('/axiosflow', (req, res) => {
  const routes = exportRoutesForSchema();
  res.json(routes);
});

// Global error handler
app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
  console.error(err.stack);
  res.status(500).json({ 
    message: 'Something went wrong', 
    error: process.env.NODE_ENV !== 'production' ? err : {} 
  });
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

Advanced Configuration: Middleware and Interceptors

import { Request, Response, NextFunction } from 'express';
import { registerRoute, typeRef } from 'axiosflow-api';


//  CSRF middleware
const csrfProtection: RequestHandler = csrf({ cookie: true });
  

// logger middleware
const logger: RequestHandler = (req, res, next) => {
    console.log(`${req.method} ${req.path}`);
    next();
};

export function registerUserRoutes() {
  // GET Users - Simple logging middleware
  registerRoute(
    userController, 
    'GET', 
    '/users', 
    null, 
    typeRef<User>('User', { id: 'number', name: 'string' }), 
    [csrfProtection,logger], 
    'getUsers'
  );
  
  // GET User by ID - Authentication and logging
  registerRoute(
    userController, 
    'GET', 
    '/users/:id', 
    null, 
    typeRef<User>('User', { id: 'number', name: 'string' }), 
    [csrfProtection, logger], 
    'getUserById'
  );
  
}

Client Setup

Prerequisites

Node.js (v16+) TypeScript Axios

Global installation via npm

Using NPM

npm install -g axiosflow

Using PNPM

pnpm add axiosflow 

Verify Installation

axiosflow --help 

Generate API Functions

# Basic generation
axiosflow generate

# With specific options
axiosflow generate -b http://localhost:3000 -o ./src/services

3. Generated Files Structure in project structure

src/services/
├── apiFunctions.ts     # Generated API functions
├── apiConfig.ts        # API endpoint configurations
├── types.ts            # Type definitions
└── api-schema.json     # API schema documentation

Usage in React/TypeScript Project

Fetch Users

import { get_users } from './services/apiFunctions';

async function UserList() {
  try {
    const users = await get_users();
    // Handle users
  } catch (error) {
    // Handle error
  }
}

Create User

import { post_users } from './services/apiFunctions';

async function createUser(name: string) {
  try {
    const newUser = await post_users({ name });
    // Handle new user
  } catch (error) {
    // Handle error
  }
}

or in components :

import React, { useEffect, useState } from 'react';
import { get_users, post_users, get_users_id } from '../services/apiFunctions';
import { User, UserRequest } from '../services/types';

const UserComponent: React.FC = () => {
    const [users, setUsers] = useState<User[]>([]);
    const [loading, setLoading] = useState<boolean>(true);
    const [error, setError] = useState<string | null>(null);
    

    // Fetch the list of users from the API on component mount 
    useEffect(() => {
        const fetchUsers = async () => {
            try {
                setLoading(true);
                setError(null);

                console.log('Attempting to fetch users...');
                const userList = await get_users();
                
                console.log('Fetched Users:', userList);
                
                if (userList.length > 0) {
                    setUsers(userList);
                } else {
                    setError('No users found');
                }
            } catch (err) {
                console.error('Fetch Users Error:', err);
                
                const errorMessage = err instanceof Error 
                    ? err.message 
                    : 'An unexpected error occurred';
                
                setError(errorMessage);
            } finally {
                setLoading(false);
            }
        };

        fetchUsers();
    }, []);
return (
    <div> 
    <h1>Users Lists</h1>
    </div>
);

};

About

Automatically Generate Type-Safe API Functions for Your RESTful APIs AxiosFlow is a powerful TypeScript library that simplifies API consumption by automatically generating type-safe API functions for your RESTful APIs. It eliminates boilerplate code, ensures compile-time type safety, and works seamlessly with Express.js and Axios.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published