diff --git a/.changeset/green-otters-wait.md b/.changeset/green-otters-wait.md
new file mode 100644
index 0000000000..4f9b02351e
--- /dev/null
+++ b/.changeset/green-otters-wait.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-catalog-unprocessed-entities': patch
+---
+
+Export some types and API items. This allows people to call the API from different places with the ApiRef, as well
+as completely customize the client if required. Check the [README.md](../plugins/catalog-unprocessed-entities/README.md) to
+note what needs to be added in order to use the new `catalogUnprocessedEntitiesApiRef` exported function.
diff --git a/plugins/catalog-unprocessed-entities/README.md b/plugins/catalog-unprocessed-entities/README.md
index c0dd996016..699629e0b2 100644
--- a/plugins/catalog-unprocessed-entities/README.md
+++ b/plugins/catalog-unprocessed-entities/README.md
@@ -44,6 +44,39 @@ import { CatalogUnprocessedEntitiesPage } from '@backstage/plugin-catalog-unproc
/>;
```
+## Customization
+
+If you want to use the provided endpoints in a different way, you can use the ApiRef doing the following:
+
+```typescript
+import { catalogUnprocessedEntitiesApiRef } from '@backstage/plugin-catalog-unprocessed-entities';
+import { useApi } from '@backstage/core-plugin-api';
+
+const catalogUnprocessedEntitiesApi = useApi(catalogUnprocessedEntitiesApiRef);
+```
+
+Note that if you are not rendering the `CatalogUnprocessedEntitiesPage` in the `App.tsx` tree, you will need to export the `catalogUnproccessedEntitiesPlugin` from your `plugins.ts` file to setup the plugin otherwise you will receive an error like `No implementation available for apiRef{plugin.catalog-unprocessed-entities.service}`
+
+```typescript
+// In packages/app/src/plugins.ts
+...
+export { catalogUnprocessedEntitiesPlugin } from '@backstage/plugin-catalog-unprocessed-entities';
+```
+
+If you don't have a `plugins.ts` file, you can create it with the path `packages/app/src/plugins.ts` and then import it into your `App.tsx`:
+
+```diff
++ import * as plugins from './plugins';
+
+const app = createApp({
+ apis,
++ plugins: Object.values(plugins),
+ bindRoutes({ bind }) {
+ /* ... */
+ },
+});
+```
+
## Getting started
Your plugin has been added to the example app in this repository,
diff --git a/plugins/catalog-unprocessed-entities/api-report.md b/plugins/catalog-unprocessed-entities/api-report.md
index 940bc2b3a5..0ccf9716f2 100644
--- a/plugins/catalog-unprocessed-entities/api-report.md
+++ b/plugins/catalog-unprocessed-entities/api-report.md
@@ -5,9 +5,25 @@
```ts
///
+import { ApiRef } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '@backstage/core-plugin-api';
+import { Entity } from '@backstage/catalog-model';
import { RouteRef } from '@backstage/core-plugin-api';
+// @public
+export interface CatalogUnprocessedEntitiesApi {
+ failed(): Promise;
+ pending(): Promise;
+}
+
+// @public
+export const catalogUnprocessedEntitiesApiRef: ApiRef;
+
+// @public
+export type CatalogUnprocessedEntitiesApiResponse = {
+ entities: UnprocessedEntity[];
+};
+
// @public
export const CatalogUnprocessedEntitiesPage: () => JSX.Element;
@@ -23,5 +39,37 @@ export const catalogUnprocessedEntitiesPlugin: BackstagePlugin<
// @public (undocumented)
export const UnprocessedEntitiesContent: () => JSX.Element;
+// @public
+export type UnprocessedEntity = {
+ entity_id: string;
+ entity_ref: string;
+ unprocessed_entity: Entity;
+ unprocessed_hash?: string;
+ processed_entity?: Entity;
+ result_hash?: string;
+ cache?: UnprocessedEntityCache;
+ next_update_at: string | Date;
+ last_discovery_at: string | Date;
+ errors?: UnprocessedEntityError[];
+ location_key?: string;
+};
+
+// @public
+export type UnprocessedEntityCache = {
+ ttl: number;
+ cache: object;
+};
+
+// @public
+export type UnprocessedEntityError = {
+ name: string;
+ message: string;
+ cause: {
+ name: string;
+ message: string;
+ stack: string;
+ };
+};
+
// (No @packageDocumentation comment for this package)
```
diff --git a/plugins/catalog-unprocessed-entities/src/api/index.ts b/plugins/catalog-unprocessed-entities/src/api/index.ts
index 5be81c8331..92dde93a93 100644
--- a/plugins/catalog-unprocessed-entities/src/api/index.ts
+++ b/plugins/catalog-unprocessed-entities/src/api/index.ts
@@ -32,20 +32,43 @@ export const catalogUnprocessedEntitiesApiRef =
});
/**
- * API client for the Catalog Unprocessed Entities plugin
+ * Response expected by the {@link CatalogUnprocessedEntitiesApi}
*
* @public
*/
-export class CatalogUnprocessedEntitiesApi {
- url: string = '';
+export type CatalogUnprocessedEntitiesApiResponse = {
+ entities: UnprocessedEntity[];
+};
+/**
+ * Interface for the CatalogUnprocessedEntitiesApi.
+ *
+ * @public
+ */
+export interface CatalogUnprocessedEntitiesApi {
+ /**
+ * Returns a list of entities with state 'pending'
+ */
+ pending(): Promise;
+ /**
+ * Returns a list of entities with state 'failed'
+ */
+ failed(): Promise;
+}
+
+/**
+ * Default API implementation for the Catalog Unprocessed Entities plugin
+ *
+ * @public
+ */
+export class CatalogUnprocessedEntitiesClient
+ implements CatalogUnprocessedEntitiesApi
+{
constructor(public discovery: DiscoveryApi, public fetchApi: FetchApi) {}
private async fetch(path: string, init?: RequestInit): Promise {
- if (!this.url) {
- this.url = await this.discovery.getBaseUrl('catalog');
- }
- const resp = await this.fetchApi.fetch(`${this.url}/${path}`, init);
+ const url = await this.discovery.getBaseUrl('catalog');
+ const resp = await this.fetchApi.fetch(`${url}/${path}`, init);
if (!resp.ok) {
throw await ResponseError.fromResponse(resp);
}
@@ -53,11 +76,11 @@ export class CatalogUnprocessedEntitiesApi {
return await resp.json();
}
- async pending(): Promise<{ entities: UnprocessedEntity[] }> {
+ async pending(): Promise {
return await this.fetch('entities/unprocessed/pending');
}
- async failed(): Promise<{ entities: UnprocessedEntity[] }> {
+ async failed(): Promise {
return await this.fetch('entities/unprocessed/failed');
}
}
diff --git a/plugins/catalog-unprocessed-entities/src/index.ts b/plugins/catalog-unprocessed-entities/src/index.ts
index 11ed24113f..4fcc9a8fcd 100644
--- a/plugins/catalog-unprocessed-entities/src/index.ts
+++ b/plugins/catalog-unprocessed-entities/src/index.ts
@@ -18,3 +18,13 @@ export {
CatalogUnprocessedEntitiesPage,
} from './plugin';
export { UnprocessedEntitiesContent } from './components/UnprocessedEntities';
+export {
+ type CatalogUnprocessedEntitiesApiResponse,
+ type CatalogUnprocessedEntitiesApi,
+ catalogUnprocessedEntitiesApiRef,
+} from './api';
+export type {
+ UnprocessedEntity,
+ UnprocessedEntityCache,
+ UnprocessedEntityError,
+} from './types';
diff --git a/plugins/catalog-unprocessed-entities/src/plugin.ts b/plugins/catalog-unprocessed-entities/src/plugin.ts
index 14598c825b..baf7278454 100644
--- a/plugins/catalog-unprocessed-entities/src/plugin.ts
+++ b/plugins/catalog-unprocessed-entities/src/plugin.ts
@@ -23,7 +23,7 @@ import {
import { rootRouteRef } from './routes';
import {
- CatalogUnprocessedEntitiesApi,
+ CatalogUnprocessedEntitiesClient,
catalogUnprocessedEntitiesApiRef,
} from './api';
@@ -42,7 +42,7 @@ export const catalogUnprocessedEntitiesPlugin = createPlugin({
api: catalogUnprocessedEntitiesApiRef,
deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },
factory: ({ discoveryApi, fetchApi }) =>
- new CatalogUnprocessedEntitiesApi(discoveryApi, fetchApi),
+ new CatalogUnprocessedEntitiesClient(discoveryApi, fetchApi),
}),
],
});
diff --git a/plugins/catalog-unprocessed-entities/src/types.ts b/plugins/catalog-unprocessed-entities/src/types.ts
index 490027b57a..65f21970f5 100644
--- a/plugins/catalog-unprocessed-entities/src/types.ts
+++ b/plugins/catalog-unprocessed-entities/src/types.ts
@@ -15,6 +15,10 @@
*/
import { Entity } from '@backstage/catalog-model';
+/**
+ * Unprocessed entity data stored in the database.
+ * @public
+ */
export type UnprocessedEntity = {
entity_id: string;
entity_ref: string;
@@ -29,11 +33,19 @@ export type UnprocessedEntity = {
location_key?: string;
};
+/**
+ * Unprocessed entity cache stored in the database.
+ * @public
+ */
export type UnprocessedEntityCache = {
ttl: number;
cache: object;
};
+/**
+ * Unprocessed entity error information stored in the database.
+ * @public
+ */
export type UnprocessedEntityError = {
name: string;
message: string;