Merge pull request #16880 from brianphillips/new-entity-switch-condition
Add isEntityWith helper method to EntitySwitch conditions
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': minor
|
||||
---
|
||||
|
||||
Added `isEntityWith` condition helper for `EntitySwitch` case statements.
|
||||
@@ -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
|
||||
|
||||
@@ -355,6 +355,14 @@ export const EntityListContainer: (props: {
|
||||
// @public
|
||||
export function EntityOrphanWarning(): JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface EntityPredicates {
|
||||
// (undocumented)
|
||||
kind?: string | string[];
|
||||
// (undocumented)
|
||||
type?: string | string[];
|
||||
}
|
||||
|
||||
// @public
|
||||
export function EntityProcessingErrorsPanel(): JSX.Element | null;
|
||||
|
||||
@@ -433,6 +441,11 @@ export function isComponentType(
|
||||
types: string | string[],
|
||||
): (entity: Entity) => boolean;
|
||||
|
||||
// @public
|
||||
export function isEntityWith(
|
||||
predicate: EntityPredicates,
|
||||
): (entity: Entity) => boolean;
|
||||
|
||||
// @public
|
||||
export function isKind(kinds: string | string[]): (entity: Entity) => boolean;
|
||||
|
||||
|
||||
@@ -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,25 @@ 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();
|
||||
});
|
||||
it('allows a check against no criteria', () => {
|
||||
const checkEntity = isEntityWith({});
|
||||
expect(checkEntity(apiKind)).toBeTruthy();
|
||||
});
|
||||
it('allows a check against empty criteria', () => {
|
||||
const checkEntity = isEntityWith({ kind: [], type: [] });
|
||||
expect(checkEntity(apiKind)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isKind', () => {
|
||||
it('should check for the intended kind', () => {
|
||||
const checkEntity = isKind('component');
|
||||
|
||||
@@ -14,22 +14,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ComponentEntity,
|
||||
ResourceEntity,
|
||||
Entity,
|
||||
} from '@backstage/catalog-model';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
function strCmp(a: string | undefined, b: string | undefined): boolean {
|
||||
/** @public */
|
||||
export interface EntityPredicates {
|
||||
kind?: string | string[];
|
||||
type?: string | string[];
|
||||
}
|
||||
|
||||
function strCmp(a: unknown, b: string | undefined): boolean {
|
||||
return Boolean(
|
||||
a && a?.toLocaleLowerCase('en-US') === b?.toLocaleLowerCase('en-US'),
|
||||
a &&
|
||||
typeof a === 'string' &&
|
||||
a?.toLocaleLowerCase('en-US') === b?.toLocaleLowerCase('en-US'),
|
||||
);
|
||||
}
|
||||
|
||||
function strCmpAll(value: string | undefined, cmpValues: string | string[]) {
|
||||
function strCmpAll(value: unknown, cmpValues: string | string[]) {
|
||||
return typeof cmpValues === 'string'
|
||||
? strCmp(value, cmpValues)
|
||||
: cmpValues.some(cmpVal => strCmp(value, cmpVal));
|
||||
: cmpValues.length === 0 || cmpValues.some(cmpVal => strCmp(value, cmpVal));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,7 +41,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 +49,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,12 +57,25 @@ 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 (predicate.kind && !strCmpAll(entity.kind, predicate.kind)) {
|
||||
return false;
|
||||
}
|
||||
const resourceEntity = entity as ResourceEntity;
|
||||
return strCmpAll(resourceEntity.spec.type, types);
|
||||
|
||||
if (predicate.type && !strCmpAll(entity.spec?.type, predicate.type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// there's no type check, return true
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
export { EntitySwitch } from './EntitySwitch';
|
||||
export type { EntitySwitchProps, EntitySwitchCaseProps } from './EntitySwitch';
|
||||
export type { EntityPredicates } from './conditions';
|
||||
export {
|
||||
isKind,
|
||||
isNamespace,
|
||||
isComponentType,
|
||||
isResourceType,
|
||||
isEntityWith,
|
||||
} from './conditions';
|
||||
|
||||
Reference in New Issue
Block a user