Back to projects

@abdallemo/routegen-client

Strictly-typed Axios wrapper for go-route-gen routes.

This is the NPM package I built to work alongside my Go CLI tool. While the Go tool does the heavy lifting of finding the routes, this package is what I actually use in my frontend projects to make sure my API calls are safe.

The "Type-Safe" Goal

I wanted a way to consume my Go APIs without having to manually type every endpoint string and every parameter. It’s so annoying when you misspell a route and spend 10 minutes debugging a 404. I wanted the TypeScript compiler to yell at me if I tried to hit a route that didn't exist or if I forgot a required ID.

It's basically a very thin wrapper around Axios that uses a lot of TypeScript generics. It takes the JSON file from the CLI tool and uses template literal types to enforce the METHOD /path format.

// src/lib/api.ts import { GoApiClient } from '@abdallemo/routegen-client' import { API_ROUTES } from './route' // Generated by the Go CLI export const api = new GoApiClient<typeof API_ROUTES>({ baseURL: 'http://localhost:8080', // Optional: Pass a pre-configured Axios instance // axiosInstance: customAxios, // Optional: Standard configuration overrides config: { timeout: 15000, // Default is 15000ms }, // Optional: Global lifecycle hooks for centralized state/UI management hooks: { onError: (message, status) => { // e.g., toast.error(message) console.error(`[API Error ${status}]:`, message); }, onUnauthorized: () => { // e.g., Clear local session state or redirect to /login console.warn("Session expired. Redirecting..."); } } })

Learning to parse strings in Types

The hardest part was getting path parameters to work. If I have a route like GET /users/{id}, I wanted the client to know that I need to provide an id object.

Building this taught me a lot about advanced TypeScript features like infer and recursive types. I had to learn how to parse strings at the type level, which was a huge challenge but really rewarding when it finally worked. I'm thinking about adding automatic retries and maybe some basic caching logic next so I don't have to keep reimplementing those in every project.