From 1dbaaf7801070c208bcad17ef531c85dbad753f2 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Wed, 13 Oct 2021 12:14:10 +0200 Subject: [PATCH] Simplify the StarredEntitiesApi interface Signed-off-by: Dominik Henneke --- plugins/catalog-react/api-report.md | 16 +++------ .../DefaultStarredEntitiesApi.test.ts | 15 ++------ .../DefaultStarredEntitiesApi.ts | 34 +++++++------------ .../StarredEntitiesApi/StarredEntitiesApi.ts | 23 ++----------- .../src/apis/StarredEntitiesApi/index.ts | 5 +-- .../src/hooks/useStarredEntities.ts | 34 +++++++++++++------ 6 files changed, 46 insertions(+), 81 deletions(-) diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 1a37f84df3..2486cdd6e8 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -139,7 +139,7 @@ export class DefaultStarredEntitiesApi implements StarredEntitiesApi { // (undocumented) isStarred(entityRef: string): boolean; // (undocumented) - starredEntitie$(): Observable; + starredEntitie$(): Observable>; // (undocumented) toggleStarred(entityRef: string): Promise; } @@ -757,16 +757,10 @@ export const rootRoute: RouteRef; // @public export interface StarredEntitiesApi { - starredEntitie$(): Observable; + starredEntitie$(): Observable>; toggleStarred(entityRef: string): Promise; } -// @public (undocumented) -export type StarredEntitiesApiObservable = { - starredEntities: Set; - isStarred: (entityRef: string) => boolean; -}; - // @public export const starredEntitiesApiRef: ApiRef; @@ -894,10 +888,10 @@ export const UserListPicker: ({ // Warning: (ae-missing-release-tag) "useStarredEntities" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const useStarredEntities: () => { +export function useStarredEntities(): { starredEntities: Set; - toggleStarredEntity: (entity: Entity) => void; - isStarredEntity: (entity: Entity) => boolean; + toggleStarredEntity: (entityOrRef: Entity | EntityName | string) => void; + isStarredEntity: (entityOrRef: Entity | EntityName | string) => boolean; }; // Warnings were encountered during analysis: diff --git a/plugins/catalog-react/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.test.ts b/plugins/catalog-react/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.test.ts index e4f7c4ffa1..be67b03dbb 100644 --- a/plugins/catalog-react/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.test.ts +++ b/plugins/catalog-react/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.test.ts @@ -85,19 +85,8 @@ describe('DefaultStarredEntitiesApi', () => { it('should receive updates', async () => { expect(handler).toBeCalledTimes(2); - expect(handler).toBeCalledWith({ - starredEntities: new Set(), - isStarred: expect.any(Function), - }); - expect(handler).toBeCalledWith({ - starredEntities: new Set(['component:default/mock']), - isStarred: expect.any(Function), - }); - }); - - it('should receive isStarred function that operates on the latest state', async () => { - expect(handler.mock.calls[0][0].isStarred(mockEntityRef)).toBe(true); - expect(handler.mock.calls[1][0].isStarred(mockEntityRef)).toBe(true); + expect(handler).toBeCalledWith(new Set()); + expect(handler).toBeCalledWith(new Set(['component:default/mock'])); }); }); }); diff --git a/plugins/catalog-react/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.ts b/plugins/catalog-react/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.ts index 8486d180b7..92a0eaebf2 100644 --- a/plugins/catalog-react/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.ts +++ b/plugins/catalog-react/src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.ts @@ -16,10 +16,7 @@ import { Observable, StorageApi } from '@backstage/core-plugin-api'; import ObservableImpl from 'zen-observable'; -import { - StarredEntitiesApi, - StarredEntitiesApiObservable, -} from './StarredEntitiesApi'; +import { StarredEntitiesApi } from './StarredEntitiesApi'; /** * Default implementation of the StarredEntitiesApi that is backed by the StorageApi. @@ -58,7 +55,7 @@ export class DefaultStarredEntitiesApi implements StarredEntitiesApi { ); } - starredEntitie$(): Observable { + starredEntitie$(): Observable> { return this.observable; } @@ -67,29 +64,22 @@ export class DefaultStarredEntitiesApi implements StarredEntitiesApi { } private readonly subscribers = new Set< - ZenObservable.SubscriptionObserver + ZenObservable.SubscriptionObserver> >(); - private readonly observable = - new ObservableImpl(subscriber => { - // forward the the latest value - subscriber.next({ - starredEntities: this.starredEntities, - isStarred: e => this.isStarred(e), - }); + private readonly observable = new ObservableImpl>(subscriber => { + // forward the the latest value + subscriber.next(this.starredEntities); - this.subscribers.add(subscriber); - return () => { - this.subscribers.delete(subscriber); - }; - }); + this.subscribers.add(subscriber); + return () => { + this.subscribers.delete(subscriber); + }; + }); private notifyChanges() { for (const subscription of this.subscribers) { - subscription.next({ - starredEntities: this.starredEntities, - isStarred: e => this.isStarred(e), - }); + subscription.next(this.starredEntities); } } } diff --git a/plugins/catalog-react/src/apis/StarredEntitiesApi/StarredEntitiesApi.ts b/plugins/catalog-react/src/apis/StarredEntitiesApi/StarredEntitiesApi.ts index 93ff55aa54..4c4c68d66a 100644 --- a/plugins/catalog-react/src/apis/StarredEntitiesApi/StarredEntitiesApi.ts +++ b/plugins/catalog-react/src/apis/StarredEntitiesApi/StarredEntitiesApi.ts @@ -25,24 +25,6 @@ export const starredEntitiesApiRef: ApiRef = createApiRef({ id: 'catalog-react.starred-entities', }); -/** - * @public - */ -export type StarredEntitiesApiObservable = { - /** - * A set of entity references that are starred - */ - starredEntities: Set; - - /** - * A function to check if an entity is starred. - * - * @param entityRef - an entity reference to check - * @returns true, if the entity is starred. - */ - isStarred: (entityRef: string) => boolean; -}; - /** * An API to store and retrieve starred entities * @@ -57,8 +39,7 @@ export interface StarredEntitiesApi { toggleStarred(entityRef: string): Promise; /** - * Observe the state of starred entities and receive a handler - * to check the star state of an entity. + * Observe the set of starred entity references. */ - starredEntitie$(): Observable; + starredEntitie$(): Observable>; } diff --git a/plugins/catalog-react/src/apis/StarredEntitiesApi/index.ts b/plugins/catalog-react/src/apis/StarredEntitiesApi/index.ts index c71a795b9e..e9f9c8923a 100644 --- a/plugins/catalog-react/src/apis/StarredEntitiesApi/index.ts +++ b/plugins/catalog-react/src/apis/StarredEntitiesApi/index.ts @@ -16,7 +16,4 @@ export { DefaultStarredEntitiesApi } from './DefaultStarredEntitiesApi'; export { starredEntitiesApiRef } from './StarredEntitiesApi'; -export type { - StarredEntitiesApi, - StarredEntitiesApiObservable, -} from './StarredEntitiesApi'; +export type { StarredEntitiesApi } from './StarredEntitiesApi'; diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.ts b/plugins/catalog-react/src/hooks/useStarredEntities.ts index e79e605877..8f6b09614f 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.ts +++ b/plugins/catalog-react/src/hooks/useStarredEntities.ts @@ -14,29 +14,43 @@ * limitations under the License. */ -import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { + Entity, + EntityName, + stringifyEntityRef, +} from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; import { useCallback } from 'react'; import { useObservable } from 'react-use'; import { starredEntitiesApiRef } from '../apis'; -export const useStarredEntities = () => { +function getEntityRef(entityOrRef: Entity | EntityName | string): string { + return typeof entityOrRef === 'string' + ? entityOrRef + : stringifyEntityRef(entityOrRef); +} + +export function useStarredEntities(): { + starredEntities: Set; + toggleStarredEntity: (entityOrRef: Entity | EntityName | string) => void; + isStarredEntity: (entityOrRef: Entity | EntityName | string) => boolean; +} { const starredEntitiesApi = useApi(starredEntitiesApiRef); - const { starredEntities, isStarred } = useObservable( + const starredEntities = useObservable( starredEntitiesApi.starredEntitie$(), - { starredEntities: new Set(), isStarred: _ => false }, + new Set(), ); const isStarredEntity = useCallback( - (entity: Entity) => isStarred(stringifyEntityRef(entity)), - [isStarred], + (entityOrRef: Entity | EntityName | string) => + starredEntities.has(getEntityRef(entityOrRef)), + [starredEntities], ); const toggleStarredEntity = useCallback( - (entity: Entity) => { - starredEntitiesApi.toggleStarred(stringifyEntityRef(entity)).then(); - }, + (entityOrRef: Entity | EntityName | string) => + starredEntitiesApi.toggleStarred(getEntityRef(entityOrRef)).then(), [starredEntitiesApi], ); @@ -45,4 +59,4 @@ export const useStarredEntities = () => { toggleStarredEntity, isStarredEntity, }; -}; +}