Ejemplos con JavaScript / TypeScript
Los snippets usan fetch (disponible en Node 18+, Bun, Deno y todos los
navegadores). Si prefieres axios o ky, la lógica es la misma.
Cliente mínimo
const BASE = 'http://localhost/api/v1';
async function login(usuario: string, password: string) {
const res = await fetch(`${BASE}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ usuario, password }),
});
if (!res.ok) throw new Error(`Login falló: ${res.status}`);
const json = await res.json();
return json.data.token as string;
}
async function get<T>(path: string, token: string): Promise<T> {
const res = await fetch(`${BASE}${path}`, {
headers: { Authorization: `Bearer ${token}` },
});
const json = await res.json();
if (json.errors) throw new Error(json.errors[0].message);
return json.data;
}
const token = await login('cb', '1234');
const monedas = await get<Array<{ id: number; nombre: string }>>('/Moneda', token);
console.log(monedas);Manejo de errores tipado
type ApiError = { code: string; message: string; field?: string | null };
type ApiResponse<T> = { data: T | null; meta: Record<string, unknown>; errors: ApiError[] | null };
async function call<T>(path: string, init: RequestInit, token?: string): Promise<T> {
const headers: HeadersInit = {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...init.headers,
};
const res = await fetch(`${BASE}${path}`, { ...init, headers });
const json = (await res.json()) as ApiResponse<T>;
if (json.errors && json.errors.length > 0) {
const first = json.errors[0];
const err = new Error(first.message);
(err as Error & { code?: string }).code = first.code;
throw err;
}
return json.data as T;
}Iterar todas las páginas
async function listAll<T>(modelo: string, token: string): Promise<T[]> {
const all: T[] = [];
let page = 1;
while (true) {
const res = await fetch(`${BASE}/${modelo}?page=${page}&per_page=100`, {
headers: { Authorization: `Bearer ${token}` },
});
const json = await res.json();
all.push(...json.data);
if (page >= json.meta.pages) break;
page++;
}
return all;
}
const compras = await listAll<{ id: number; total: number }>('Compra', token);
console.log(`Total compras: ${compras.length}`);Business Action — autorizar batch
async function autorizarCompras(ids: number[], token: string) {
const res = await fetch(`${BASE}/Compra/actions/autorizar_compra`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
body: JSON.stringify({ ids }),
});
const json = await res.json();
const failures = json.data.results.filter((r: { ok: boolean }) => !r.ok);
return { succeeded: json.meta.succeeded, failed: json.meta.failed, failures };
}
const result = await autorizarCompras([12345, 12346, 12347], token);
if (result.failed > 0) {
console.warn(`${result.failed} fallaron:`, result.failures);
}