@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.