diff --git a/plugins/catalog-graph/api-report.md b/plugins/catalog-graph/api-report.md
new file mode 100644
index 0000000000..9131c45ba3
--- /dev/null
+++ b/plugins/catalog-graph/api-report.md
@@ -0,0 +1,139 @@
+## API Report File for "@backstage/plugin-catalog-graph"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+///
+
+import { BackstagePlugin } from '@backstage/core-plugin-api';
+import { DependencyGraphTypes } from '@backstage/core-components';
+import { EntityName } from '@backstage/catalog-model';
+import { ExternalRouteRef } from '@backstage/core-plugin-api';
+import { InfoCardVariants } from '@backstage/core-components';
+import { MouseEvent as MouseEvent_2 } from 'react';
+import { MouseEventHandler } from 'react';
+import { RouteRef } from '@backstage/core-plugin-api';
+
+// @public
+export const CatalogGraphPage: ({
+ relationPairs,
+ initialState,
+}: {
+ relationPairs?: RelationPairs | undefined;
+ initialState?:
+ | {
+ selectedRelations?: string[] | undefined;
+ selectedKinds?: string[] | undefined;
+ rootEntityRefs?: string[] | undefined;
+ maxDepth?: number | undefined;
+ unidirectional?: boolean | undefined;
+ mergeRelations?: boolean | undefined;
+ direction?: Direction | undefined;
+ showFilters?: boolean | undefined;
+ }
+ | undefined;
+}) => JSX.Element;
+
+// @public
+export const catalogGraphPlugin: BackstagePlugin<
+ {
+ catalogGraph: RouteRef;
+ },
+ {
+ catalogEntity: ExternalRouteRef<
+ {
+ name: string;
+ kind: string;
+ namespace: string;
+ },
+ false
+ >;
+ }
+>;
+
+// @public
+export const catalogGraphRouteRef: RouteRef;
+
+// @public
+export enum Direction {
+ BOTTOM_TOP = 'BT',
+ LEFT_RIGHT = 'LR',
+ RIGHT_LEFT = 'RL',
+ TOP_BOTTOM = 'TB',
+}
+
+// @public
+export const EntityCatalogGraphCard: ({
+ variant,
+ relationPairs,
+ maxDepth,
+ unidirectional,
+ mergeRelations,
+ kinds,
+ relations,
+ direction,
+ maxHeight,
+ title,
+}: {
+ variant?: InfoCardVariants | undefined;
+ relationPairs?: RelationPairs | undefined;
+ maxDepth?: number | undefined;
+ unidirectional?: boolean | undefined;
+ mergeRelations?: boolean | undefined;
+ kinds?: string[] | undefined;
+ relations?: string[] | undefined;
+ direction?: Direction | undefined;
+ maxHeight?: number | undefined;
+ title?: string | undefined;
+}) => JSX.Element;
+
+// @public
+export type EntityEdge = DependencyGraphTypes.DependencyEdge<{
+ relations: string[];
+ label: 'visible';
+}>;
+
+// @public
+export type EntityNode = DependencyGraphTypes.DependencyNode<{
+ name: string;
+ kind?: string;
+ title?: string;
+ namespace: string;
+ focused?: boolean;
+ color?: 'primary' | 'secondary' | 'default';
+ onClick?: MouseEventHandler;
+}>;
+
+// @public
+export const EntityRelationsGraph: ({
+ rootEntityNames,
+ maxDepth,
+ unidirectional,
+ mergeRelations,
+ kinds,
+ relations,
+ direction,
+ onNodeClick,
+ relationPairs,
+ className,
+}: {
+ rootEntityNames: EntityName | EntityName[];
+ maxDepth?: number | undefined;
+ unidirectional?: boolean | undefined;
+ mergeRelations?: boolean | undefined;
+ kinds?: string[] | undefined;
+ relations?: string[] | undefined;
+ direction?: Direction | undefined;
+ onNodeClick?:
+ | ((value: EntityNode, event: MouseEvent_2) => void)
+ | undefined;
+ relationPairs?: RelationPairs | undefined;
+ className?: string | undefined;
+}) => JSX.Element;
+
+// @public
+export const RELATION_PAIRS: RelationPairs;
+
+// @public
+export type RelationPairs = [string, string][];
+```
diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json
index 2a47979a06..b0ab659d5d 100644
--- a/plugins/catalog-graph/package.json
+++ b/plugins/catalog-graph/package.json
@@ -11,7 +11,7 @@
},
"scripts": {
"build": "backstage-cli plugin:build",
- "start": "backstage-cli plugin:serve --config ../../app-config.yaml",
+ "start": "backstage-cli plugin:serve",
"lint": "backstage-cli lint",
"test": "backstage-cli test",
"diff": "backstage-cli plugin:diff",
@@ -46,7 +46,11 @@
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^13.1.8",
- "@testing-library/react-hooks": "^3.4.2"
+ "@testing-library/react-hooks": "^3.4.2",
+ "@types/jest": "^26.0.7",
+ "@types/node": "^14.14.32",
+ "cross-fetch": "^3.0.6",
+ "msw": "^0.29.0"
},
"files": [
"dist"
diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx
index 78d02d6f3f..bb61e622e4 100644
--- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx
+++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx
@@ -47,19 +47,6 @@ const useStyles = makeStyles({
},
});
-export type Props = {
- variant?: InfoCardVariants;
- relationPairs?: RelationPairs;
- maxDepth?: number;
- unidirectional?: boolean;
- mergeRelations?: boolean;
- kinds?: string[];
- relations?: string[];
- direction?: Direction;
- maxHeight?: number;
- title?: string;
-};
-
export const CatalogGraphCard = ({
variant = 'gridItem',
relationPairs = RELATION_PAIRS,
@@ -71,7 +58,18 @@ export const CatalogGraphCard = ({
direction = Direction.LEFT_RIGHT,
maxHeight,
title = 'Relations',
-}: Props) => {
+}: {
+ variant?: InfoCardVariants;
+ relationPairs?: RelationPairs;
+ maxDepth?: number;
+ unidirectional?: boolean;
+ mergeRelations?: boolean;
+ kinds?: string[];
+ relations?: string[];
+ direction?: Direction;
+ maxHeight?: number;
+ title?: string;
+}) => {
const { entity } = useEntity();
const entityName = getEntityName(entity);
const catalogEntityRoute = useRouteRef(catalogEntityRouteRef);
diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx
index 8a80b2043e..9dc54e00b2 100644
--- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx
+++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx
@@ -59,6 +59,11 @@ const useStyles = makeStyles(theme => ({
},
}));
+/**
+ * Core building block for custom entity relations diagrams.
+ *
+ * @public
+ */
export const EntityRelationsGraph = ({
rootEntityNames,
maxDepth = Number.POSITIVE_INFINITY,
diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/relations.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/relations.ts
index edde7c46f1..054cf79c9f 100644
--- a/plugins/catalog-graph/src/components/EntityRelationsGraph/relations.ts
+++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/relations.ts
@@ -30,6 +30,12 @@ import {
RELATION_PROVIDES_API,
} from '@backstage/catalog-model';
+/**
+ * A pair of two relations that describe the opposite of each other. The first
+ * relation is considered as the primary relation.
+ *
+ * @public
+ */
export type RelationPairs = [string, string][];
// TODO: This file only contains the pairs for the build-in relations.
@@ -37,6 +43,12 @@ export type RelationPairs = [string, string][];
// the relations everywhere.
// Another option is to move this into @backstage/catalog-model
+/**
+ * A list of pairs of entity relations, used to define which relations are
+ * merged together and which the primary relation is.
+ *
+ * @public
+ */
export const RELATION_PAIRS: RelationPairs = [
[RELATION_OWNER_OF, RELATION_OWNED_BY],
[RELATION_CONSUMES_API, RELATION_API_CONSUMED_BY],
diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/types.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/types.ts
index a7b0c6741c..b5a65580c0 100644
--- a/plugins/catalog-graph/src/components/EntityRelationsGraph/types.ts
+++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/types.ts
@@ -16,19 +16,57 @@
import { DependencyGraphTypes } from '@backstage/core-components';
import { MouseEventHandler } from 'react';
+/**
+ * Edge between two entities.
+ *
+ * @public
+ */
export type EntityEdge = DependencyGraphTypes.DependencyEdge<{
+ /**
+ * Up to two relations that are connecting an entity.
+ */
relations: string[];
+ /**
+ * Whether the entity is visible or not.
+ */
// Not used, but has to be non empty to draw a label at all!
label: 'visible';
}>;
+/**
+ * Node representing an entity.
+ *
+ * @public
+ */
export type EntityNode = DependencyGraphTypes.DependencyNode<{
+ /**
+ * Name of the entity.
+ */
name: string;
+ /**
+ * Optional kind of the entity.
+ */
kind?: string;
+ /**
+ * Optional title of the entity.
+ */
title?: string;
+ /**
+ * Namespace of the entity.
+ */
namespace: string;
+ /**
+ * Whether the entity is focused, optional, defaults to false. Focused
+ * entities are highlighted in the graph.
+ */
focused?: boolean;
+ /**
+ * Optional color of the entity, defaults to 'default'.
+ */
color?: 'primary' | 'secondary' | 'default';
+ /**
+ * Optional click handler.
+ */
onClick?: MouseEventHandler;
}>;
@@ -36,9 +74,26 @@ export type GraphEdge = DependencyGraphTypes.GraphEdge;
export type GraphNode = DependencyGraphTypes.GraphNode;
+/**
+ * Render direction of the graph.
+ *
+ * @public
+ */
export enum Direction {
+ /**
+ * Top to bottom.
+ */
TOP_BOTTOM = 'TB',
+ /**
+ * Bottom to top.
+ */
BOTTOM_TOP = 'BT',
+ /**
+ * Left to right.
+ */
LEFT_RIGHT = 'LR',
+ /**
+ * Right to left.
+ */
RIGHT_LEFT = 'RL',
}
diff --git a/plugins/catalog-graph/src/extensions.tsx b/plugins/catalog-graph/src/extensions.tsx
index 3b933b906c..5dbd7c50ea 100644
--- a/plugins/catalog-graph/src/extensions.tsx
+++ b/plugins/catalog-graph/src/extensions.tsx
@@ -20,6 +20,11 @@ import {
import { catalogGraphPlugin } from './plugin';
import { catalogGraphRouteRef } from './routes';
+/**
+ * A card that displays the directly related entities to the current entity.
+ *
+ * @public
+ */
export const EntityCatalogGraphCard = catalogGraphPlugin.provide(
createComponentExtension({
component: {
@@ -29,6 +34,12 @@ export const EntityCatalogGraphCard = catalogGraphPlugin.provide(
}),
);
+/**
+ * A standalone page that can be added to your application providing a viewer
+ * for your entities and their relations.
+ *
+ * @public
+ */
export const CatalogGraphPage = catalogGraphPlugin.provide(
createRoutableExtension({
component: () =>
diff --git a/plugins/catalog-graph/src/index.ts b/plugins/catalog-graph/src/index.ts
index 1a12e9ea84..af81b076f2 100644
--- a/plugins/catalog-graph/src/index.ts
+++ b/plugins/catalog-graph/src/index.ts
@@ -13,6 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+/**
+ * The catalog graph visualizes the relations between entities, like ownership,
+ * grouping or API relationships.
+ *
+ * @packageDocumentation
+ */
+
export * from './components';
export { CatalogGraphPage, EntityCatalogGraphCard } from './extensions';
export { catalogGraphPlugin } from './plugin';
diff --git a/plugins/catalog-graph/src/plugin.ts b/plugins/catalog-graph/src/plugin.ts
index d795643450..b804ce1e63 100644
--- a/plugins/catalog-graph/src/plugin.ts
+++ b/plugins/catalog-graph/src/plugin.ts
@@ -16,6 +16,10 @@
import { createPlugin } from '@backstage/core-plugin-api';
import { catalogEntityRouteRef, catalogGraphRouteRef } from './routes';
+/**
+ * Catalog Graph Plugin instance.
+ * @public
+ */
export const catalogGraphPlugin = createPlugin({
id: '@internal/catalog-graph',
routes: {
diff --git a/plugins/catalog-graph/src/routes.ts b/plugins/catalog-graph/src/routes.ts
index 6516bcc1f0..9f8372c7a5 100644
--- a/plugins/catalog-graph/src/routes.ts
+++ b/plugins/catalog-graph/src/routes.ts
@@ -18,11 +18,22 @@ import {
createRouteRef,
} from '@backstage/core-plugin-api';
+/**
+ * Route pointing to the standalone catalog graph page.
+ *
+ * @public
+ */
export const catalogGraphRouteRef = createRouteRef({
path: '/catalog-graph',
title: 'Catalog Graph',
});
+/**
+ * Route pointing to the entity page.
+ * Used to navigate from the graph to an entity.
+ *
+ * @public
+ */
export const catalogEntityRouteRef = createExternalRouteRef({
id: 'catalog-entity',
params: ['namespace', 'kind', 'name'],