From b53d3537ddd30362ec9dc8ff298eedbb9aea14b0 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho Date: Wed, 30 Aug 2023 17:23:31 +0200 Subject: [PATCH] feature(home-plugin): Use static methods on Api classes Confirming with the style guide: 7.Keep constructors private, prefer static factory methods for creating instances. Signed-off-by: Renan Mendes Carvalho --- plugins/home/api-report.md | 59 ++++++++++--------- .../home/src/api/CoreStorageVisitsApi.test.ts | 8 +-- plugins/home/src/api/CoreStorageVisitsApi.ts | 21 ++++--- .../src/api/LocalStorageVisitsApi.test.ts | 8 +-- plugins/home/src/api/LocalStorageVisitsApi.ts | 21 ++++--- plugins/home/src/api/VisitsApiFactory.ts | 18 +++--- 6 files changed, 77 insertions(+), 58 deletions(-) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 9eddb81da5..2dc1aca8e2 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -78,19 +78,18 @@ export const ComponentTabs: (props: { // @public export class CoreStorageVisitsApi extends VisitsApiFactory { - constructor({ - storageApi, - identityApi, - randomUUID, - limit, - }: { - storageApi: StorageApi; - randomUUID?: Window['crypto']['randomUUID']; - limit?: number; - identityApi: IdentityApi; - }); + // (undocumented) + static create(options: CoreStorageVisitsApiOptions): CoreStorageVisitsApi; } +// @public (undocumented) +export type CoreStorageVisitsApiOptions = { + storageApi: StorageApi; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + identityApi: IdentityApi; +}; + // @public @deprecated (undocumented) export const createCardExtension: typeof createCardExtension_2; @@ -180,19 +179,18 @@ export type LayoutConfiguration = { // @public export class LocalStorageVisitsApi extends VisitsApiFactory { - constructor({ - localStorage, - randomUUID, - limit, - identityApi, - }: { - localStorage?: Window['localStorage']; - randomUUID?: Window['crypto']['randomUUID']; - limit?: number; - identityApi: IdentityApi; - }); + // (undocumented) + static create(options: LocalStorageVisitsApiOptions): LocalStorageVisitsApi; } +// @public (undocumented) +export type LocalStorageVisitsApiOptions = { + localStorage?: Window['localStorage']; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + identityApi: IdentityApi; +}; + // @public @deprecated (undocumented) export type RendererProps = RendererProps_2; @@ -270,17 +268,12 @@ export interface VisitsApi { // @public export class VisitsApiFactory implements VisitsApi { - constructor({ + protected constructor({ randomUUID, limit, retrieveAll, persistAll, - }: { - randomUUID: Window['crypto']['randomUUID']; - limit: number; - retrieveAll?: () => Promise>; - persistAll?: (visits: Array) => Promise; - }); + }: VisitsApiFactoryOptions); // (undocumented) protected readonly limit: number; // (undocumented) @@ -295,6 +288,14 @@ export class VisitsApiFactory implements VisitsApi { saveVisit(saveParams: VisitsApiSaveParams): Promise; } +// @public (undocumented) +export type VisitsApiFactoryOptions = { + randomUUID: Window['crypto']['randomUUID']; + limit: number; + retrieveAll?: () => Promise>; + persistAll?: (visits: Array) => Promise; +}; + // @public export type VisitsApiQueryParams = { limit?: number; diff --git a/plugins/home/src/api/CoreStorageVisitsApi.test.ts b/plugins/home/src/api/CoreStorageVisitsApi.test.ts index e14f71ad60..ab5d66c495 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.test.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.test.ts @@ -18,7 +18,7 @@ import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; import { CoreStorageVisitsApi } from './CoreStorageVisitsApi'; import { MockStorageApi } from '@backstage/test-utils'; -describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () => { +describe('CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create() })', () => { const mockRandomUUID = () => '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( /x/g, @@ -42,7 +42,7 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () }); it('instantiates', () => { - const api = new CoreStorageVisitsApi({ + const api = CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); @@ -50,7 +50,7 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () }); it('saves a visit', async () => { - const api = new CoreStorageVisitsApi({ + const api = CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); @@ -67,7 +67,7 @@ describe('new CoreStorageVisitsApi({ storageApi: MockStorageApi.create() })', () }); it('retrieves visits', async () => { - const api = new CoreStorageVisitsApi({ + const api = CoreStorageVisitsApi.create({ storageApi: MockStorageApi.create(), identityApi: mockIdentityApi, }); diff --git a/plugins/home/src/api/CoreStorageVisitsApi.ts b/plugins/home/src/api/CoreStorageVisitsApi.ts index ae7fac14e1..c4b70eff88 100644 --- a/plugins/home/src/api/CoreStorageVisitsApi.ts +++ b/plugins/home/src/api/CoreStorageVisitsApi.ts @@ -17,6 +17,14 @@ import { IdentityApi, StorageApi } from '@backstage/core-plugin-api'; import { Visit } from './VisitsApi'; import { VisitsApiFactory } from './VisitsApiFactory'; +/** @public */ +export type CoreStorageVisitsApiOptions = { + storageApi: StorageApi; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + identityApi: IdentityApi; +}; + /** * @public * This is an implementation of VisitsApi that relies on a StorageApi @@ -26,17 +34,16 @@ export class CoreStorageVisitsApi extends VisitsApiFactory { private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; private readonly identityApi: IdentityApi; - constructor({ + static create(options: CoreStorageVisitsApiOptions) { + return new CoreStorageVisitsApi(options); + } + + private constructor({ storageApi, identityApi, randomUUID = window?.crypto?.randomUUID, limit = 100, - }: { - storageApi: StorageApi; - randomUUID?: Window['crypto']['randomUUID']; - limit?: number; - identityApi: IdentityApi; - }) { + }: CoreStorageVisitsApiOptions) { super({ randomUUID, limit }); this.storageApi = storageApi; this.identityApi = identityApi; diff --git a/plugins/home/src/api/LocalStorageVisitsApi.test.ts b/plugins/home/src/api/LocalStorageVisitsApi.test.ts index 4e2e3f9c7a..c17fa3cfb8 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.test.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.test.ts @@ -17,7 +17,7 @@ import { BackstageUserIdentity, IdentityApi } from '@backstage/core-plugin-api'; import { LocalStorageVisitsApi } from './LocalStorageVisitsApi'; -describe('new LocalStorageVisitsApi()', () => { +describe('LocalStorageVisitsApi.create()', () => { const mockRandomUUID = () => '068f3129-7440-4e0e-8fd4-xxxxxxxxxxxx'.replace( /x/g, @@ -42,12 +42,12 @@ describe('new LocalStorageVisitsApi()', () => { }); it('instantiates with only identitiyApi', () => { - const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); expect(api).toBeTruthy(); }); it('saves a visit', async () => { - const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); const visit = { pathname: '/catalog/default/component/playback-order', entityRef: 'component:default/playback-order', @@ -61,7 +61,7 @@ describe('new LocalStorageVisitsApi()', () => { }); it('retrieves visits', async () => { - const api = new LocalStorageVisitsApi({ identityApi: mockIdentityApi }); + const api = LocalStorageVisitsApi.create({ identityApi: mockIdentityApi }); const visit = { pathname: '/catalog/default/component/playback-order', entityRef: 'component:default/playback-order', diff --git a/plugins/home/src/api/LocalStorageVisitsApi.ts b/plugins/home/src/api/LocalStorageVisitsApi.ts index 21a8e5cb6f..31cd30dc21 100644 --- a/plugins/home/src/api/LocalStorageVisitsApi.ts +++ b/plugins/home/src/api/LocalStorageVisitsApi.ts @@ -17,6 +17,14 @@ import { IdentityApi } from '@backstage/core-plugin-api'; import { Visit } from './VisitsApi'; import { VisitsApiFactory } from './VisitsApiFactory'; +/** @public */ +export type LocalStorageVisitsApiOptions = { + localStorage?: Window['localStorage']; + randomUUID?: Window['crypto']['randomUUID']; + limit?: number; + identityApi: IdentityApi; +}; + /** * @public * This is a reference implementation of VisitsApi using window.localStorage. @@ -26,17 +34,16 @@ export class LocalStorageVisitsApi extends VisitsApiFactory { private readonly storageKeyPrefix = '@backstage/plugin-home:visits'; private readonly identityApi: IdentityApi; - constructor({ + static create(options: LocalStorageVisitsApiOptions) { + return new LocalStorageVisitsApi(options); + } + + private constructor({ localStorage = window?.localStorage, randomUUID = window?.crypto?.randomUUID, limit = 100, identityApi, - }: { - localStorage?: Window['localStorage']; - randomUUID?: Window['crypto']['randomUUID']; - limit?: number; - identityApi: IdentityApi; - }) { + }: LocalStorageVisitsApiOptions) { super({ randomUUID, limit }); this.localStorage = localStorage; this.identityApi = identityApi; diff --git a/plugins/home/src/api/VisitsApiFactory.ts b/plugins/home/src/api/VisitsApiFactory.ts index ba3fe1fe3e..1b04c775a0 100644 --- a/plugins/home/src/api/VisitsApiFactory.ts +++ b/plugins/home/src/api/VisitsApiFactory.ts @@ -17,6 +17,14 @@ import { Visit, VisitsApi, VisitsApiQueryParams, VisitsApiSaveParams } from './V type ArrayElement = A extends readonly (infer T)[] ? T : never; +/** @public */ +export type VisitsApiFactoryOptions = { + randomUUID: Window['crypto']['randomUUID']; + limit: number; + retrieveAll?: () => Promise>; + persistAll?: (visits: Array) => Promise; +}; + /** * @public * This helps the creation of VisitApi implementations. Important to note @@ -30,17 +38,12 @@ export class VisitsApiFactory implements VisitsApi { protected retrieveAll: () => Promise>; protected persistAll: (visits: Array) => Promise; - constructor({ + protected constructor({ randomUUID = window?.crypto?.randomUUID, limit = 100, retrieveAll, persistAll, - }: { - randomUUID: Window['crypto']['randomUUID']; - limit: number; - retrieveAll?: () => Promise>; - persistAll?: (visits: Array) => Promise; - }) { + }: VisitsApiFactoryOptions) { this.randomUUID = randomUUID; this.limit = Math.abs(limit); this.retrieveAll = retrieveAll ?? (async () => []); @@ -59,6 +62,7 @@ export class VisitsApiFactory implements VisitsApi { } }); + // reversing order to guarantee filterBy priority (queryParams?.filterBy ?? []).reverse().forEach(filter => { visits = visits.filter(visit => { const field = visit[filter.field] as number | string;