Add isEntityWith helper method to EntitySwitch conditions

This will make it easier to conditionally show content for a given
entity based on the `spec.type` field beyond just component entities
(e.g. api, group and resource, all have a spec.type field)

Signed-off-by: Brian Phillips <28457+brianphillips@users.noreply.github.com>
This commit is contained in:
Brian Phillips
2023-03-14 15:09:52 -05:00
parent 8f72566485
commit fc6cab4eb4
4 changed files with 54 additions and 17 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': minor
---
Added isEntityWith condition helper
+1 -1
View File
@@ -480,7 +480,7 @@ function isKind(kind: string) {
```
The `@backstage/catalog` plugin provides a couple of built-in conditions,
`isKind`, `isComponentType`, and `isNamespace`.
`isKind`, `isComponentType`, `isResourceType`, `isEntityWith`, and `isNamespace`.
In addition to the `EntitySwitch` component, the catalog plugin also exports a
new `EntityLayout` component. It is a tweaked version and replacement for the
@@ -20,6 +20,7 @@ import {
isKind,
isNamespace,
isResourceType,
isEntityWith,
} from './conditions';
const kubernetesClusterResource: Entity = {
@@ -64,6 +65,13 @@ const notComponent: Entity = {
spec: { type: 'service' },
};
const missingSpecType: Entity = {
apiVersion: '',
kind: 'another-type',
metadata: { name: 'anEntity' },
spec: {},
};
const apiKind: Entity = {
apiVersion: '',
kind: 'api',
@@ -125,6 +133,17 @@ describe('isComponentType', () => {
});
});
describe('isEntityWith', () => {
it('allows for a kind-only check (empty type array)', () => {
const checkEntity = isEntityWith({kind: 'api', type: []});
expect(checkEntity(apiKind)).toBeTruthy();
});
it('handles missing spec.type field', () => {
const checkEntity = isEntityWith({kind: 'another-type', type: 'service'});
expect(checkEntity(missingSpecType)).not.toBeTruthy();
});
});
describe('isKind', () => {
it('should check for the intended kind', () => {
const checkEntity = isKind('component');
@@ -14,11 +14,12 @@
* limitations under the License.
*/
import {
ComponentEntity,
ResourceEntity,
Entity,
} from '@backstage/catalog-model';
import { Entity } from '@backstage/catalog-model';
export interface EntityPredicates {
kind: string | string[];
type?: string | string[];
}
function strCmp(a: string | undefined, b: string | undefined): boolean {
return Boolean(
@@ -37,7 +38,7 @@ function strCmpAll(value: string | undefined, cmpValues: string | string[]) {
* @public
*/
export function isKind(kinds: string | string[]) {
return (entity: Entity) => strCmpAll(entity.kind, kinds);
return isEntityWith({kind: kinds});
}
/**
@@ -45,13 +46,7 @@ export function isKind(kinds: string | string[]) {
* @public
*/
export function isComponentType(types: string | string[]) {
return (entity: Entity) => {
if (!strCmp(entity.kind, 'component')) {
return false;
}
const componentEntity = entity as ComponentEntity;
return strCmpAll(componentEntity.spec.type, types);
};
return isEntityWith({ kind: 'component', type: types });
}
/**
@@ -59,15 +54,33 @@ export function isComponentType(types: string | string[]) {
* @public
*/
export function isResourceType(types: string | string[]) {
return isEntityWith({ kind: 'resource', type: types });
}
/**
*
* For use in EntitySwitch.Case. Matches if the entity is the specified kind and type (if present).
* @public
*/
export function isEntityWith(predicate: EntityPredicates) {
return (entity: Entity) => {
if (!strCmp(entity.kind, 'resource')) {
if (!strCmpAll(entity.kind, predicate.kind)) {
return false;
}
const resourceEntity = entity as ResourceEntity;
return strCmpAll(resourceEntity.spec.type, types);
if (!predicate.type || (Array.isArray(predicate.type) && predicate.type.length === 0)) {
// there's no type check, return true
return true;
} else if (typeof entity.spec?.type !== 'string') {
// we'll reject any entity's with some non-string (including undefined/null) spec.type value
return false;
}
return strCmpAll(entity.spec.type, predicate.type);
};
}
/**
* For use in EntitySwitch.Case. Matches if the entity is in a given namespace.
* @public