CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-backstage--plugin-catalog-react

A frontend library that helps other Backstage plugins interact with the catalog through React components, hooks, and utilities.

Pending
Overview
Eval results
Files

api-integration.mddocs/

API Integration

API references and utilities for integrating with the Backstage catalog backend and related services. These provide standardized interfaces for data fetching and service integration.

Capabilities

Catalog API Reference

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
}

Starred Entities API

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();

Entity Presentation API

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>
  );
}

Re-exported APIs

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;
}

API Provider Setup

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>
  );
}

Integration Patterns

Combined API Usage

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

docs

alpha-features.md

api-integration.md

entity-display.md

entity-filters.md

entity-hooks.md

index.md

picker-components.md

utilities.md

tile.json