Merge pull request #33789 from backstage/freben/location-uuid-names

feat(catalog): expose `entityRef` on Location type and add `PUT /locations/:id`
This commit is contained in:
Fredrik Adelöw
2026-04-13 11:38:16 +02:00
committed by GitHub
35 changed files with 830 additions and 49 deletions
@@ -84,6 +84,14 @@ export class InMemoryCatalogClient implements CatalogApi {
_request?: QueryLocationsInitialRequest,
): AsyncIterable<Location_2[]>;
// (undocumented)
updateLocation(
_id: string,
_location: {
type?: string;
target: string;
},
): Promise<Location_2>;
// (undocumented)
validateEntity(
_entity: Entity,
_locationRef: string,
+17
View File
@@ -102,6 +102,14 @@ export interface CatalogApi {
request?: QueryLocationsInitialRequest,
options?: CatalogRequestOptions,
): AsyncIterable<Location_2[]>;
updateLocation(
id: string,
location: {
type?: string;
target: string;
},
options?: CatalogRequestOptions,
): Promise<Location_2>;
validateEntity(
entity: Entity,
locationRef: string,
@@ -196,6 +204,14 @@ export class CatalogClient implements CatalogApi {
request?: QueryLocationsInitialRequest,
options?: CatalogRequestOptions,
): AsyncIterable<Location_2[]>;
updateLocation(
id: string,
location: {
type?: string;
target: string;
},
options?: CatalogRequestOptions,
): Promise<Location_2>;
validateEntity(
entity: Entity,
locationRef: string,
@@ -307,6 +323,7 @@ type Location_2 = {
id: string;
type: string;
target: string;
entityRef: string;
};
export { Location_2 as Location };
@@ -1107,6 +1107,7 @@ describe('CatalogClient', () => {
id: '42',
type: 'url',
target: 'https://example.com',
entityRef: 'location:default/generated-42',
},
},
{
@@ -1114,6 +1115,7 @@ describe('CatalogClient', () => {
id: '43',
type: 'url',
target: 'https://example.com',
entityRef: 'location:default/generated-43',
},
},
] satisfies GetLocations200ResponseInner[];
@@ -1134,11 +1136,13 @@ describe('CatalogClient', () => {
id: '42',
type: 'url',
target: 'https://example.com',
entityRef: 'location:default/generated-42',
},
{
id: '43',
type: 'url',
target: 'https://example.com',
entityRef: 'location:default/generated-43',
},
],
});
@@ -612,6 +612,27 @@ export class CatalogClient implements CatalogApi {
.find(l => locationRef === stringifyLocationRef(l));
}
/**
* {@inheritdoc CatalogApi.updateLocation}
*/
async updateLocation(
id: string,
location: { type?: string; target: string },
options?: CatalogRequestOptions,
): Promise<Location> {
const { type = 'url', target } = location;
const response = await this.apiClient.updateLocation(
{ path: { id }, body: { type, target } },
options,
);
if (response.status !== 200) {
throw await ResponseError.fromResponse(response);
}
return response.json();
}
/**
* {@inheritdoc CatalogApi.removeLocationById}
*/
@@ -40,6 +40,7 @@ import { CreateLocationRequest } from '../models/CreateLocationRequest.model';
import { GetLocations200ResponseInner } from '../models/GetLocations200ResponseInner.model';
import { GetLocationsByQueryRequest } from '../models/GetLocationsByQueryRequest.model';
import { Location } from '../models/Location.model';
import { LocationInput } from '../models/LocationInput.model';
import { LocationsQueryResponse } from '../models/LocationsQueryResponse.model';
/**
@@ -217,6 +218,15 @@ export type GetLocations = {};
export type GetLocationsByQuery = {
body: GetLocationsByQueryRequest;
};
/**
* @public
*/
export type UpdateLocation = {
path: {
id: string;
};
body: LocationInput;
};
/**
* @public
@@ -747,4 +757,32 @@ export class DefaultApiClient {
body: JSON.stringify(request.body),
});
}
/**
* Update the type and target of an existing location by id.
* @param id -
* @param locationInput -
*/
public async updateLocation(
// @ts-ignore
request: UpdateLocation,
options?: RequestOptions,
): Promise<TypedResponse<Location>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/locations/{id}`;
const uri = parser.parse(uriTemplate).expand({
id: request.path.id,
});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'PUT',
body: JSON.stringify(request.body),
});
}
}
@@ -26,4 +26,8 @@ export interface Location {
target: string;
type: string;
id: string;
/**
* The entity ref of the corresponding Location kind entity, e.g. location:default/generated-<sha1hex>.
*/
entityRef: string;
}
@@ -584,6 +584,13 @@ export class InMemoryCatalogClient implements CatalogApi {
throw new NotImplementedError('Method not implemented.');
}
async updateLocation(
_id: string,
_location: { type?: string; target: string },
): Promise<Location> {
throw new NotImplementedError('Method not implemented.');
}
async getLocationByEntity(
_entityRef: string | CompoundEntityRef,
): Promise<Location | undefined> {
+15
View File
@@ -372,6 +372,8 @@ export type Location = {
id: string;
type: string;
target: string;
/** The entity ref of the corresponding Location kind entity, e.g. `location:default/generated-<sha1hex>`. */
entityRef: string;
};
/**
@@ -829,6 +831,19 @@ export interface CatalogApi {
options?: CatalogRequestOptions,
): Promise<void>;
/**
* Updates the type and target of an existing registered location.
*
* @param id - The location ID to update
* @param location - The new type and target for the location
* @param options - Additional options
*/
updateLocation(
id: string,
location: { type?: string; target: string },
options?: CatalogRequestOptions,
): Promise<Location>;
/**
* Gets a location associated with an entity.
*