[catalog-unprocessed-entities] Move types and clients from frontend to common plugin

Moved some types, as well as the API and client definitions to the common package.
The original types, client and interface are now re-exported from the common package instead.

This allows not only frontend plugins, but also backend ones, to use this client
if needed. Until now, and since the types and all definitions were stored in the
frontend plugin, the only way to implement such feature was to copy the code
in the project. It would make much more sense to make this exportable from the
plugin itself and let people use this plugin if needed.

I made this change a patch, since all types have been initially deprecated and
a mention to the new location has been added.

Signed-off-by: ivangonzalezacuna <ivangonzalezacuna@gmail.com>
This commit is contained in:
ivangonzalezacuna
2025-11-05 13:32:41 +01:00
parent e512dfd1e5
commit df4d64609e
12 changed files with 355 additions and 128 deletions
+15
View File
@@ -0,0 +1,15 @@
---
'@backstage/plugin-catalog-unprocessed-entities-common': patch
'@backstage/plugin-catalog-unprocessed-entities': patch
---
Moved types, API and client to the common package, allowing both frontend and
backend plugins to use the `CatalogUnprocessedEntitiesClient`.
The following types, clients and interfaces have been deprecated and should be
imported from the `@backstage/plugin-catalog-unprocessed-entities-common` instead:
`CatalogUnprocessedEntitiesApi`, `CatalogUnprocessedEntitiesApiResponse`, `UnprocessedEntity`,
`UnprocessedEntityCache`, `UnprocessedEntityError`, `CatalogUnprocessedEntitiesClient`.
All those types, clients and interfaces are re-exported temporarily in the
`@backstage/plugin-catalog-unprocessed-entities` package until cleaned up.
@@ -37,6 +37,8 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/catalog-model": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^"
},
"devDependencies": {
@@ -4,6 +4,53 @@
```ts
import { BasicPermission } from '@backstage/plugin-permission-common';
import { Entity } from '@backstage/catalog-model';
// @public
export interface CatalogUnprocessedEntitiesApi {
delete(
entityId: string,
options?: UnprocessedEntitiesRequestOptions,
): Promise<void>;
failed(
options?: UnprocessedEntitiesRequestOptions,
): Promise<CatalogUnprocessedEntitiesApiResponse>;
pending(
options?: UnprocessedEntitiesRequestOptions,
): Promise<CatalogUnprocessedEntitiesApiResponse>;
}
// @public
export type CatalogUnprocessedEntitiesApiResponse = {
entities: UnprocessedEntity[];
};
// @public
export class CatalogUnprocessedEntitiesClient
implements CatalogUnprocessedEntitiesApi
{
constructor(
discovery: {
getBaseUrl(pluginId: string): Promise<string>;
},
fetchApi?: {
fetch: typeof fetch;
},
);
// (undocumented)
delete(
entityId: string,
options?: UnprocessedEntitiesRequestOptions,
): Promise<void>;
// (undocumented)
failed(
options?: UnprocessedEntitiesRequestOptions,
): Promise<CatalogUnprocessedEntitiesApiResponse>;
// (undocumented)
pending(
options?: UnprocessedEntitiesRequestOptions,
): Promise<CatalogUnprocessedEntitiesApiResponse>;
}
// @public
export const unprocessedEntitiesDeletePermission: BasicPermission;
@@ -12,4 +59,42 @@ export const unprocessedEntitiesDeletePermission: BasicPermission;
export const unprocessedEntitiesPermissions: {
unprocessedEntitiesDeletePermission: BasicPermission;
};
// @public
export interface UnprocessedEntitiesRequestOptions {
// (undocumented)
token?: string;
}
// @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;
};
};
```
@@ -0,0 +1,124 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { CatalogUnprocessedEntitiesApiResponse } from '../types';
import { ResponseError } from '@backstage/errors';
/**
* Options you can pass into a catalog request for additional information.
*
* @public
*/
export interface UnprocessedEntitiesRequestOptions {
token?: string;
}
/**
* Interface for the CatalogUnprocessedEntitiesApi.
*
* @public
*/
export interface CatalogUnprocessedEntitiesApi {
/**
* Returns a list of entities with state 'pending'
*
* @param options - Additional options
*/
pending(
options?: UnprocessedEntitiesRequestOptions,
): Promise<CatalogUnprocessedEntitiesApiResponse>;
/**
* Returns a list of entities with state 'failed'
*
* @param options - Additional options
*/
failed(
options?: UnprocessedEntitiesRequestOptions,
): Promise<CatalogUnprocessedEntitiesApiResponse>;
/**
* Deletes an entity from the refresh_state table
*
* @param entityId - The ID of the entity to delete
* @param options - Additional options
*/
delete(
entityId: string,
options?: UnprocessedEntitiesRequestOptions,
): Promise<void>;
}
/**
* Default API implementation for the Catalog Unprocessed Entities plugin
*
* @public
*/
export class CatalogUnprocessedEntitiesClient
implements CatalogUnprocessedEntitiesApi
{
private readonly discovery: { getBaseUrl(pluginId: string): Promise<string> };
private readonly fetchApi: { fetch: typeof fetch };
constructor(
discovery: { getBaseUrl(pluginId: string): Promise<string> },
fetchApi?: { fetch: typeof fetch },
) {
this.discovery = discovery;
this.fetchApi = fetchApi ?? { fetch };
}
private async fetch<T>(
method: string,
path: string,
options?: UnprocessedEntitiesRequestOptions,
): Promise<T> {
const url = await this.discovery.getBaseUrl('catalog');
const resp = await this.fetchApi.fetch(`${url}/${path}`, {
method,
headers: {
...(options?.token ? { Authorization: `Bearer ${options.token}` } : {}),
},
});
if (!resp.ok) {
throw await ResponseError.fromResponse(resp);
}
return resp.status === 204 ? (resp as T) : await resp.json();
}
async pending(
options?: UnprocessedEntitiesRequestOptions,
): Promise<CatalogUnprocessedEntitiesApiResponse> {
return await this.fetch('GET', 'entities/unprocessed/pending', options);
}
async failed(
options?: UnprocessedEntitiesRequestOptions,
): Promise<CatalogUnprocessedEntitiesApiResponse> {
return await this.fetch('GET', 'entities/unprocessed/failed', options);
}
async delete(
entityId: string,
options?: UnprocessedEntitiesRequestOptions,
): Promise<void> {
await this.fetch(
'DELETE',
`entities/unprocessed/delete/${entityId}`,
options,
);
}
}
@@ -0,0 +1,16 @@
/*
* Copyright 2025 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './api';
@@ -20,4 +20,6 @@
* @packageDocumentation
*/
export * from './api';
export * from './permissions';
export * from './types';
@@ -0,0 +1,66 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Entity } from '@backstage/catalog-model';
/**
* Unprocessed entity data stored in the database.
* @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; // remove?
errors?: UnprocessedEntityError[];
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;
cause: {
name: string;
message: string;
stack: string;
};
};
/**
* Response expected by the {@link CatalogUnprocessedEntitiesApi}
*
* @public
*/
export type CatalogUnprocessedEntitiesApiResponse = {
entities: UnprocessedEntity[];
};
@@ -50,11 +50,11 @@
"test": "backstage-cli package test"
},
"dependencies": {
"@backstage/catalog-model": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/frontend-plugin-api": "workspace:^",
"@backstage/plugin-catalog-unprocessed-entities-common": "workspace:^",
"@material-ui/core": "^4.9.13",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.60",
@@ -5,24 +5,24 @@
```ts
import { ApiRef } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { Entity } from '@backstage/catalog-model';
import { CatalogUnprocessedEntitiesApi as CatalogUnprocessedEntitiesApi_2 } from '@backstage/plugin-catalog-unprocessed-entities-common';
import { CatalogUnprocessedEntitiesApiResponse as CatalogUnprocessedEntitiesApiResponse_2 } from '@backstage/plugin-catalog-unprocessed-entities-common';
import { JSX as JSX_2 } from 'react/jsx-runtime';
import { RouteRef } from '@backstage/core-plugin-api';
import type { UnprocessedEntity as UnprocessedEntity_2 } from '@backstage/plugin-catalog-unprocessed-entities-common';
import type { UnprocessedEntityCache as UnprocessedEntityCache_2 } from '@backstage/plugin-catalog-unprocessed-entities-common';
import type { UnprocessedEntityError as UnprocessedEntityError_2 } from '@backstage/plugin-catalog-unprocessed-entities-common';
// @public
export interface CatalogUnprocessedEntitiesApi {
delete(entityId: string): Promise<void>;
failed(): Promise<CatalogUnprocessedEntitiesApiResponse>;
pending(): Promise<CatalogUnprocessedEntitiesApiResponse>;
}
// @public @deprecated
export interface CatalogUnprocessedEntitiesApi
extends CatalogUnprocessedEntitiesApi_2 {}
// @public
export const catalogUnprocessedEntitiesApiRef: ApiRef<CatalogUnprocessedEntitiesApi>;
// @public
export type CatalogUnprocessedEntitiesApiResponse = {
entities: UnprocessedEntity[];
};
// @public @deprecated
export type CatalogUnprocessedEntitiesApiResponse =
CatalogUnprocessedEntitiesApiResponse_2;
// @public
export const CatalogUnprocessedEntitiesPage: () => JSX_2.Element;
@@ -38,37 +38,14 @@ export const catalogUnprocessedEntitiesPlugin: BackstagePlugin<
// @public (undocumented)
export const UnprocessedEntitiesContent: () => JSX_2.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 @deprecated
export type UnprocessedEntity = UnprocessedEntity_2;
// @public
export type UnprocessedEntityCache = {
ttl: number;
cache: object;
};
// @public @deprecated
export type UnprocessedEntityCache = UnprocessedEntityCache_2;
// @public
export type UnprocessedEntityError = {
name: string;
message: string;
cause: {
name: string;
message: string;
stack: string;
};
};
// @public @deprecated
export type UnprocessedEntityError = UnprocessedEntityError_2;
// (No @packageDocumentation comment for this package)
```
@@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createApiRef } from '@backstage/core-plugin-api';
import {
DiscoveryApi,
createApiRef,
FetchApi,
} from '@backstage/core-plugin-api';
import { ResponseError } from '@backstage/errors';
import { UnprocessedEntity } from '../types';
CatalogUnprocessedEntitiesApiResponse as CommonCatalogUnprocessedEntitiesApiResponse,
CatalogUnprocessedEntitiesApi as CommonCatalogUnprocessedEntitiesApi,
CatalogUnprocessedEntitiesClient as CommonCatalogUnprocessedEntitiesClient,
} from '@backstage/plugin-catalog-unprocessed-entities-common';
/**
* {@link @backstage/core-plugin-api#ApiRef} for the {@link CatalogUnprocessedEntitiesApi}
@@ -35,69 +34,24 @@ export const catalogUnprocessedEntitiesApiRef =
* Response expected by the {@link CatalogUnprocessedEntitiesApi}
*
* @public
* @deprecated Use the type imported from `@backstage/plugin-catalog-unprocessed-entities-common` instead.
*/
export type CatalogUnprocessedEntitiesApiResponse = {
entities: UnprocessedEntity[];
};
export type CatalogUnprocessedEntitiesApiResponse =
CommonCatalogUnprocessedEntitiesApiResponse;
/**
* Interface for the CatalogUnprocessedEntitiesApi.
*
* @public
* @deprecated Use the type imported from `@backstage/plugin-catalog-unprocessed-entities-common` instead.
*/
export interface CatalogUnprocessedEntitiesApi {
/**
* Returns a list of entities with state 'pending'
*/
pending(): Promise<CatalogUnprocessedEntitiesApiResponse>;
/**
* Returns a list of entities with state 'failed'
*/
failed(): Promise<CatalogUnprocessedEntitiesApiResponse>;
/**
* Deletes an entity from the refresh_state table
*/
delete(entityId: string): Promise<void>;
}
export interface CatalogUnprocessedEntitiesApi
extends CommonCatalogUnprocessedEntitiesApi {}
/**
* Default API implementation for the Catalog Unprocessed Entities plugin
*
* @public
* @deprecated Use the client imported from `@backstage/plugin-catalog-unprocessed-entities-common` instead.
*/
export class CatalogUnprocessedEntitiesClient
implements CatalogUnprocessedEntitiesApi
{
public discovery: DiscoveryApi;
public fetchApi: FetchApi;
constructor(discovery: DiscoveryApi, fetchApi: FetchApi) {
this.discovery = discovery;
this.fetchApi = fetchApi;
}
private async fetch<T>(path: string, init?: RequestInit): Promise<T> {
const url = await this.discovery.getBaseUrl('catalog');
const resp = await this.fetchApi.fetch(`${url}/${path}`, init);
if (!resp.ok) {
throw await ResponseError.fromResponse(resp);
}
return resp.status === 204 ? (resp as T) : await resp.json();
}
async pending(): Promise<CatalogUnprocessedEntitiesApiResponse> {
return await this.fetch('entities/unprocessed/pending');
}
async failed(): Promise<CatalogUnprocessedEntitiesApiResponse> {
return await this.fetch('entities/unprocessed/failed');
}
async delete(entityId: string): Promise<void> {
await this.fetch(`entities/unprocessed/delete/${entityId}`, {
method: 'DELETE',
});
}
}
export class CatalogUnprocessedEntitiesClient extends CommonCatalogUnprocessedEntitiesClient {}
@@ -13,45 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Entity } from '@backstage/catalog-model';
import type {
UnprocessedEntity as CommonUnprocessedEntity,
UnprocessedEntityCache as CommonUnprocessedEntityCache,
UnprocessedEntityError as CommonUnprocessedEntityError,
} from '@backstage/plugin-catalog-unprocessed-entities-common';
/**
* Unprocessed entity data stored in the database.
* @public
* @deprecated Use the type imported from `@backstage/plugin-catalog-unprocessed-entities-common` instead.
*/
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; // remove?
errors?: UnprocessedEntityError[];
location_key?: string;
};
export type UnprocessedEntity = CommonUnprocessedEntity;
/**
* Unprocessed entity cache stored in the database.
* @public
* @deprecated Use the type imported from `@backstage/plugin-catalog-unprocessed-entities-common` instead.
*/
export type UnprocessedEntityCache = {
ttl: number;
cache: object;
};
export type UnprocessedEntityCache = CommonUnprocessedEntityCache;
/**
* Unprocessed entity error information stored in the database.
* @public
* @deprecated Use the type imported from `@backstage/plugin-catalog-unprocessed-entities-common` instead.
*/
export type UnprocessedEntityError = {
name: string;
message: string;
cause: {
name: string;
message: string;
stack: string;
};
};
export type UnprocessedEntityError = CommonUnprocessedEntityError;
+3 -1
View File
@@ -5289,7 +5289,9 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-catalog-unprocessed-entities-common@workspace:plugins/catalog-unprocessed-entities-common"
dependencies:
"@backstage/catalog-model": "workspace:^"
"@backstage/cli": "workspace:^"
"@backstage/errors": "workspace:^"
"@backstage/plugin-permission-common": "workspace:^"
languageName: unknown
linkType: soft
@@ -5298,13 +5300,13 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-catalog-unprocessed-entities@workspace:plugins/catalog-unprocessed-entities"
dependencies:
"@backstage/catalog-model": "workspace:^"
"@backstage/cli": "workspace:^"
"@backstage/core-components": "workspace:^"
"@backstage/core-plugin-api": "workspace:^"
"@backstage/dev-utils": "workspace:^"
"@backstage/errors": "workspace:^"
"@backstage/frontend-plugin-api": "workspace:^"
"@backstage/plugin-catalog-unprocessed-entities-common": "workspace:^"
"@material-ui/core": "npm:^4.9.13"
"@material-ui/icons": "npm:^4.9.1"
"@material-ui/lab": "npm:^4.0.0-alpha.60"