API Bridge 🚀
Extensión de VS Code que genera automáticamente un cliente TypeScript tipado a partir de las rutas de tu API Laravel, listo para usar en tu proyecto React.
¿Qué hace?
Cada vez que corrés el comando, API Bridge lee tu routes/api.php y genera dos archivos en tu proyecto React:
src/api/generated.ts — cliente axios con todas tus rutas tipadas
src/api/types.ts — interfaces TypeScript para cada recurso
Y los mantiene sincronizados automáticamente cada vez que guardás cambios en api.php.
Requisitos
- VS Code 1.70 o superior
- Proyecto Laravel con
routes/api.php
- Proyecto React con
src/
- Ambos proyectos abiertos en el mismo workspace
Estructura esperada del workspace
mi-workspace/
├── backend/ ← Proyecto Laravel
│ ├── artisan
│ └── routes/
│ └── api.php
└── frontend/ ← Proyecto React
├── package.json
└── src/
Instalación
- Abrí VS Code
- Instalá la extensión desde el Marketplace o con:
code --install-extension apiBridge-0.0.1.vsix
Uso
Primera vez
- Abrí tu workspace en VS Code (la carpeta raíz que contiene backend y frontend)
- Presioná
Ctrl+Shift+P (o Cmd+Shift+P en Mac)
- Escribí
API Bridge: Generate y presioná Enter
La extensión va a:
- Detectar automáticamente tus proyectos Laravel y React
- Crear el archivo
apiBridge.config.json en la raíz del workspace
- Generar
src/api/generated.ts y src/api/types.ts en tu proyecto React
- Activar el modo watch para detectar cambios futuros en
api.php
Siguientes veces
Simplemente guardá cambios en api.php — la extensión detecta el cambio y regenera automáticamente. Aparecerá una notificación confirmando cuántas rutas se procesaron.
Configuración
Al correr el comando por primera vez se crea apiBridge.config.json en la raíz del workspace:
{
"backendPath": "backend",
"frontendPath": "frontend",
"baseUrl": "http://localhost:8000",
"ignoredRoutes": []
}
| Campo |
Descripción |
Ejemplo |
backendPath |
Path relativo al proyecto Laravel |
"Backend/Sumire-Backed" |
frontendPath |
Path relativo al proyecto React |
"Frontend/Sumire-App" |
baseUrl |
URL base de tu API |
"http://localhost:8000" |
ignoredRoutes |
Rutas a excluir de la generación |
["/health", "/telescope"] |
También podés configurar estos valores en el settings.json de VS Code bajo la clave apiBridge. El archivo apiBridge.config.json tiene prioridad sobre settings.json.
Archivos generados
src/api/generated.ts
Cliente axios con todas tus rutas organizadas por recurso:
import axios from 'axios';
import * as Types from './types';
axios.defaults.baseURL = 'http://localhost:8000';
export const api = {
auth: {
me: () => axios.get<Types.User>(`/user`),
login: (data: Record<string, any>) => axios.post(`/login`, data),
logout: (data: Record<string, any>) => axios.post(`/user/logout`, data),
register: (data: Record<string, any>) => axios.post(`/user/register`, data),
},
users: {
get: () => axios.get<Types.User[]>(`/users`),
getById: (id: string) => axios.get<Types.User>(`/users/${id}`),
create: (data: Partial<Types.User>) => axios.post<Types.User>(`/users`, data),
update: (id: string, data: Partial<Types.User>) => axios.put<Types.User>(`/users/${id}`, data),
delete: (id: string) => axios.delete<void>(`/users/${id}`),
},
};
src/api/types.ts
Interfaces TypeScript listas para completar:
export interface User {
// TODO: definir propiedades
}
Una vez que completás las propiedades, la extensión las respeta y no las sobreescribe en generaciones futuras.
Rutas soportadas en api.php
// ✅ Rutas simples
Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);
Route::patch('/users/{id}', [UserController::class, 'update']); // se normaliza a PUT
// ✅ apiResource (genera las 5 rutas CRUD automáticamente)
Route::apiResource('users', UserController::class);
// ✅ Grupos con prefix
Route::group(['prefix' => 'v1'], function () {
Route::get('/users', [UserController::class, 'index']); // → /v1/users
});
// ✅ Middleware
Route::middleware('auth:sanctum')->group(function () {
Route::get('/profile', [UserController::class, 'profile']);
});
// ✅ Grupos anidados
Route::middleware('auth')->group(function () {
Route::group(['prefix' => 'admin'], function () {
Route::apiResource('users', UserController::class); // → /admin/users
});
});
Uso en React
import { api } from './api/generated';
// Login
const response = await api.auth.login({ email, password });
// Usuario autenticado
const { data: user } = await api.auth.me();
// Lista de recursos
const { data: users } = await api.users.get();
// Por ID
const { data: user } = await api.users.getById('123');
// Crear
await api.users.create({ name: 'John', email: 'john@example.com' });
// Actualizar
await api.users.update('123', { name: 'John Updated' });
// Eliminar
await api.users.delete('123');
Configuración de Sanctum (si usás autenticación por cookies)
// Antes del login, obtener el CSRF cookie
await axios.get('http://localhost:8000/sanctum/csrf-cookie', {
withCredentials: true
});
// Habilitar cookies en todas las requests
axios.defaults.withCredentials = true;
Y en Laravel, en config/cors.php:
'allowed_origins' => ['http://localhost:5173'],
Y en .env:
SANCTUM_STATEFUL_DOMAINS=localhost:5173
SESSION_DOMAIN=localhost
Cómo funciona internamente
api.php (texto)
↓ parser.ts — extrae rutas, controladores y acciones
[{ method, path, controller, action }, ...]
↓ routeClassifier.ts — clasifica rutas CRUD vs acciones
{ resource, method, hasType }
↓ codeGenerator.ts — genera el código TypeScript
generated.ts + types.ts
↓ typeMerger.ts — preserva interfaces ya definidas
types.ts (merge inteligente)
Detección automática de proyectos
La extensión busca recursivamente desde la raíz del workspace:
- Laravel: carpeta que tenga
artisan y routes/api.php
- React: carpeta que tenga
package.json y src/
Ignora node_modules, .git y vendor para mayor velocidad.
Clasificación de rutas
El nombre del controlador determina el grupo en el cliente generado:
| Controlador |
Grupo generado |
UserController |
user |
ProductController |
product |
AuthenticatedSessionController |
auth |
SessionController |
auth |
Las rutas de identidad (/user, /me, /profile) se mapean automáticamente al método me.
Merge inteligente de tipos
Al regenerar, types.ts sigue estas reglas:
- Interfaces nuevas → se agregan con
TODO
- Interfaces con propiedades definidas → se conservan sin cambios
- Interfaces que ya no tienen ruta → se conservan con un comentario indicándolo
Estructura del proyecto
src/
├── extension.ts # Entry point de VS Code
├── parser.ts # Lee y parsea api.php
├── commands/
│ └── generate.ts # Orquesta el comando principal
└── utils/
├── pathUtils.ts # Transformaciones de rutas
├── projectFinder.ts # Detección de proyectos
├── routeClassifier.ts # Clasifica rutas CRUD vs acciones
├── codeGenerator.ts # Genera generated.ts
├── typeMerger.ts # Merge inteligente de types.ts
├── watcher.ts # Watch automático de api.php
└── config.ts # Carga de configuración
Limitaciones conocidas
- La singularización de tipos es básica:
users → User, products → Product. Irregulares como people o children no se manejan automáticamente.
- Rutas definidas en variables o con métodos muy encadenados pueden no parsearse correctamente.
- El modo watch se activa recién después de correr el comando por primera vez en cada sesión de VS Code.