A frontend library that helps other Backstage plugins interact with the catalog through React components, hooks, and utilities.
—
API references and utilities for integrating with the Backstage catalog backend and related services. These provide standardized interfaces for data fetching and service integration.
Primary API reference for accessing the Backstage catalog backend.
/**
* API reference for the CatalogApi service
* Used with Backstage's dependency injection system
*/
const catalogApiRef: ApiRef<CatalogApi>;Usage Examples:
import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react';
import { useApi } from '@backstage/core-plugin-api';
function EntityLoader() {
const catalogApi = useApi(catalogApiRef);
const loadEntity = async (entityRef: string) => {
try {
const entity = await catalogApi.getEntityByRef(entityRef);
return entity;
} catch (error) {
console.error('Failed to load entity:', error);
throw error;
}
};
const searchEntities = async (filters: any) => {
const { items } = await catalogApi.getEntities({
filter: filters
});
return items;
};
return null; // Component implementation
}API for managing user's starred entities with persistent storage.
/**
* API reference for the StarredEntitiesApi service
*/
const starredEntitiesApiRef: ApiRef<StarredEntitiesApi>;
/**
* API for storing and retrieving starred entities
*/
interface StarredEntitiesApi {
/** Toggle starred status for an entity */
toggleStarred(entityRef: string): Promise<void>;
/** Observable of currently starred entity references */
starredEntitie$(): Observable<Set<string>>;
}
/**
* Mock implementation for testing
*/
class MockStarredEntitiesApi implements StarredEntitiesApi {
toggleStarred(entityRef: string): Promise<void>;
starredEntitie$(): Observable<Set<string>>;
}Usage Examples:
import {
starredEntitiesApiRef,
StarredEntitiesApi,
MockStarredEntitiesApi
} from '@backstage/plugin-catalog-react';
import { useApi } from '@backstage/core-plugin-api';
function StarredEntitiesManager() {
const starredApi = useApi(starredEntitiesApiRef);
const [starredEntities, setStarredEntities] = useState<Set<string>>(new Set());
useEffect(() => {
const subscription = starredApi.starredEntitie$().subscribe(setStarredEntities);
return () => subscription.unsubscribe();
}, [starredApi]);
const toggleStarred = async (entityRef: string) => {
await starredApi.toggleStarred(entityRef);
};
return (
<div>
<h3>Starred Entities ({starredEntities.size})</h3>
{Array.from(starredEntities).map(entityRef => (
<div key={entityRef}>
<EntityRefLink entityRef={entityRef} />
<button onClick={() => toggleStarred(entityRef)}>
Remove Star
</button>
</div>
))}
</div>
);
}
// Testing with mock API
const mockStarredApi = new MockStarredEntitiesApi();API for customizing how entities are visually presented throughout the UI.
/**
* API reference for the EntityPresentationApi service
*/
const entityPresentationApiRef: ApiRef<EntityPresentationApi>;
/**
* API for customizing visual representation of entities
*/
interface EntityPresentationApi {
/** Get presentation configuration for an entity */
forEntity(
entityOrRef: Entity | string,
context?: {
defaultKind?: string;
defaultNamespace?: string;
}
): EntityRefPresentation;
}
/**
* Visual presentation configuration for an entity reference
*/
interface EntityRefPresentation {
/** Current presentation state */
snapshot: EntityRefPresentationSnapshot;
/** Observable for presentation updates */
update$?: Observable<EntityRefPresentationSnapshot>;
}
/**
* Snapshot of entity visual presentation
*/
interface EntityRefPresentationSnapshot {
/** Canonical entity reference string */
entityRef: string;
/** Primary display title */
primaryTitle: string;
/** Optional secondary title/subtitle */
secondaryTitle?: string;
/** Icon component or false to hide icon */
Icon?: IconComponent | undefined | false;
}
/**
* Default implementation for entity presentation
*/
function defaultEntityPresentation(
entity: Entity | string,
context?: { defaultKind?: string; defaultNamespace?: string }
): EntityRefPresentation;
/**
* Hook for using entity presentation in components
*/
function useEntityPresentation(
entityOrRef: Entity | string,
context?: { defaultKind?: string; defaultNamespace?: string }
): EntityRefPresentationSnapshot;Usage Examples:
import {
entityPresentationApiRef,
useEntityPresentation,
defaultEntityPresentation
} from '@backstage/plugin-catalog-react';
import { useApi } from '@backstage/core-plugin-api';
function EntityPresentationExample() {
const presentationApi = useApi(entityPresentationApiRef);
const getEntityPresentation = (entityRef: string) => {
const presentation = presentationApi.forEntity(entityRef);
return presentation.snapshot;
};
return null;
}
// Using the hook directly
function EntityTitle({ entityRef }: { entityRef: string }) {
const presentation = useEntityPresentation(entityRef);
return (
<div>
{presentation.Icon && <presentation.Icon />}
<h2>{presentation.primaryTitle}</h2>
{presentation.secondaryTitle && (
<p>{presentation.secondaryTitle}</p>
)}
</div>
);
}
// Custom presentation configuration
function CustomEntityPresentation() {
const customPresentation = defaultEntityPresentation(
'component:default/my-service',
{ defaultKind: 'component', defaultNamespace: 'default' }
);
const { snapshot } = customPresentation;
return (
<div>
<h3>{snapshot.primaryTitle}</h3>
<p>Reference: {snapshot.entityRef}</p>
</div>
);
}The package also re-exports key types and constants from the catalog client:
/**
* Re-exported from @backstage/catalog-client
* Main interface for catalog backend communication
*/
type CatalogApi = import('@backstage/catalog-client').CatalogApi;
/**
* Re-exported from @backstage/catalog-client
* Constant for existence filters in catalog queries
*/
const CATALOG_FILTER_EXISTS: unique symbol;Usage Examples:
import {
CatalogApi,
CATALOG_FILTER_EXISTS,
catalogApiRef
} from '@backstage/plugin-catalog-react';
import { useApi } from '@backstage/core-plugin-api';
function CatalogQueries() {
const catalogApi = useApi(catalogApiRef);
// Query entities with existence filter
const getEntitiesWithOwner = async () => {
const response = await catalogApi.getEntities({
filter: {
'spec.owner': CATALOG_FILTER_EXISTS
}
});
return response.items;
};
// Get specific entity
const getEntity = async (entityRef: string) => {
return await catalogApi.getEntityByRef(entityRef);
};
// Query with multiple filters
const getComponentsInNamespace = async (namespace: string) => {
const response = await catalogApi.getEntities({
filter: {
kind: 'component',
'metadata.namespace': namespace
}
});
return response.items;
};
return null;
}For testing and development, you can provide mock implementations:
import {
catalogApiRef,
starredEntitiesApiRef,
entityPresentationApiRef,
MockStarredEntitiesApi,
defaultEntityPresentation
} from '@backstage/plugin-catalog-react';
import { TestApiProvider } from '@backstage/test-utils';
function TestWrapper({ children }: { children: React.ReactNode }) {
const mockCatalogApi = {
getEntities: jest.fn(),
getEntityByRef: jest.fn(),
// ... other CatalogApi methods
};
const mockStarredApi = new MockStarredEntitiesApi();
const mockPresentationApi = {
forEntity: (entityOrRef, context) =>
defaultEntityPresentation(entityOrRef, context)
};
return (
<TestApiProvider
apis={[
[catalogApiRef, mockCatalogApi],
[starredEntitiesApiRef, mockStarredApi],
[entityPresentationApiRef, mockPresentationApi],
]}
>
{children}
</TestApiProvider>
);
}import {
catalogApiRef,
starredEntitiesApiRef,
useEntityList
} from '@backstage/plugin-catalog-react';
import { useApi } from '@backstage/core-plugin-api';
function EntityManagerWithStarring() {
const catalogApi = useApi(catalogApiRef);
const starredApi = useApi(starredEntitiesApiRef);
const { entities, updateFilters } = useEntityList();
const [starredEntities, setStarredEntities] = useState<Set<string>>(new Set());
useEffect(() => {
const subscription = starredApi.starredEntitie$().subscribe(setStarredEntities);
return () => subscription.unsubscribe();
}, [starredApi]);
const toggleStarred = async (entityRef: string) => {
await starredApi.toggleStarred(entityRef);
};
const loadAdditionalEntities = async (filter: any) => {
const response = await catalogApi.getEntities({ filter });
return response.items;
};
return (
<div>
{entities.map(entity => {
const entityRef = `${entity.kind}:${entity.metadata.namespace}/${entity.metadata.name}`;
const isStarred = starredEntities.has(entityRef);
return (
<div key={entityRef}>
<EntityRefLink entityRef={entity} />
<button onClick={() => toggleStarred(entityRef)}>
{isStarred ? '⭐' : '☆'}
</button>
</div>
);
})}
</div>
);
}Install with Tessl CLI
npx tessl i tessl/npm-backstage--plugin-catalog-react