New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

typed-axios-manager

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

typed-axios-manager

Type-safe axios manager with autocomplete and path binding support

latest
Source
npmnpm
Version
1.0.4
Version published
Weekly downloads
3
200%
Maintainers
1
Weekly downloads
 
Created
Source

Typed Axios Manager

Un gestor de axios fuertemente tipado con autocompletado inteligente, soporte para rutas dinámicas y parámetros de consulta opcionales.

Comentario del Creador: Por que cree este typed manager? Cuando inicie el camino en la programacion, me incertaron en la mente que hay que hacer las cosas de la manera más eficiente posible. Siempre buscar optimizar el codigo,funciones pero tambien nuestra forma de codear. Hoy con la IA podemos ser muy eficientes, pero no hay que dejar de crear las herramientas que mantengan organizado nuestros proyecto y mejorar nuestra experiencia de desarrollo.

Arranque creando archivos para todos los path. Rapidamente se convirtio en un sin fin de constantes.

Un claro ejemplo que seguramente todos recordaremos:

const PATH_CREATE_USER = "/api/user/"
const PATH_GET_USER = (id: number)=>`/api/user/${id}`
const PATH_UPDATE_USER = (id: number)=> `/api/user/${id}`
...

Y mientras buscaba proyectos mas grandes, surgio la necesidad de organizar esto diferente Probe con una carpeta API y archivos x endpoint

api/
├── auth/
│   ├── login.ts
│   ├── register.ts
│   ├── me.ts
├── users/
│   ├── getAll.ts
│   ├── getById.ts
│   ├── create.ts
│   ├── update.ts
│   ├── delete.ts
│   ├── search.ts
├── products/
│   ├── getAll.ts
│   ├── getById.ts
│   ├── search.ts

Pero no resolvia el problema de las constantes, y los archivos crecian sin parar. Sin contar que cuando empezas, tenes poca organizacion. Cambias objetos, se te rompen request y despues anda a acordarte donde esta y que cambio. Cosas como tener que cambiar el path en MIL lugares, cuando deberia cambiarlo en 1.

Despues conoci React - con sus miles de componentes (los que yo creaba) + Axios Y facilmente empece a crear axios.get("y un path") en un componente, y luego usar en otro, y asi sucesivamente.

Que archivo use? En que componente esta? en un child-component del form? Organizarme es fundamental. Los proyectos grandes requieren que seamos desarrolladores organizados.

En mi experiencia pase por Redux, Zustand, librerias que me gustan mucho por la organizacion Aunque el que tiene que mejorar en organizacion soy yo, me inspire en la forma en la que ellos tienen sus generadores.

Dije: esto, para un axios, estaria barbaro.

Empece a probar, genere varias versiones, y ahora me siento lo suficientemente confiado para mostrar este invento.

Lo tengo funcionando en 2 proyectos. Esta es la primera version que subo porque quiero que sea una dependencia en y no un conjunto de archivos dentro de /helper.

La idea es tener mas organizado los proyectos y la conexion con el backend, en un solo archivo Una unica fuente de la verdad Menos erroes, mas proyectos, mas rapido, mas $$$$

Si a alguien le sirve, encantado de saberlo. Happy Coding!

🚀 Características

  • TypeScript First: Tipado fuerte con autocompletado inteligente
  • Fluent API: Definición de rutas clara y escalable que permite inferencia correcta de tipos
  • Query Params Opcionales: No más objetos vacíos obligatorios
  • Path Bindings: Soporte para rutas dinámicas con {param}
  • Framework Agnostic: Funciona con React, Vue, Node.js, Next.js, Astro
  • Sin Dependencias de Estado: No requiere Redux ni ningún estado específico
  • Testing Ready: Tests incluidos con Vitest
  • ESM + CommonJS: Compatible con ambos sistemas de módulos
  • Hooks de React Opcionales: Usa los hooks si quieres, no es obligatorio

📦 Instalación

npm install typed-axios-manager axios

🔧 Uso Básico

1. Define tus rutas

import { createRouteConfig, get, post, put, del } from 'typed-axios-manager';

type User = { name: string; email: string };
type Product = { name: string; price: number };
type ProductSearchRequest = { name: string; limit?: number; page: number };

const apiRoutes = createRouteConfig({
  auth: {
    login: post('/auth/login').body<{ email: string; password: string }>().response<{ token: string }>(),
    register: post('/auth/register').body<{ email: string; password: string }>(),
    me: get('/auth/me').response<User>(),
  },
  users: {
    getAll: get('/users').response<User[]>(),
    getById: get('/users/{id}').response<User>(), // Ruta dinámica con inferencia de {id}
    create: post('/users').body<{ name: string; email: string }>().response<User>(),
    update: put('/users/{id}').body<Partial<User>>(),
    delete: del('/users/{id}'),
    search: get('/users/search').query<{ q: string; limit?: number }>().response<User[]>(), // Con query params
  },
  products: {
    getAll: get('/products').response<Product[]>(),
    getById: get('/products/{id}').response<Product>(),
    search: get('/products/search').query<ProductSearchRequest>().response<Product[]>(), // query params opcionales
  },
});

type ApiRoutes = typeof apiRoutes;

2. Crea el manager

const manager = createAxiosManager<ApiRoutes>({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  headers: {
    'X-API-Key': 'your-api-key'
  }
});

// Crea las funciones tipadas
const api = manager.createTypedRoutes(apiRoutes);

3. Usa las funciones

// Query params realmente opcionales
const users = await api.users.getAll(); // No requiere argumentos

//  Con query params cuando los necesites
const products = await api.products.search({ 
  q: 'laptop', 
  limit: 10,
  sort: 'price_asc' 
});

//  Path bindings funcionan perfectamente
const user = await api.users.getById({ id: 123 });

//  Body params bien tipados
const newUser = await api.auth.login({
  email: 'user@example.com',
  password: 'password123'
});

🧩 Ejemplos de Query Params

Declarar rutas con tipos de query

import { createRouteConfig, get, post, patch } from 'typed-axios-manager';

const routes = createRouteConfig({
  users: {
    search: get('/users/search').query<{ q: string; limit?: number }>().response<unknown>(),
    getById: get('/users/{id}').query<{ include?: 'profile' | 'roles' }>().response<unknown>(),
    create: post('/users').body<{ name: string; email: string }>().query<{ sendWelcomeEmail?: boolean }>().response<unknown>(),
    partialUpdate: patch('/users/{id}').body<{ name?: string; email?: string }>().query<{ notify?: boolean }>().response<unknown>(),
  },
});

Llamadas con y sin query

// GET sin query
await api.users.search();

// GET con query tipada
await api.users.search({ q: 'neo', limit: 10 });

// GET con bindings y query
await api.users.getById({ include: 'profile' }, { id: 1 });

// POST con body, sin query
await api.users.create({ name: 'John', email: 'john@example.com' });

// POST con body y query
await api.users.create(
  { name: 'John', email: 'john@example.com' },
  { sendWelcomeEmail: true }
);

// PATCH con body y bindings
await api.users.partialUpdate({ name: 'John' }, { id: 1 });

// PATCH con body, query y bindings
await api.users.partialUpdate(
  { name: 'John' },
  { notify: true },
  { id: 1 }
);

💡 Evolución y Fluent API

Originalmente, esta librería usaba genéricos directos como get<Response>('/path'). Sin embargo, esto causaba un problema en TypeScript: al especificar un tipo genérico (Response), TypeScript dejaba de inferir automáticamente el literal del path string.

El problema anterior:

// TypeScript infiere Path como 'string' genérico, perdiendo los params {id}
get<Product>('/products/{id}') 
// Resultado: api.products.getById() <- No pide argumentos

La solución Fluent API:

// 1. Infiere el path primero ('/products/{id}')
// 2. Añade tipos incrementalmente
get('/products/{id}').response<Product>()
// Resultado: api.products.getById({ id: 1 }) <- Correctamente tipado

Esta nueva sintaxis permite mantener la inferencia precisa de los parámetros de ruta mientras se definen fuertemente los tipos de respuesta, body y query params.

📋 Orden de argumentos y bindings

Los helpers aceptan argumentos en un orden consistente que determina cómo se construye la request de axios:

// GET / DELETE
// Sin bindings: (query?)
await api.users.getAll();
await api.users.search({ q: 'neo', limit: 10 });

// Con bindings: (bindings) o (query, bindings)
await api.users.getById({ id: 1 });
await api.users.getById({ include: 'profile' }, { id: 1 });

// POST / PUT / PATCH
// Sin bindings: (body, query?)
await api.users.create({ name: 'John', email: 'john@example.com' });
await api.users.create({ name: 'John', email: 'john@example.com' }, { sendWelcomeEmail: true });

// Con bindings: (body, bindings) o (body, query, bindings)
await api.users.update({ name: 'Jane' }, { id: 3 });
await api.users.partialUpdate({ name: 'Neo' }, { notify: true }, { id: 99 });
  • bindings reemplaza variables de ruta {id} en el url (ver src/core/AxiosManager.ts:113-121).
  • query se envía como axios params (ver GET/DELETE en src/core/AxiosManager.ts:75-86).
  • body se envía como axios data (ver POST/PUT/PATCH en src/core/AxiosManager.ts:101-106).

Esto permite que las firmas sean limpias y que el path se infiera directamente del argumento de la función, evitando repetirlo en los genéricos.

📘 Uso de TypeScript

Tipar rutas y obtener funciones tipadas

const routes = createRouteConfig({
  products: {
    // Definir respuesta en la configuración (Recomendado)
    getAll: get('/products').response<Product[]>(),
    // Definir query params
    search: get('/products/search').query<{ q: string; limit?: number }>().response<Product[]>(),
  },
});

type Routes = typeof routes;
const manager = createAxiosManager<Routes>({ baseURL: 'https://api.example.com' });
const api = manager.createTypedRoutes(routes);

Tipar la respuesta al llamar (Override)

Si no defines el tipo de respuesta en la configuración, o quieres sobrescribirlo:

type Product = { id: number; name: string };

// Si la ruta se definió como: get('/products') -> response es unknown
const products = await api.products.getAll<Product[]>();
// products: Product[]

// También funciona para sobrescribir el tipo definido
const products = await api.products.getAll<CustomProductType[]>();

Tipos auxiliares disponibles

import type { QueryParams, PathBindings, ResponseWrapper } from 'typed-axios-manager';

const qp: QueryParams = { q: 'neo', limit: 10 };
const pb: PathBindings = { id: 1 };
const res: ResponseWrapper<{ ok: boolean }> = { code: 'SUCCESS', httpStatus: 200, message: 'OK', data: { ok: true } };

🎯 Uso con React (Opcional)

Con Hooks

import { useApiCall, useAuth } from 'typed-axios-manager';

function UserProfile({ userId }: { userId: number }) {
  const { execute, loading, error, data: user } = useApiCall(manager);

  useEffect(() => {
    execute(() => api.users.getById({ id: userId }));
  }, [userId, execute]);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!user) return <div>No user found</div>;

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

Con Context Provider

import { createAxiosContext } from 'typed-axios-manager';

const { Provider: AxiosProvider, useApi, useManager } = createAxiosContext<ApiRoutes>();

function App() {
  return (
    <AxiosProvider manager={manager}>
      <YourComponents />
    </AxiosProvider>
  );
}

function YourComponent() {
  const api = useApi();
  const manager = useManager();
  
  // Usa api.auth.login(), api.users.getAll(), etc.
}

🛠️ Uso con Node.js/Next.js/Astro

// server/api.ts
import { createAxiosManager, createRouteConfig, get, post } from 'typed-axios-manager';

const routes = createRouteConfig({
  posts: {
    getAll: get('/posts'),
    create: post('/posts'),
  },
});

const apiManager = createAxiosManager<typeof routes>({
  baseURL: process.env.API_URL || 'https://api.example.com',
});

export const api = apiManager.createTypedRoutes(routes);

// pages/api/posts.ts (Next.js)
import { api } from '../server/api';

export default async function handler(req, res) {
  try {
    const posts = await api.posts.getAll();
    res.json(posts);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
}

⚙️ Configuración Avanzada

Headers Dinámicos

// Establecer token de autenticación
manager.setAuthToken('your-jwt-token');

// Agregar headers personalizados
manager.setHeader('X-Custom-Header', 'value');

// Remover token
manager.removeAuthToken();

Múltiples Instancias

const publicApi = createAxiosManager({ 
  baseURL: 'https://api.public.com' 
});

const privateApi = createAxiosManager({ 
  baseURL: 'https://api.private.com' 
});

const publicRoutes = publicApi.createTypedRoutes(publicRouteConfig);
const privateRoutes = privateApi.createTypedRoutes(privateRouteConfig);

📚 API Reference

createAxiosManager(config)

Crea una nueva instancia del manager.

Parámetros:

  • baseURL?: string - URL base para todas las peticiones
  • timeout?: number - Timeout en milisegundos (default: 5000)
  • headers?: Record<string, string> - Headers por defecto

Retorna: AxiosManager<T>

createRouteConfig(config)

Crea una configuración de rutas tipadas.

Retorna: T (tipado según tu configuración)

Helpers de rutas

  • get(path) - GET request
  • post(path) - POST request
  • put(path) - PUT request
  • del(path) - DELETE request
  • patch(path) - PATCH request

Manager Methods

  • createTypedRoutes(config) - Crea las funciones tipadas
  • setHeader(key, value) - Establece un header
  • setAuthToken(token) - Establece token de auth
  • removeAuthToken() - Remueve el token
  • getInstance() - Obtiene la instancia de axios

React Hooks (opcionales)

  • useApiCall(manager) - Hook para llamadas con loading/error states
  • useAuth(manager) - Hook para autenticación
  • createAxiosContext() - Crea context provider

🤝 Contribuir

¡Las contribuciones son bienvenidas! Por favor:

  • Fork el proyecto
  • Crea una rama para tu feature (git checkout -b feature/AmazingFeature)
  • Commit tus cambios (git commit -m 'Add some AmazingFeature')
  • Push a la rama (git push origin feature/AmazingFeature)
  • Abre un Pull Request

📝 Licencia

Este proyecto está bajo la Licencia MIT.

Keywords

axios

FAQs

Package last updated on 09 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts