Merge pull request #5493 from monzo/multiple-filter-params

catalog-client: allow `filter` param to be specified multiple times
This commit is contained in:
Fredrik Adelöw
2021-04-29 18:01:38 +02:00
committed by GitHub
5 changed files with 59 additions and 11 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/catalog-client': patch
---
Allow `filter` parameter to be specified multiple times
+1 -1
View File
@@ -67,7 +67,7 @@ export class CatalogClient implements CatalogApi {
// @public (undocumented)
export type CatalogEntitiesRequest = {
filter?: Record<string, string | string[]> | undefined;
filter?: Record<string, string | string[]>[] | Record<string, string | string[]> | undefined;
fields?: string[] | undefined;
};
@@ -76,7 +76,38 @@ describe('CatalogClient', () => {
expect(response).toEqual(defaultResponse);
});
it('builds entity search filters properly', async () => {
it('builds multiple entity search filters properly', async () => {
expect.assertions(2);
server.use(
rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => {
expect(req.url.search).toBe(
'?filter=a=1,b=2,b=3,%C3%B6=%3D&filter=a=2',
);
return res(ctx.json([]));
}),
);
const response = await client.getEntities(
{
filter: [
{
a: '1',
b: ['2', '3'],
ö: '=',
},
{
a: '2',
},
],
},
{ token },
);
expect(response.items).toEqual([]);
});
it('builds single entity search filter properly', async () => {
expect.assertions(2);
server.use(
+17 -8
View File
@@ -56,18 +56,27 @@ export class CatalogClient implements CatalogApi {
request?: CatalogEntitiesRequest,
options?: CatalogRequestOptions,
): Promise<CatalogListResponse<Entity>> {
const { filter = {}, fields = [] } = request ?? {};
const { filter = [], fields = [] } = request ?? {};
const filterItems = [filter].flat();
const params: string[] = [];
const filterParts: string[] = [];
for (const [key, value] of Object.entries(filter)) {
for (const v of [value].flat()) {
filterParts.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`);
// filter param can occur multiple times, for example
// /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component'
// the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters
// the "inner array" defined within a `filter` param corresponds to "allOf" filters
for (const filterItem of filterItems) {
const filterParts: string[] = [];
for (const [key, value] of Object.entries(filterItem)) {
for (const v of [value].flat()) {
filterParts.push(
`${encodeURIComponent(key)}=${encodeURIComponent(v)}`,
);
}
}
}
if (filterParts.length) {
params.push(`filter=${filterParts.join(',')}`);
if (filterParts.length) {
params.push(`filter=${filterParts.join(',')}`);
}
}
if (fields.length) {
+4 -1
View File
@@ -17,7 +17,10 @@
import { Entity, EntityName, Location } from '@backstage/catalog-model';
export type CatalogEntitiesRequest = {
filter?: Record<string, string | string[]> | undefined;
filter?:
| Record<string, string | string[]>[]
| Record<string, string | string[]>
| undefined;
fields?: string[] | undefined;
};