Frontend: datos, APIs y APIs de Backstage
|
Objetivos del capítulo
|
ApisRegistry: el bus del frontend
El backend tiene coreServices; el frontend tiene ApisRegistry. Es el mismo concepto: una pieza pide lo que necesita y el shell se lo inyecta. La sala del restaurante tiene su propio sistema de pedidos: cada camarero pide al jefe de sala y el jefe le pasa lo que necesita.
Backstage expone APIs de sistema a través de refs:
-
:code:`catalogApiRef` — acceso al catalog.
-
:code:`errorApiRef` — notificación de errores.
-
:code:`identityApiRef` — usuario autenticado.
-
:code:`notificationApiRef` — toasts.
-
:code:`fetchApiRef` — fetch configurado con auth headers.
Consumir el catalog con useApi
Un hook que consulta el catalog de Sazón Foods:
import { useEffect, useState } from 'react';
import { useApi, errorApiRef } from '@backstage/core-plugin-api';
import { catalogApiRef } from '@backstage/plugin-catalog-react';
import { Entity } from '@backstage/catalog-model';
export function useSazonComponents(): {
components: Entity[] | null;
loading: boolean;
} {
const catalogApi = useApi(catalogApiRef);
const errorApi = useApi(errorApiRef);
const [components, setComponents] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
catalogApi
.getEntities({ filter: { kind: 'Component', 'spec.system': 'sazon-restaurant' } })
.then(res => setComponents(res.items))
.catch(err => errorApi.post(err))
.finally(() => setLoading(false));
}, [catalogApi, errorApi]);
return { components, loading };
}
|
Lo que acabas de hacer
|
|
Filtros de catalog
El parámetro
Combina con :code:`fields:` para reducir el payload. |
Consumir tu propio backend
Para llamar a un endpoint custom (como /api/sazon/status del :cap-06), usa fetchApiRef o el fetch global según el caso:
export function useCustomSazonStatus(): { rows: { service: string; status: string }[] | null } {
const [rows, setRows] = useState<{ service: string; status: string }[] | null>(null);
useEffect(() => {
// /api/sazon-status is proxied to the backend (see app-config dev server).
fetch('/api/sazon/status')
.then(r => r.json())
.then(j => setRows(j.rows ?? []))
.catch(() => setRows([]));
}, []);
return { rows };
}
|
Proxy en desarrollo
:code:`fetch('/api/…')` desde el navegador solo funciona si el frontend tiene un proxy al backend en
En producción, el frontend se sirve detrás del mismo dominio que el backend o un proxy inverso. |
Manejo de errores
Tres reglas:
-
Nunca
console.errory ya. UsaerrorApi.post(err)para que aparezca la UI de error. -
Loading y error states son obligatorios en cualquier fetch. Muestra un
<Progress />mientras loading y un<EmptyState />si la lista está vacía. -
401/403 se manejan vía el
ErrorApi. Backstage los trata especialmente: el 401 te redirige a login.
-
Importa los refs (
catalogApiRef,errorApiRef) que necesites. -
Usa
useApi(ref)para resolverlos en componentes. -
Para datos de catálogo, prefiere
catalogApi.getEntities()sobre fetch manual. -
Para endpoints custom, configura el proxy y usa
fetchApiRef. -
Maneja loading, error y empty state en cada componente que hace fetch.
Resumen
-
ApisRegistryexpone servicios del shell a los plugins. -
useApi(ref)los resuelve en componentes. -
catalogApiRefda acceso al catalog con filtros estructurados. -
errorApi.post(err)muestra errores en la UI estándar.
Glosario del capítulo
- ApisRegistry
-
Bus de APIs del shell, equivalente frontend de
coreServices. - ref
-
Objeto
ApiRef<T>que identifica un API por su tipo T. - useApi
-
Hook que resuelve un ref en su implementación inyectada.
- fetchApiRef
-
Ref al fetch configurado con auth headers del shell.
- proxy
-
Config de
app-config.yamlque redirige paths del dev server al backend.
Próximo capítulo
Componentes, tablas y UX consistente —composición con Material UI y los componentes de @backstage/core-components.