From ce34320d919f8467bbdd9a58d85f4a643c690059 Mon Sep 17 00:00:00 2001 From: Andrew Thauer Date: Fri, 11 Nov 2022 07:14:43 -0500 Subject: [PATCH] fix api reports + create StaticExploreToolProvider Signed-off-by: Andrew Thauer --- packages/backend/package.json | 1 - packages/backend/src/plugins/explore.ts | 7 +- plugins/explore-backend/api-report.md | 8 ++ .../src/example/{tools.ts => exampleTools.ts} | 0 plugins/explore-backend/src/index.ts | 3 +- plugins/explore-backend/src/service/index.ts | 1 - .../src/service/router.test.ts | 3 +- plugins/explore-backend/src/service/router.ts | 2 +- plugins/explore-backend/src/tools/index.ts | 18 ++++ .../src/tools/providers.test.ts | 85 +++++++++++++++++++ .../getExampleTools.ts => tools/providers.ts} | 41 ++++++--- .../src/{service => tools}/types.ts | 0 plugins/explore/api-report.md | 46 ++++++++++ plugins/explore/src/api/types.ts | 3 + .../ToolExplorerContent.tsx | 5 ++ yarn.lock | 1 - 16 files changed, 200 insertions(+), 24 deletions(-) rename plugins/explore-backend/src/example/{tools.ts => exampleTools.ts} (100%) create mode 100644 plugins/explore-backend/src/tools/index.ts create mode 100644 plugins/explore-backend/src/tools/providers.test.ts rename plugins/explore-backend/src/{example/getExampleTools.ts => tools/providers.ts} (55%) rename plugins/explore-backend/src/{service => tools}/types.ts (100%) diff --git a/packages/backend/package.json b/packages/backend/package.json index 614de918e0..9b376fab67 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -44,7 +44,6 @@ "@backstage/plugin-events-backend": "workspace:^", "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-explore-backend": "workspace:^", - "@backstage/plugin-explore-common": "workspace:^", "@backstage/plugin-graphql-backend": "workspace:^", "@backstage/plugin-jenkins-backend": "workspace:^", "@backstage/plugin-kafka-backend": "workspace:^", diff --git a/packages/backend/src/plugins/explore.ts b/packages/backend/src/plugins/explore.ts index 6793213dd3..131f9461fa 100644 --- a/packages/backend/src/plugins/explore.ts +++ b/packages/backend/src/plugins/explore.ts @@ -16,7 +16,8 @@ import { createRouter, - getExampleTools, + exampleTools, + StaticExploreToolProvider, } from '@backstage/plugin-explore-backend'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; @@ -26,8 +27,6 @@ export default async function createPlugin( ): Promise { return await createRouter({ logger: env.logger, - toolProvider: { - getTools: getExampleTools, - }, + toolProvider: StaticExploreToolProvider.fromData(exampleTools), }); } diff --git a/plugins/explore-backend/api-report.md b/plugins/explore-backend/api-report.md index 89dd256cd9..cc112ed3cc 100644 --- a/plugins/explore-backend/api-report.md +++ b/plugins/explore-backend/api-report.md @@ -32,6 +32,14 @@ export interface RouterOptions { toolProvider: ExploreToolProvider; } +// @public +export class StaticExploreToolProvider implements ExploreToolProvider { + // (undocumented) + static fromData(tools: ExploreTool[]): StaticExploreToolProvider; + // (undocumented) + getTools(request: GetExploreToolsRequest): Promise; +} + // @public export interface ToolDocument extends IndexableDocument, ExploreTool {} diff --git a/plugins/explore-backend/src/example/tools.ts b/plugins/explore-backend/src/example/exampleTools.ts similarity index 100% rename from plugins/explore-backend/src/example/tools.ts rename to plugins/explore-backend/src/example/exampleTools.ts diff --git a/plugins/explore-backend/src/index.ts b/plugins/explore-backend/src/index.ts index ca0daaa8c4..a0e7216621 100644 --- a/plugins/explore-backend/src/index.ts +++ b/plugins/explore-backend/src/index.ts @@ -22,8 +22,9 @@ export * from './search'; export * from './service'; +export * from './tools'; /** * @internal Example only - do not use in production */ -export { getExampleTools } from './example/getExampleTools'; +export { exampleTools } from './example/exampleTools'; diff --git a/plugins/explore-backend/src/service/index.ts b/plugins/explore-backend/src/service/index.ts index 376a2bb98c..8727bd620b 100644 --- a/plugins/explore-backend/src/service/index.ts +++ b/plugins/explore-backend/src/service/index.ts @@ -16,4 +16,3 @@ export { createRouter } from './router'; export type { RouterOptions } from './router'; -export * from './types'; diff --git a/plugins/explore-backend/src/service/router.test.ts b/plugins/explore-backend/src/service/router.test.ts index 6f8a7b1110..5fe5b6c6a3 100644 --- a/plugins/explore-backend/src/service/router.test.ts +++ b/plugins/explore-backend/src/service/router.test.ts @@ -21,9 +21,8 @@ import { } from '@backstage/plugin-explore-common'; import express from 'express'; import request from 'supertest'; - +import { ExploreToolProvider } from '../tools'; import { createRouter } from './router'; -import { ExploreToolProvider } from './types'; const mockTools: ExploreTool[] = [ { title: 'Tool 1', url: 'https://example.com/tool1', image: '' }, diff --git a/plugins/explore-backend/src/service/router.ts b/plugins/explore-backend/src/service/router.ts index 22b5afbc87..393736529a 100644 --- a/plugins/explore-backend/src/service/router.ts +++ b/plugins/explore-backend/src/service/router.ts @@ -19,7 +19,7 @@ import { GetExploreToolsRequest } from '@backstage/plugin-explore-common'; import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; -import { ExploreToolProvider } from './types'; +import { ExploreToolProvider } from '../tools'; /** * @public diff --git a/plugins/explore-backend/src/tools/index.ts b/plugins/explore-backend/src/tools/index.ts new file mode 100644 index 0000000000..7c34ce56b8 --- /dev/null +++ b/plugins/explore-backend/src/tools/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { StaticExploreToolProvider } from './providers'; +export type { ExploreToolProvider } from './types'; diff --git a/plugins/explore-backend/src/tools/providers.test.ts b/plugins/explore-backend/src/tools/providers.test.ts new file mode 100644 index 0000000000..7a219e49fd --- /dev/null +++ b/plugins/explore-backend/src/tools/providers.test.ts @@ -0,0 +1,85 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ExploreTool } from '@backstage/plugin-explore-common'; +import { StaticExploreToolProvider } from './providers'; + +describe('StaticExploreToolProvider', () => { + const tool1: ExploreTool = { + title: 'Tool 1', + image: 'https://example/image.png', + url: 'https://example.com', + lifecycle: 'production', + tags: ['tag1', 'tag2'], + }; + const tool2: ExploreTool = { + ...tool1, + title: 'Tool 2', + lifecycle: 'production', + tags: ['tag1'], + }; + const tool3: ExploreTool = { + ...tool1, + title: 'Tool 3', + lifecycle: 'experimental', + tags: ['tag2'], + }; + const allTools: ExploreTool[] = [tool1, tool2, tool3]; + + describe('getTools', () => { + it('returns a list of all tools', async () => { + const provider = StaticExploreToolProvider.fromData(allTools); + + await expect(provider.getTools({})).resolves.toEqual({ + tools: allTools, + }); + }); + + it.each([ + [['tag1'], [tool1, tool2]], + [['tag2'], [tool1, tool3]], + [[], allTools], + ])( + 'returns % when filtered by tags %', + async (tagFilter, expectedTools) => { + const provider = StaticExploreToolProvider.fromData(allTools); + + await expect( + provider.getTools({ filter: { tags: tagFilter } }), + ).resolves.toEqual({ + tools: expectedTools, + }); + }, + ); + + it.each([ + [['production'], [tool1, tool2]], + [['experimental'], [tool3]], + [[], allTools], + ])( + 'returns % when filtered by lifecycle %', + async (lifecycleFilter, expectedTools) => { + const provider = StaticExploreToolProvider.fromData(allTools); + + await expect( + provider.getTools({ filter: { lifecycle: lifecycleFilter } }), + ).resolves.toEqual({ + tools: expectedTools, + }); + }, + ); + }); +}); diff --git a/plugins/explore-backend/src/example/getExampleTools.ts b/plugins/explore-backend/src/tools/providers.ts similarity index 55% rename from plugins/explore-backend/src/example/getExampleTools.ts rename to plugins/explore-backend/src/tools/providers.ts index 8d26c8073a..7a87824776 100644 --- a/plugins/explore-backend/src/example/getExampleTools.ts +++ b/plugins/explore-backend/src/tools/providers.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2022 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,12 @@ */ import { + ExploreTool, GetExploreToolsRequest, GetExploreToolsResponse, } from '@backstage/plugin-explore-common'; import { intersection, isEmpty } from 'lodash'; -import { exampleTools } from './tools'; +import { ExploreToolProvider } from './types'; const anyOf = (prop: T | T[], matches: T[]) => isEmpty(matches) @@ -27,18 +28,32 @@ const anyOf = (prop: T | T[], matches: T[]) => : intersection([...[prop]].flat(), matches)?.length > 0; /** - * @private Example only - do not use in production + * A basic ExploreToolProvider implementation using static data. + * + * @public */ -export async function getExampleTools( - request: GetExploreToolsRequest, -): Promise { - const { filter } = request ?? {}; - const tags = filter?.tags ?? []; - const lifecycles = filter?.lifecycle ?? []; +export class StaticExploreToolProvider implements ExploreToolProvider { + private readonly tools: ExploreTool[]; - return { - tools: exampleTools.filter( + static fromData(tools: ExploreTool[]) { + return new StaticExploreToolProvider(tools); + } + + private constructor(tools: ExploreTool[]) { + this.tools = tools; + } + + async getTools( + request: GetExploreToolsRequest, + ): Promise { + const { filter } = request ?? {}; + const tags = filter?.tags ?? []; + const lifecycles = filter?.lifecycle ?? []; + + const tools = this.tools.filter( t => anyOf(t.tags ?? [], tags) && anyOf(t.lifecycle ?? [], lifecycles), - ), - }; + ); + + return { tools }; + } } diff --git a/plugins/explore-backend/src/service/types.ts b/plugins/explore-backend/src/tools/types.ts similarity index 100% rename from plugins/explore-backend/src/service/types.ts rename to plugins/explore-backend/src/tools/types.ts diff --git a/plugins/explore/api-report.md b/plugins/explore/api-report.md index 9653c0fb63..6151f1ea0e 100644 --- a/plugins/explore/api-report.md +++ b/plugins/explore/api-report.md @@ -5,10 +5,18 @@ ```ts /// +import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { default as default_2 } from 'react'; +import { DiscoveryApi } from '@backstage/core-plugin-api'; import { DomainEntity } from '@backstage/catalog-model'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; +import { FetchApi } from '@backstage/core-plugin-api'; +import { GetExploreToolsRequest } from '@backstage/plugin-explore-common'; +import { GetExploreToolsResponse } from '@backstage/plugin-explore-common'; +import { IndexableDocument } from '@backstage/plugin-search-common'; +import { ReactNode } from 'react'; +import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; import { TabProps } from '@material-ui/core'; @@ -30,6 +38,27 @@ export const DomainExplorerContent: (props: { title?: string | undefined; }) => JSX.Element; +// @public +export interface ExploreApi { + getTools(request?: GetExploreToolsRequest): Promise; +} + +// @public (undocumented) +export const exploreApiRef: ApiRef; + +// @public +export class ExploreClient implements ExploreApi { + constructor({ + discoveryApi, + fetchApi, + }: { + discoveryApi: DiscoveryApi; + fetchApi: FetchApi; + }); + // (undocumented) + getTools(request?: GetExploreToolsRequest): Promise; +} + // @public export const ExploreLayout: { (props: ExploreLayoutProps): JSX.Element; @@ -91,4 +120,21 @@ export type SubRoute = { export const ToolExplorerContent: (props: { title?: string | undefined; }) => JSX.Element; + +// @public (undocumented) +export function ToolSearchResultListItem( + props: ToolSearchResultListItemProps, +): JSX.Element; + +// @public +export interface ToolSearchResultListItemProps { + // (undocumented) + highlight?: ResultHighlight; + // (undocumented) + icon?: ReactNode; + // (undocumented) + rank?: number; + // (undocumented) + result: IndexableDocument; +} ``` diff --git a/plugins/explore/src/api/types.ts b/plugins/explore/src/api/types.ts index 0d9eb4ac07..ef9eb646b7 100644 --- a/plugins/explore/src/api/types.ts +++ b/plugins/explore/src/api/types.ts @@ -34,6 +34,9 @@ export interface ExploreApi { getTools(request?: GetExploreToolsRequest): Promise; } +/** + * @public + */ export const exploreApiRef = createApiRef({ id: 'plugin.explore.service', }); diff --git a/plugins/explore/src/components/ToolExplorerContent/ToolExplorerContent.tsx b/plugins/explore/src/components/ToolExplorerContent/ToolExplorerContent.tsx index 5404c67393..3e26cab857 100644 --- a/plugins/explore/src/components/ToolExplorerContent/ToolExplorerContent.tsx +++ b/plugins/explore/src/components/ToolExplorerContent/ToolExplorerContent.tsx @@ -28,15 +28,20 @@ import { WarningPanel, } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; +// import { exploreApiRef } from '../../api'; const Body = () => { const exploreToolsConfigApi = useApi(exploreToolsConfigRef); + // const exploreApi = useApi(exploreApiRef); + const { value: tools, loading, error, } = useAsync(async () => { return await exploreToolsConfigApi.getTools(); + // TODO: Enable the backend ExploreClient + // return (await exploreApi.getTools())?.tools; }, [exploreToolsConfigApi]); if (loading) { diff --git a/yarn.lock b/yarn.lock index fe3feb9581..0f9031d749 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21902,7 +21902,6 @@ __metadata: "@backstage/plugin-events-backend": "workspace:^" "@backstage/plugin-events-node": "workspace:^" "@backstage/plugin-explore-backend": "workspace:^" - "@backstage/plugin-explore-common": "workspace:^" "@backstage/plugin-graphql-backend": "workspace:^" "@backstage/plugin-jenkins-backend": "workspace:^" "@backstage/plugin-kafka-backend": "workspace:^"