From e35b13afa9e0c9a7a8865df769cc9086b84a31ba Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Tue, 13 Jul 2021 17:17:46 +0200 Subject: [PATCH 1/2] Handle error responses in `getTechDocsMetadata` and `getEntityMetadata` such that `` doesn't throw errors. Signed-off-by: Dominik Henneke --- .changeset/techdocs-young-gorillas-share.md | 5 +++++ plugins/techdocs/src/client.ts | 16 +++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 .changeset/techdocs-young-gorillas-share.md diff --git a/.changeset/techdocs-young-gorillas-share.md b/.changeset/techdocs-young-gorillas-share.md new file mode 100644 index 0000000000..6b1d3f03da --- /dev/null +++ b/.changeset/techdocs-young-gorillas-share.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Handle error responses in `getTechDocsMetadata` and `getEntityMetadata` such that `` doesn't throw errors. diff --git a/plugins/techdocs/src/client.ts b/plugins/techdocs/src/client.ts index afbf4b74a0..f867ce4011 100644 --- a/plugins/techdocs/src/client.ts +++ b/plugins/techdocs/src/client.ts @@ -17,7 +17,7 @@ import { EntityName } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; -import { NotFoundError } from '@backstage/errors'; +import { NotFoundError, ResponseError } from '@backstage/errors'; import EventSource from 'eventsource'; import { SyncResult, TechDocsApi, TechDocsStorageApi } from './api'; import { TechDocsEntityMetadata, TechDocsMetadata } from './types'; @@ -72,9 +72,12 @@ export class TechDocsClient implements TechDocsApi { const request = await fetch(`${requestUrl}`, { headers: token ? { Authorization: `Bearer ${token}` } : {}, }); - const res = await request.json(); - return res; + if (!request.ok) { + throw await ResponseError.fromResponse(request); + } + + return await request.json(); } /** @@ -97,9 +100,12 @@ export class TechDocsClient implements TechDocsApi { const request = await fetch(`${requestUrl}`, { headers: token ? { Authorization: `Bearer ${token}` } : {}, }); - const res = await request.json(); - return res; + if (!request.ok) { + throw await ResponseError.fromResponse(request); + } + + return await request.json(); } } From 9ed3d401c8f04e42e536150ef84c67e7f266662d Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Tue, 13 Jul 2021 17:21:27 +0200 Subject: [PATCH 2/2] Refactor `` to not use `AsyncState` as inputs Signed-off-by: Dominik Henneke --- plugins/techdocs/api-report.md | 2 +- .../src/reader/components/TechDocsPage.tsx | 10 ++-- .../components/TechDocsPageHeader.test.tsx | 55 ++++++------------- .../reader/components/TechDocsPageHeader.tsx | 37 ++++--------- plugins/techdocs/src/types.ts | 6 +- 5 files changed, 39 insertions(+), 71 deletions(-) diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index d63303c134..10e338c89a 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -13,7 +13,7 @@ import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { EntityName } from '@backstage/catalog-model'; import { IdentityApi } from '@backstage/core-plugin-api'; -import { Location as Location_2 } from '@backstage/catalog-model'; +import { LocationSpec } from '@backstage/catalog-model'; import { RouteRef } from '@backstage/core-plugin-api'; // Warning: (ae-missing-release-tag) "DocsCardGrid" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/techdocs/src/reader/components/TechDocsPage.tsx b/plugins/techdocs/src/reader/components/TechDocsPage.tsx index 88c53a38a7..19092f47c3 100644 --- a/plugins/techdocs/src/reader/components/TechDocsPage.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsPage.tsx @@ -30,7 +30,7 @@ export const TechDocsPage = () => { const techdocsApi = useApi(techdocsApiRef); - const techdocsMetadataRequest = useAsync(() => { + const { value: techdocsMetadataValue } = useAsync(() => { if (documentReady) { return techdocsApi.getTechDocsMetadata({ kind, namespace, name }); } @@ -38,7 +38,7 @@ export const TechDocsPage = () => { return Promise.resolve(undefined); }, [kind, namespace, name, techdocsApi, documentReady]); - const entityMetadataRequest = useAsync(() => { + const { value: entityMetadataValue } = useAsync(() => { return techdocsApi.getEntityMetadata({ kind, namespace, name }); }, [kind, namespace, name, techdocsApi]); @@ -49,10 +49,8 @@ export const TechDocsPage = () => { return ( ', () => { name: 'test-name', namespace: 'test-namespace', }} - metadataRequest={{ - entity: { - loading: false, - value: { - locationMetadata: { - type: 'github', - target: 'https://example.com/', - }, - spec: { - owner: 'test', - }, - }, + entityMetadata={{ + locationMetadata: { + type: 'github', + target: 'https://example.com/', }, - techdocs: { - loading: false, - value: { - site_name: 'test-site-name', - site_description: 'test-site-desc', - }, + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'test', }, + spec: { + owner: 'test', + }, + }} + techDocsMetadata={{ + site_name: 'test-site-name', + site_description: 'test-site-desc', }} />, { @@ -75,14 +72,6 @@ describe('', () => { name: 'test-name', namespace: 'test-namespace', }} - metadataRequest={{ - entity: { - loading: false, - }, - techdocs: { - loading: false, - }, - }} />, { mountedRoutes: { @@ -105,17 +94,9 @@ describe('', () => { name: 'test-name', namespace: 'test-namespace', }} - metadataRequest={{ - entity: { - loading: false, - }, - techdocs: { - loading: false, - value: { - site_name: 'test-site-name', - site_description: 'test-site-desc', - }, - }, + techDocsMetadata={{ + site_name: 'test-site-name', + site_description: 'test-site-desc', }} />, { diff --git a/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx b/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx index 38e122e9cb..34d564bdfe 100644 --- a/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx @@ -15,6 +15,8 @@ */ import { EntityName, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { Header, HeaderLabel } from '@backstage/core-components'; +import { useRouteRef } from '@backstage/core-plugin-api'; import { EntityRefLink, EntityRefLinks, @@ -22,45 +24,30 @@ import { } from '@backstage/plugin-catalog-react'; import CodeIcon from '@material-ui/icons/Code'; import React from 'react'; -import { AsyncState } from 'react-use/lib/useAsync'; import { rootRouteRef } from '../../routes'; -import { TechDocsMetadata } from '../../types'; - -import { Header, HeaderLabel } from '@backstage/core-components'; -import { useRouteRef } from '@backstage/core-plugin-api'; +import { TechDocsEntityMetadata, TechDocsMetadata } from '../../types'; type TechDocsPageHeaderProps = { entityId: EntityName; - metadataRequest: { - entity: AsyncState; - techdocs: AsyncState; - }; + entityMetadata?: TechDocsEntityMetadata; + techDocsMetadata?: TechDocsMetadata; }; export const TechDocsPageHeader = ({ entityId, - metadataRequest, + entityMetadata, + techDocsMetadata, }: TechDocsPageHeaderProps) => { - const { - techdocs: techdocsMetadata, - entity: entityMetadata, - } = metadataRequest; - - const { value: techdocsMetadataValues } = techdocsMetadata; - const { value: entityMetadataValues } = entityMetadata; - const { name } = entityId; const { site_name: siteName, site_description: siteDescription } = - techdocsMetadataValues || {}; + techDocsMetadata || {}; - const { - locationMetadata, - spec: { lifecycle }, - } = entityMetadataValues || { spec: {} }; + const { locationMetadata, spec } = entityMetadata || {}; + const lifecycle = spec?.lifecycle; - const ownedByRelations = entityMetadataValues - ? getEntityRelations(entityMetadataValues, RELATION_OWNED_BY) + const ownedByRelations = entityMetadata + ? getEntityRelations(entityMetadata, RELATION_OWNED_BY) : []; const docsRootLink = useRouteRef(rootRouteRef)(); diff --git a/plugins/techdocs/src/types.ts b/plugins/techdocs/src/types.ts index f6d849b426..dd35e255b6 100644 --- a/plugins/techdocs/src/types.ts +++ b/plugins/techdocs/src/types.ts @@ -14,11 +14,13 @@ * limitations under the License. */ -import { Entity, Location } from '@backstage/catalog-model'; +import { Entity, LocationSpec } from '@backstage/catalog-model'; export type TechDocsMetadata = { site_name: string; site_description: string; }; -export type TechDocsEntityMetadata = Entity & { locationMetadata?: Location }; +export type TechDocsEntityMetadata = Entity & { + locationMetadata?: LocationSpec; +};